<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>奋飞安全</title>
    <link>http://91fans.com.cn/</link>
    <description>Recent content on 奋飞安全</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>zh-cn</language>
    <lastBuildDate>Wed, 22 Apr 2026 12:00:00 +0800</lastBuildDate>
    
        <atom:link href="http://91fans.com.cn/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>关于奋飞</title>
      <link>http://91fans.com.cn/about/</link>
      <pubDate>Mon, 01 Jul 2019 21:38:52 +0800</pubDate>
      
      <guid>http://91fans.com.cn/about/</guid>
      
        <description>&lt;meta charset=&#34;UTF-8&#34;/&gt;&lt;meta http-equiv=&#34;X-UA-Compatible&#34; content=&#34;IE=edge&#34;/&gt;&lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;/&gt;&lt;meta name=&#34;generator&#34; content=&#34;Asciidoctor 2.0.20&#34;/&gt;&lt;title&gt;Untitled&lt;/title&gt;&lt;style&gt;/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import &#34;https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700&#34;; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:&#34;\201C&#34; &#34;\201D&#34; &#34;\2018&#34; &#34;\2019&#34;}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock&gt;.content&gt;.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock&gt;.content&gt;.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:&#34; &#34;;display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])&gt;code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre&gt;code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:&#34;[&#34;;padding:0 3px 0 2px}
b.button::after{content:&#34;]&#34;;padding:0 2px 0 3px}
p a&gt;code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:&#34; &#34;;display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header&gt;h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header&gt;h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header&gt;h1:only-child,body.toc2 #header&gt;h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:&#34;\00a0\2013\00a0&#34;}
#header .details br+span.author::before{content:&#34;\00a0\22c5\00a0&#34;;color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:&#34;\00a0|\00a0&#34;}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:&#34;\00a0&#34;}
#content&gt;h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc&gt;ul{margin-left:.125em}
#toc ul.sectlevel0&gt;li&gt;a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2&gt;ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2&gt;ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc&gt;:first-child{margin-top:0}
#content #toc&gt;:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1&gt;a.anchor,h2&gt;a.anchor,h3&gt;a.anchor,#toctitle&gt;a.anchor,.sidebarblock&gt;.content&gt;.title&gt;a.anchor,h4&gt;a.anchor,h5&gt;a.anchor,h6&gt;a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1&gt;a.anchor::before,h2&gt;a.anchor::before,h3&gt;a.anchor::before,#toctitle&gt;a.anchor::before,.sidebarblock&gt;.content&gt;.title&gt;a.anchor::before,h4&gt;a.anchor::before,h5&gt;a.anchor::before,h6&gt;a.anchor::before{content:&#34;\00A7&#34;;font-size:.85em;display:block;padding-top:.1em}
#content h1:hover&gt;a.anchor,#content h1&gt;a.anchor:hover,h2:hover&gt;a.anchor,h2&gt;a.anchor:hover,h3:hover&gt;a.anchor,#toctitle:hover&gt;a.anchor,.sidebarblock&gt;.content&gt;.title:hover&gt;a.anchor,h3&gt;a.anchor:hover,#toctitle&gt;a.anchor:hover,.sidebarblock&gt;.content&gt;.title&gt;a.anchor:hover,h4:hover&gt;a.anchor,h4&gt;a.anchor:hover,h5:hover&gt;a.anchor,h5&gt;a.anchor:hover,h6:hover&gt;a.anchor,h6&gt;a.anchor:hover{visibility:visible}
#content h1&gt;a.link,h2&gt;a.link,h3&gt;a.link,#toctitle&gt;a.link,.sidebarblock&gt;.content&gt;.title&gt;a.link,h4&gt;a.link,h5&gt;a.link,h6&gt;a.link{color:#ba3925;text-decoration:none}
#content h1&gt;a.link:hover,h2&gt;a.link:hover,h3&gt;a.link:hover,#toctitle&gt;a.link:hover,.sidebarblock&gt;.content&gt;.title&gt;a.link:hover,h4&gt;a.link:hover,h5&gt;a.link:hover,h6&gt;a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details&gt;summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details&gt;summary::-webkit-details-marker{display:none}
details&gt;summary::before{content:&#34;&#34;;border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]&gt;summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details&gt;summary::after{content:&#34;&#34;;width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{text-rendering:optimizeLegibility;text-align:left;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content&gt;caption.title{white-space:nowrap;width:0}
.paragraph.lead&gt;p,#preamble&gt;.sectionbody&gt;[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock&gt;table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock&gt;table td.icon{text-align:center;width:80px}
.admonitionblock&gt;table td.icon img{max-width:none}
.admonitionblock&gt;table td.icon .title{font-weight:bold;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;text-transform:uppercase}
.admonitionblock&gt;table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock&gt;table td.content&gt;:last-child&gt;:last-child{margin-bottom:0}
.exampleblock&gt;.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock&gt;.content&gt;.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock&gt;.content&gt;:first-child,.sidebarblock&gt;.content&gt;:first-child{margin-top:0}
.exampleblock&gt;.content&gt;:last-child,.exampleblock&gt;.content&gt;:last-child&gt;:last-child,.exampleblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child&gt;:last-child,.sidebarblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child{margin-bottom:0}
.literalblock pre,.listingblock&gt;.content&gt;pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:1em}}
.literalblock pre,.listingblock&gt;.content&gt;pre:not(.highlight),.listingblock&gt;.content&gt;pre[class=highlight],.listingblock&gt;.content&gt;pre[class^=&#34;highlight &#34;]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock&gt;.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:&#34;$&#34;}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs&gt;code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)&gt;.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:&#34;\201c&#34;;float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote&gt;.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract&gt;.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt&gt;blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock&gt;.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock&gt;.content&gt;:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all&gt;*&gt;tr&gt;*{border-width:1px}
table.grid-cols&gt;*&gt;tr&gt;*{border-width:0 1px}
table.grid-rows&gt;*&gt;tr&gt;*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none&gt;colgroup+*&gt;:first-child&gt;*,table.frame-sides&gt;colgroup+*&gt;:first-child&gt;*{border-top-width:0}
table.frame-none&gt;:last-child&gt;:last-child&gt;*,table.frame-sides&gt;:last-child&gt;:last-child&gt;*{border-bottom-width:0}
table.frame-none&gt;*&gt;tr&gt;:first-child,table.frame-ends&gt;*&gt;tr&gt;:first-child{border-left-width:0}
table.frame-none&gt;*&gt;tr&gt;:last-child,table.frame-ends&gt;*&gt;tr&gt;:last-child{border-right-width:0}
table.stripes-all&gt;*&gt;tr,table.stripes-odd&gt;*&gt;tr:nth-of-type(odd),table.stripes-even&gt;*&gt;tr:nth-of-type(even),table.stripes-hover&gt;*&gt;tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock&gt;code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child&gt;:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li&gt;p:empty:only-child::before{content:&#34;&#34;;display:inline-block}
ul.checklist&gt;li&gt;p:first-child{margin-left:-1em}
ul.checklist&gt;li&gt;p:first-child&gt;.fa-square-o:first-child,ul.checklist&gt;li&gt;p:first-child&gt;.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist&gt;li&gt;p:first-child&gt;input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline&gt;li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist&gt;table,.colist&gt;table{border:0;background:none}
.hdlist&gt;table&gt;tbody&gt;tr,.colist&gt;table&gt;tbody&gt;tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock&gt;.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb&gt;.title,.imageblock.th&gt;.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon&gt;.fa{cursor:default}
a span.icon&gt;.fa{cursor:inherit}
.admonitionblock td.icon [class^=&#34;fa icon-&#34;]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:&#34;\f05a&#34;;color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:&#34;\f0eb&#34;;text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:&#34;\f071&#34;;color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:&#34;\f06d&#34;;color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:&#34;\f06a&#34;;color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock&gt;.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^=&#34;#&#34;],a[href^=&#34;mailto:&#34;]{text-decoration:none!important}
a[href^=&#34;http:&#34;]:not(.bare)::after,a[href^=&#34;https:&#34;]:not(.bare)::after{content:&#34;(&#34; attr(href) &#34;)&#34;;display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:&#34; (&#34; attr(title) &#34;)&#34;}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock&gt;.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header&gt;h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1&gt;h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header&gt;h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}&lt;/style&gt;&lt;/head&gt;&lt;body class=&#34;article&#34;&gt;&lt;header&gt;&lt;/header&gt;&lt;div id=&#34;content&#34;&gt;&lt;figure class=&#34;image-block&#34; style=&#34;text-align: center;&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ffwx.jpeg&#34; alt=&#34;ffwx&#34;/&gt;
&lt;figcaption&gt;奋飞微信号：fenfei331&lt;/figcaption&gt;&lt;/figure&gt;
&lt;aside class=&#34;sidebar&#34;&gt;&lt;h6 class=&#34;block-title&#34;&gt;关于奋飞&lt;/h6&gt;&lt;p&gt;奋飞，国家高级信息系统项目管理师，独立安全研究员。
c/c++/asm/go/python&lt;/p&gt;
&lt;p&gt;少习文，经史子集略有涉猎；北上学艺，A-Z语言敢说略懂；初入江湖，混入外企，乐不思蜀；后为人父，发愤图强，略有建树；而今重新出发，万事随缘。&lt;/p&gt;&lt;/aside&gt;&lt;/div&gt;&lt;footer&gt;&lt;div id=&#34;footer-text&#34;&gt;&lt;br/&gt;Last updated 2026-04-27 18:48:41 +0800&lt;/div&gt;&lt;/footer&gt;
</description>
      
    </item>
    
    <item>
      <title>精华导航</title>
      <link>http://91fans.com.cn/navigator/</link>
      <pubDate>Mon, 01 Jul 2019 21:38:52 +0800</pubDate>
      
      <guid>http://91fans.com.cn/navigator/</guid>
      
        <description>&lt;meta charset=&#34;UTF-8&#34;/&gt;&lt;meta http-equiv=&#34;X-UA-Compatible&#34; content=&#34;IE=edge&#34;/&gt;&lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;/&gt;&lt;meta name=&#34;generator&#34; content=&#34;Asciidoctor 2.0.20&#34;/&gt;&lt;title&gt;第一章 实例操练&lt;/title&gt;&lt;style&gt;/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import &#34;https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700&#34;; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:&#34;\201C&#34; &#34;\201D&#34; &#34;\2018&#34; &#34;\2019&#34;}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock&gt;.content&gt;.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock&gt;.content&gt;.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:&#34; &#34;;display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])&gt;code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre&gt;code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:&#34;[&#34;;padding:0 3px 0 2px}
b.button::after{content:&#34;]&#34;;padding:0 2px 0 3px}
p a&gt;code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:&#34; &#34;;display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header&gt;h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header&gt;h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header&gt;h1:only-child,body.toc2 #header&gt;h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:&#34;\00a0\2013\00a0&#34;}
#header .details br+span.author::before{content:&#34;\00a0\22c5\00a0&#34;;color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:&#34;\00a0|\00a0&#34;}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:&#34;\00a0&#34;}
#content&gt;h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc&gt;ul{margin-left:.125em}
#toc ul.sectlevel0&gt;li&gt;a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2&gt;ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2&gt;ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc&gt;:first-child{margin-top:0}
#content #toc&gt;:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1&gt;a.anchor,h2&gt;a.anchor,h3&gt;a.anchor,#toctitle&gt;a.anchor,.sidebarblock&gt;.content&gt;.title&gt;a.anchor,h4&gt;a.anchor,h5&gt;a.anchor,h6&gt;a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1&gt;a.anchor::before,h2&gt;a.anchor::before,h3&gt;a.anchor::before,#toctitle&gt;a.anchor::before,.sidebarblock&gt;.content&gt;.title&gt;a.anchor::before,h4&gt;a.anchor::before,h5&gt;a.anchor::before,h6&gt;a.anchor::before{content:&#34;\00A7&#34;;font-size:.85em;display:block;padding-top:.1em}
#content h1:hover&gt;a.anchor,#content h1&gt;a.anchor:hover,h2:hover&gt;a.anchor,h2&gt;a.anchor:hover,h3:hover&gt;a.anchor,#toctitle:hover&gt;a.anchor,.sidebarblock&gt;.content&gt;.title:hover&gt;a.anchor,h3&gt;a.anchor:hover,#toctitle&gt;a.anchor:hover,.sidebarblock&gt;.content&gt;.title&gt;a.anchor:hover,h4:hover&gt;a.anchor,h4&gt;a.anchor:hover,h5:hover&gt;a.anchor,h5&gt;a.anchor:hover,h6:hover&gt;a.anchor,h6&gt;a.anchor:hover{visibility:visible}
#content h1&gt;a.link,h2&gt;a.link,h3&gt;a.link,#toctitle&gt;a.link,.sidebarblock&gt;.content&gt;.title&gt;a.link,h4&gt;a.link,h5&gt;a.link,h6&gt;a.link{color:#ba3925;text-decoration:none}
#content h1&gt;a.link:hover,h2&gt;a.link:hover,h3&gt;a.link:hover,#toctitle&gt;a.link:hover,.sidebarblock&gt;.content&gt;.title&gt;a.link:hover,h4&gt;a.link:hover,h5&gt;a.link:hover,h6&gt;a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details&gt;summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details&gt;summary::-webkit-details-marker{display:none}
details&gt;summary::before{content:&#34;&#34;;border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]&gt;summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details&gt;summary::after{content:&#34;&#34;;width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{text-rendering:optimizeLegibility;text-align:left;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content&gt;caption.title{white-space:nowrap;width:0}
.paragraph.lead&gt;p,#preamble&gt;.sectionbody&gt;[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock&gt;table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock&gt;table td.icon{text-align:center;width:80px}
.admonitionblock&gt;table td.icon img{max-width:none}
.admonitionblock&gt;table td.icon .title{font-weight:bold;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;text-transform:uppercase}
.admonitionblock&gt;table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock&gt;table td.content&gt;:last-child&gt;:last-child{margin-bottom:0}
.exampleblock&gt;.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock&gt;.content&gt;.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock&gt;.content&gt;:first-child,.sidebarblock&gt;.content&gt;:first-child{margin-top:0}
.exampleblock&gt;.content&gt;:last-child,.exampleblock&gt;.content&gt;:last-child&gt;:last-child,.exampleblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child&gt;:last-child,.sidebarblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child{margin-bottom:0}
.literalblock pre,.listingblock&gt;.content&gt;pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:1em}}
.literalblock pre,.listingblock&gt;.content&gt;pre:not(.highlight),.listingblock&gt;.content&gt;pre[class=highlight],.listingblock&gt;.content&gt;pre[class^=&#34;highlight &#34;]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock&gt;.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:&#34;$&#34;}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs&gt;code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)&gt;.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:&#34;\201c&#34;;float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote&gt;.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract&gt;.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt&gt;blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock&gt;.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock&gt;.content&gt;:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all&gt;*&gt;tr&gt;*{border-width:1px}
table.grid-cols&gt;*&gt;tr&gt;*{border-width:0 1px}
table.grid-rows&gt;*&gt;tr&gt;*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none&gt;colgroup+*&gt;:first-child&gt;*,table.frame-sides&gt;colgroup+*&gt;:first-child&gt;*{border-top-width:0}
table.frame-none&gt;:last-child&gt;:last-child&gt;*,table.frame-sides&gt;:last-child&gt;:last-child&gt;*{border-bottom-width:0}
table.frame-none&gt;*&gt;tr&gt;:first-child,table.frame-ends&gt;*&gt;tr&gt;:first-child{border-left-width:0}
table.frame-none&gt;*&gt;tr&gt;:last-child,table.frame-ends&gt;*&gt;tr&gt;:last-child{border-right-width:0}
table.stripes-all&gt;*&gt;tr,table.stripes-odd&gt;*&gt;tr:nth-of-type(odd),table.stripes-even&gt;*&gt;tr:nth-of-type(even),table.stripes-hover&gt;*&gt;tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock&gt;code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child&gt;:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li&gt;p:empty:only-child::before{content:&#34;&#34;;display:inline-block}
ul.checklist&gt;li&gt;p:first-child{margin-left:-1em}
ul.checklist&gt;li&gt;p:first-child&gt;.fa-square-o:first-child,ul.checklist&gt;li&gt;p:first-child&gt;.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist&gt;li&gt;p:first-child&gt;input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline&gt;li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist&gt;table,.colist&gt;table{border:0;background:none}
.hdlist&gt;table&gt;tbody&gt;tr,.colist&gt;table&gt;tbody&gt;tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock&gt;.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb&gt;.title,.imageblock.th&gt;.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon&gt;.fa{cursor:default}
a span.icon&gt;.fa{cursor:inherit}
.admonitionblock td.icon [class^=&#34;fa icon-&#34;]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:&#34;\f05a&#34;;color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:&#34;\f0eb&#34;;text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:&#34;\f071&#34;;color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:&#34;\f06d&#34;;color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:&#34;\f06a&#34;;color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock&gt;.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^=&#34;#&#34;],a[href^=&#34;mailto:&#34;]{text-decoration:none!important}
a[href^=&#34;http:&#34;]:not(.bare)::after,a[href^=&#34;https:&#34;]:not(.bare)::after{content:&#34;(&#34; attr(href) &#34;)&#34;;display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:&#34; (&#34; attr(title) &#34;)&#34;}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock&gt;.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header&gt;h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1&gt;h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header&gt;h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}&lt;/style&gt;&lt;/head&gt;&lt;body class=&#34;article&#34;&gt;&lt;header&gt;&lt;/header&gt;&lt;div id=&#34;content&#34;&gt;&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_第一章_实例操练&#34;&gt;第一章 实例操练&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_1android_app操练&#34;&gt;1、Android App操练&lt;/h3&gt;&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_1_1_签名类&#34;&gt;1.1、 签名类&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_1_某电商app签名算法解析一_重点是找sign的思路&#34;&gt;1.1.1、 &lt;a href=&#34;http://91fans.com.cn/post/jdsignone/&#34;&gt;某电商App签名算法解析(一)  重点是找sign的思路&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_2_某电商app签名算法解析二&#34;&gt;1.1.2、 &lt;a href=&#34;http://91fans.com.cn/post/jdsigntwo/&#34;&gt;某电商App签名算法解析(二)&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_3_androidnativeemu模拟执行计算出某电商app_sign&#34;&gt;1.1.3、 &lt;a href=&#34;http://91fans.com.cn/post/liudqsign/&#34;&gt;AndroidNativeEmu模拟执行计算出某电商App sign&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_4_某种草电商app签名算法解析一&#34;&gt;1.1.4、 &lt;a href=&#34;http://91fans.com.cn/post/addgrass/&#34;&gt;某种草电商App签名算法解析(一)&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_5_某生鲜app签名算法解析一&#34;&gt;1.1.5、 &lt;a href=&#34;http://91fans.com.cn/post/vegetablesone/&#34;&gt;某生鲜App签名算法解析(一)&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_6_某生活服务app返回数据密文解析一_android_device_monitor定位&#34;&gt;1.1.6、 &lt;a href=&#34;http://91fans.com.cn/post/lifeserviceone/&#34;&gt;某生活服务App返回数据密文解析(一) Android Device Monitor定位&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_7_某生活服务app请求数据密文解析二_从base64说起&#34;&gt;1.1.7、 &lt;a href=&#34;http://91fans.com.cn/post/lifeservicetwo/&#34;&gt;某生活服务App请求数据密文解析(二) 从Base64说起&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_8_某站app签名算法解析一&#34;&gt;1.1.8、 &lt;a href=&#34;http://91fans.com.cn/post/bilibilione/&#34;&gt;某站App签名算法解析(一)&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_9_某段子app签名计算方法一&#34;&gt;1.1.9、 &lt;a href=&#34;http://91fans.com.cn/post/zysignone/&#34;&gt;某段子App签名计算方法(一)&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_10_某段子app协议分析二&#34;&gt;1.1.10、 &lt;a href=&#34;http://91fans.com.cn/post/zysigntwo/&#34;&gt;某段子App协议分析(二)&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_11_某小视频app_v8_x_签名计算方法一_先从抓包说起&#34;&gt;1.1.11、 &lt;a href=&#34;http://91fans.com.cn/post/smallvideosignone/&#34;&gt;某小视频App v8.x 签名计算方法(一) 先从抓包说起&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_12_某小视频app_v8_x_签名计算方法二_sig和_ns_sig3&#34;&gt;1.1.12、 &lt;a href=&#34;http://91fans.com.cn/post/smallvideosigntwo/&#34;&gt;某小视频App v8.x 签名计算方法(二) sig和__NS_sig3&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_12_1_某小视频app_v10_x_手机号加密算法分析&#34;&gt;1.1.12.1、 &lt;a href=&#34;http://91fans.com.cn/post/smallvideosignthr/&#34;&gt;某小视频App v10.x 手机号加密算法分析&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_13_某电商app_anti_token_签名计算方法_学学objection&#34;&gt;1.1.13、 &lt;a href=&#34;http://91fans.com.cn/post/pxxone/&#34;&gt;某电商App anti-token 签名计算方法 学学objection&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_14_某电商app_sign签名算法解析_内部类的hook&#34;&gt;1.1.14、 &lt;a href=&#34;http://91fans.com.cn/post/dsbuysignone/&#34;&gt;某电商App Sign签名算法解析 内部类的Hook&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_15_某二手电商app_x_sign签名分析_类成员变量的分析&#34;&gt;1.1.15、 &lt;a href=&#34;http://91fans.com.cn/post/idlesignone/&#34;&gt;某二手电商App x-sign签名分析 类成员变量的分析&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_16_某影评书评社区app_sig签名分析&#34;&gt;1.1.16、 &lt;a href=&#34;http://91fans.com.cn/post/frodosignone/&#34;&gt;某影评书评社区App _sig签名分析&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_17_某汽车资讯app_返回数据解密&#34;&gt;1.1.17、 &lt;a href=&#34;http://91fans.com.cn/post/secondcartextone/&#34;&gt;某汽车资讯App 返回数据解密&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_18_某搬家app_sign签名算法解析&#34;&gt;1.1.18、 &lt;a href=&#34;http://91fans.com.cn/post/banjiasignone/&#34;&gt;某搬家App _sign签名算法解析&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_19_某足球资讯app_sign签名算法解析&#34;&gt;1.1.19、 &lt;a href=&#34;http://91fans.com.cn/post/footballsignone/&#34;&gt;某足球资讯App sign签名算法解析&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_20_搞个大点的_某团购app_mtgsig&#34;&gt;1.1.20、 &lt;a href=&#34;http://91fans.com.cn/post/mtgsigone/&#34;&gt;搞个大点的 某团购App mtgsig&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_21_中华ps_app_sig签名分析&#34;&gt;1.1.21、 &lt;a href=&#34;http://91fans.com.cn/post/mtssone/&#34;&gt;中华PS App sig签名分析&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_22_某潮牌电商app_newsign签名分析&#34;&gt;1.1.22、 &lt;a href=&#34;http://91fans.com.cn/post/cpdsone/&#34;&gt;某潮牌电商App newSign签名分析&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_23_某资讯app_signature签名分析_一&#34;&gt;1.1.23、 &lt;a href=&#34;http://91fans.com.cn/post/onenewsone/&#34;&gt;某资讯App signature签名分析 (一)&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_24_再搞个大点的_某小视频app_x_gorgon_分析&#34;&gt;1.1.24、 &lt;a href=&#34;http://91fans.com.cn/post/smallvideoexone/&#34;&gt;再搞个大点的 某小视频App X-Gorgon 分析&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_25_某社交app_cs签名算法解析一_ssl双向认证&#34;&gt;1.1.25、 &lt;a href=&#34;http://91fans.com.cn/post/socialsignone/&#34;&gt;某社交App cs签名算法解析(一) SSL双向认证&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_26_某社交app_cs签名算法解析二_都是套路&#34;&gt;1.1.26、 &lt;a href=&#34;http://91fans.com.cn/post/socialsigntwo/&#34;&gt;某社交App cs签名算法解析(二) 都是套路&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_27_某nft交易平台app_wtoken分析&#34;&gt;1.1.27、 &lt;a href=&#34;http://91fans.com.cn/post/iboxone/&#34;&gt;某NFT交易平台App wtoken分析&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_1_2so直接调用&#34;&gt;1.2、so直接调用&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_2_1_借鸡生蛋之sandhook的使用一&#34;&gt;1.2.1、 &lt;a href=&#34;http://91fans.com.cn/post/loadsoone/&#34;&gt;借鸡生蛋之SandHook的使用(一)&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_2_2_借鸡生蛋之某电商app签名so的使用二&#34;&gt;1.2.2、 &lt;a href=&#34;http://91fans.com.cn/post/loadsotwo/&#34;&gt;借鸡生蛋之某电商App签名so的使用(二)&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_2_3_借鸡生蛋之某电商app签名so的使用三&#34;&gt;1.2.3、 &lt;a href=&#34;http://91fans.com.cn/post/loadsothr/&#34;&gt;借鸡生蛋之某电商App签名so的使用(三)&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_1_3_rpc调用&#34;&gt;1.3、 RPC调用&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_3_1_frida_flask_rpc调用&#34;&gt;1.3.1、 &lt;a href=&#34;http://91fans.com.cn/post/zysignthr/&#34;&gt;frida + Flask rpc调用&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_3_2_xposed_nanohttpd_rpc调用&#34;&gt;1.3.2、 &lt;a href=&#34;http://91fans.com.cn/post/zysignfour/&#34;&gt;Xposed + NanoHTTPD rpc调用&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_3_3_android连真机签名公网ip更新方案&#34;&gt;1.3.3、 &lt;a href=&#34;http://91fans.com.cn/post/androidipsend/&#34;&gt;android连真机签名公网ip更新方案&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_3_4_sekiro_xposed_签名解决方案&#34;&gt;1.3.4、 &lt;a href=&#34;http://91fans.com.cn/post/sekiroone/&#34;&gt;Sekiro + Xposed 签名解决方案&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_3_5_frida_androidasync_实现_rpc&#34;&gt;1.3.5、 &lt;a href=&#34;http://91fans.com.cn/post/fridarpctwo/&#34;&gt;Frida + AndroidAsync 实现 RPC&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_第二章_进阶学习&#34;&gt;第二章 进阶学习&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_1反混淆&#34;&gt;1、反混淆&lt;/h3&gt;&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_1_1_unicorn反混淆&#34;&gt;1.1、 Unicorn反混淆&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_1_unicorn反混淆恢复被ollvm保护的程序一&#34;&gt;1.1.1、 &lt;a href=&#34;http://91fans.com.cn/post/disollvmone/&#34;&gt;Unicorn反混淆：恢复被OLLVM保护的程序(一)&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_2反调试&#34;&gt;2、反调试&lt;/h3&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_3反反调试&#34;&gt;3、反反调试&lt;/h3&gt;&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_3_1_tracerid检测&#34;&gt;3.1 Tracerid检测&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_3_1_1_某电商app反反调试&#34;&gt;3.1.1 &lt;a href=&#34;http://91fans.com.cn/post/jdantidbg/&#34;&gt;某电商App反反调试&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_4分析技巧&#34;&gt;4、分析技巧&lt;/h3&gt;&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_4_1_frida分析技巧&#34;&gt;4.1 Frida分析技巧&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_4_1_1_算法还原的助手一_先让时间停下来&#34;&gt;4.1.1 &lt;a href=&#34;http://91fans.com.cn/post/timestops/&#34;&gt;算法还原的助手(一) 先让时间停下来&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_5就不分类&#34;&gt;5、就不分类&lt;/h3&gt;&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_5_1&#34;&gt;5.1&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_5_1_1_trace大盘点&#34;&gt;5.1.1 &lt;a href=&#34;http://91fans.com.cn/post/traceinfo/&#34;&gt;Trace大盘点&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_第三章_模拟执行&#34;&gt;第三章 模拟执行&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_1androidnativeemu&#34;&gt;1、AndroidNativeEmu&lt;/h3&gt;&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_1_1基础&#34;&gt;1.1、基础&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_1_androidnativeemu使用指南&#34;&gt;1.1.1、 &lt;a href=&#34;http://91fans.com.cn/post/androidnativeemu/&#34;&gt;AndroidNativeEmu使用指南&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_1_2实例&#34;&gt;1.2、实例&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_2_1_androidnativeemu模拟执行计算出某电商app_sign&#34;&gt;1.2.1、 &lt;a href=&#34;http://91fans.com.cn/post/liudqsign/&#34;&gt;AndroidNativeEmu模拟执行计算出某电商App sign&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_2_1_androidnativeemu中hook_gettimeofday和lrand48来验证签名值&#34;&gt;1.2.1、 &lt;a href=&#34;http://91fans.com.cn/post/timestopstwo/&#34;&gt;AndroidNativeEmu中Hook gettimeofday和lrand48来验证签名值&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_1_3反模拟执行&#34;&gt;1.3、反模拟执行&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_3_1_一种对抗androidnativeemu的方法&#34;&gt;1.3.1、 &lt;a href=&#34;http://91fans.com.cn/post/androidemubug/&#34;&gt;一种对抗AndroidNativeEmu的方法&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_1_6系列教程&#34;&gt;1.6、系列教程&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_6_1_androidnativeemu模拟执行大厂so实操教程一_如何搞一个类&#34;&gt;1.6.1、  &lt;a href=&#34;http://91fans.com.cn/post/androidemuone/&#34;&gt;AndroidNativeEmu模拟执行大厂so实操教程(一) 如何搞一个类&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_6_2_androidnativeemu模拟执行大厂so实操教程二_增加成员函数&#34;&gt;1.6.2、  &lt;a href=&#34;http://91fans.com.cn/post/androidemutwo/&#34;&gt;AndroidNativeEmu模拟执行大厂so实操教程(二) 增加成员函数&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_6_3_androidnativeemu模拟执行大厂so实操教程三_填jmethodid相同的坑&#34;&gt;1.6.3、  &lt;a href=&#34;http://91fans.com.cn/post/androidemuthr/&#34;&gt;AndroidNativeEmu模拟执行大厂so实操教程(三) 填jmethodID相同的坑&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_6_4_androidnativeemu模拟执行大厂so实操教程四_函数功能实现&#34;&gt;1.6.4、  &lt;a href=&#34;http://91fans.com.cn/post/androidemufour/&#34;&gt;AndroidNativeEmu模拟执行大厂so实操教程(四) 函数功能实现&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_6_5_androidnativeemu模拟执行大厂so实操教程五_增加字段成员变量&#34;&gt;1.6.5、  &lt;a href=&#34;http://91fans.com.cn/post/androidemufive/&#34;&gt;AndroidNativeEmu模拟执行大厂so实操教程(五) 增加字段(成员变量)&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_6_6_androidnativeemu模拟执行大厂so实操教程六_补齐jni函数&#34;&gt;1.6.6、  &lt;a href=&#34;http://91fans.com.cn/post/androidemusix/&#34;&gt;AndroidNativeEmu模拟执行大厂so实操教程(六) 补齐jni函数&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_6_7_androidnativeemu模拟执行大厂so实操教程七_构造参数来调用native函数&#34;&gt;1.6.7、  &lt;a href=&#34;http://91fans.com.cn/post/androidemusev/&#34;&gt;AndroidNativeEmu模拟执行大厂so实操教程(七) 构造参数来调用Native函数&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_2unidbg&#34;&gt;2、Unidbg&lt;/h3&gt;&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_2_1基础&#34;&gt;2.1、基础&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_2_1_1_unidbg使用指南一&#34;&gt;2.1.1、 &lt;a href=&#34;http://91fans.com.cn/post/unidbgone/&#34;&gt;Unidbg使用指南(一)&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_2_2实例&#34;&gt;2.2、实例&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_2_2_1_unidbg模拟执行大厂so实操教程一_先把框架搭起来&#34;&gt;2.2.1、 &lt;a href=&#34;http://91fans.com.cn/post/unidbgtwo/&#34;&gt;Unidbg模拟执行大厂so实操教程(一) 先把框架搭起来&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_2_2_2_unidbg模拟执行大厂so实操教程二&#34;&gt;2.2.2、 &lt;a href=&#34;http://91fans.com.cn/post/unidbgthr/&#34;&gt;Unidbg模拟执行大厂so实操教程(二)&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_2_2_3_unidbg模拟执行某段子so实操教程一_先把框架搭起来&#34;&gt;2.2.3、 &lt;a href=&#34;http://91fans.com.cn/post/unidbgzyone/&#34;&gt;Unidbg模拟执行某段子so实操教程(一) 先把框架搭起来&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_2_2_4_unidbg模拟执行某段子so实操教程二_loadso对比&#34;&gt;2.2.4、 &lt;a href=&#34;http://91fans.com.cn/post/unidbgzytwo/&#34;&gt;Unidbg模拟执行某段子so实操教程(二) LoadSo对比&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_3appdbg&#34;&gt;3、AppDbg&lt;/h3&gt;&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_3_1基础&#34;&gt;3.1、基础&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_3_1_1_appdbg_一个伪装成调试器的虚拟机&#34;&gt;3.1.1、 &lt;a href=&#34;http://91fans.com.cn/post/appdbgone/&#34;&gt;appdbg: 一个伪装成调试器的虚拟机&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;/div&gt;&lt;footer&gt;&lt;div id=&#34;footer-text&#34;&gt;&lt;br/&gt;Last updated 2026-04-27 18:48:41 +0800&lt;/div&gt;&lt;/footer&gt;
</description>
      
    </item>
    
    <item>
      <title>新手指南</title>
      <link>http://91fans.com.cn/startguide/</link>
      <pubDate>Mon, 01 Jul 2019 21:38:52 +0800</pubDate>
      
      <guid>http://91fans.com.cn/startguide/</guid>
      
        <description>&lt;meta charset=&#34;UTF-8&#34;/&gt;&lt;meta http-equiv=&#34;X-UA-Compatible&#34; content=&#34;IE=edge&#34;/&gt;&lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;/&gt;&lt;meta name=&#34;generator&#34; content=&#34;Asciidoctor 2.0.20&#34;/&gt;&lt;title&gt;第一章 基础&lt;/title&gt;&lt;style&gt;/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import &#34;https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700&#34;; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:&#34;\201C&#34; &#34;\201D&#34; &#34;\2018&#34; &#34;\2019&#34;}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock&gt;.content&gt;.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock&gt;.content&gt;.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:&#34; &#34;;display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])&gt;code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre&gt;code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:&#34;[&#34;;padding:0 3px 0 2px}
b.button::after{content:&#34;]&#34;;padding:0 2px 0 3px}
p a&gt;code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:&#34; &#34;;display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header&gt;h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header&gt;h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header&gt;h1:only-child,body.toc2 #header&gt;h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:&#34;\00a0\2013\00a0&#34;}
#header .details br+span.author::before{content:&#34;\00a0\22c5\00a0&#34;;color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:&#34;\00a0|\00a0&#34;}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:&#34;\00a0&#34;}
#content&gt;h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc&gt;ul{margin-left:.125em}
#toc ul.sectlevel0&gt;li&gt;a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2&gt;ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2&gt;ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc&gt;:first-child{margin-top:0}
#content #toc&gt;:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1&gt;a.anchor,h2&gt;a.anchor,h3&gt;a.anchor,#toctitle&gt;a.anchor,.sidebarblock&gt;.content&gt;.title&gt;a.anchor,h4&gt;a.anchor,h5&gt;a.anchor,h6&gt;a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1&gt;a.anchor::before,h2&gt;a.anchor::before,h3&gt;a.anchor::before,#toctitle&gt;a.anchor::before,.sidebarblock&gt;.content&gt;.title&gt;a.anchor::before,h4&gt;a.anchor::before,h5&gt;a.anchor::before,h6&gt;a.anchor::before{content:&#34;\00A7&#34;;font-size:.85em;display:block;padding-top:.1em}
#content h1:hover&gt;a.anchor,#content h1&gt;a.anchor:hover,h2:hover&gt;a.anchor,h2&gt;a.anchor:hover,h3:hover&gt;a.anchor,#toctitle:hover&gt;a.anchor,.sidebarblock&gt;.content&gt;.title:hover&gt;a.anchor,h3&gt;a.anchor:hover,#toctitle&gt;a.anchor:hover,.sidebarblock&gt;.content&gt;.title&gt;a.anchor:hover,h4:hover&gt;a.anchor,h4&gt;a.anchor:hover,h5:hover&gt;a.anchor,h5&gt;a.anchor:hover,h6:hover&gt;a.anchor,h6&gt;a.anchor:hover{visibility:visible}
#content h1&gt;a.link,h2&gt;a.link,h3&gt;a.link,#toctitle&gt;a.link,.sidebarblock&gt;.content&gt;.title&gt;a.link,h4&gt;a.link,h5&gt;a.link,h6&gt;a.link{color:#ba3925;text-decoration:none}
#content h1&gt;a.link:hover,h2&gt;a.link:hover,h3&gt;a.link:hover,#toctitle&gt;a.link:hover,.sidebarblock&gt;.content&gt;.title&gt;a.link:hover,h4&gt;a.link:hover,h5&gt;a.link:hover,h6&gt;a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details&gt;summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details&gt;summary::-webkit-details-marker{display:none}
details&gt;summary::before{content:&#34;&#34;;border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]&gt;summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details&gt;summary::after{content:&#34;&#34;;width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{text-rendering:optimizeLegibility;text-align:left;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content&gt;caption.title{white-space:nowrap;width:0}
.paragraph.lead&gt;p,#preamble&gt;.sectionbody&gt;[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock&gt;table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock&gt;table td.icon{text-align:center;width:80px}
.admonitionblock&gt;table td.icon img{max-width:none}
.admonitionblock&gt;table td.icon .title{font-weight:bold;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;text-transform:uppercase}
.admonitionblock&gt;table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock&gt;table td.content&gt;:last-child&gt;:last-child{margin-bottom:0}
.exampleblock&gt;.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock&gt;.content&gt;.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock&gt;.content&gt;:first-child,.sidebarblock&gt;.content&gt;:first-child{margin-top:0}
.exampleblock&gt;.content&gt;:last-child,.exampleblock&gt;.content&gt;:last-child&gt;:last-child,.exampleblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child&gt;:last-child,.sidebarblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child{margin-bottom:0}
.literalblock pre,.listingblock&gt;.content&gt;pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:1em}}
.literalblock pre,.listingblock&gt;.content&gt;pre:not(.highlight),.listingblock&gt;.content&gt;pre[class=highlight],.listingblock&gt;.content&gt;pre[class^=&#34;highlight &#34;]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock&gt;.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:&#34;$&#34;}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs&gt;code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)&gt;.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:&#34;\201c&#34;;float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote&gt;.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract&gt;.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt&gt;blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock&gt;.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock&gt;.content&gt;:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all&gt;*&gt;tr&gt;*{border-width:1px}
table.grid-cols&gt;*&gt;tr&gt;*{border-width:0 1px}
table.grid-rows&gt;*&gt;tr&gt;*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none&gt;colgroup+*&gt;:first-child&gt;*,table.frame-sides&gt;colgroup+*&gt;:first-child&gt;*{border-top-width:0}
table.frame-none&gt;:last-child&gt;:last-child&gt;*,table.frame-sides&gt;:last-child&gt;:last-child&gt;*{border-bottom-width:0}
table.frame-none&gt;*&gt;tr&gt;:first-child,table.frame-ends&gt;*&gt;tr&gt;:first-child{border-left-width:0}
table.frame-none&gt;*&gt;tr&gt;:last-child,table.frame-ends&gt;*&gt;tr&gt;:last-child{border-right-width:0}
table.stripes-all&gt;*&gt;tr,table.stripes-odd&gt;*&gt;tr:nth-of-type(odd),table.stripes-even&gt;*&gt;tr:nth-of-type(even),table.stripes-hover&gt;*&gt;tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock&gt;code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child&gt;:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li&gt;p:empty:only-child::before{content:&#34;&#34;;display:inline-block}
ul.checklist&gt;li&gt;p:first-child{margin-left:-1em}
ul.checklist&gt;li&gt;p:first-child&gt;.fa-square-o:first-child,ul.checklist&gt;li&gt;p:first-child&gt;.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist&gt;li&gt;p:first-child&gt;input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline&gt;li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist&gt;table,.colist&gt;table{border:0;background:none}
.hdlist&gt;table&gt;tbody&gt;tr,.colist&gt;table&gt;tbody&gt;tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock&gt;.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb&gt;.title,.imageblock.th&gt;.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon&gt;.fa{cursor:default}
a span.icon&gt;.fa{cursor:inherit}
.admonitionblock td.icon [class^=&#34;fa icon-&#34;]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:&#34;\f05a&#34;;color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:&#34;\f0eb&#34;;text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:&#34;\f071&#34;;color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:&#34;\f06d&#34;;color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:&#34;\f06a&#34;;color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock&gt;.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^=&#34;#&#34;],a[href^=&#34;mailto:&#34;]{text-decoration:none!important}
a[href^=&#34;http:&#34;]:not(.bare)::after,a[href^=&#34;https:&#34;]:not(.bare)::after{content:&#34;(&#34; attr(href) &#34;)&#34;;display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:&#34; (&#34; attr(title) &#34;)&#34;}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock&gt;.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header&gt;h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1&gt;h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header&gt;h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}&lt;/style&gt;&lt;/head&gt;&lt;body class=&#34;article&#34;&gt;&lt;header&gt;&lt;/header&gt;&lt;div id=&#34;content&#34;&gt;&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_第一章_基础&#34;&gt;第一章 基础&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_1android逆向环境搭建&#34;&gt;1、Android逆向环境搭建&lt;/h3&gt;&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_1_1反编译工具&#34;&gt;1.1、反编译工具&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_1_jeb_3_19_1_pro_安装&#34;&gt;1.1.1、 &lt;a href=&#34;http://91fans.com.cn/post/jebtool/&#34;&gt;JEB 3.19.1 PRO 安装&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_1_2动态调试&#34;&gt;1.2、动态调试&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_2_1_frida_安装一&#34;&gt;1.2.1、 &lt;a href=&#34;http://91fans.com.cn/post/fridainstallone/&#34;&gt;Frida 安装(一)&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_2_1_ida动态调试so&#34;&gt;1.2.1、 &lt;a href=&#34;http://91fans.com.cn/post/idadbg/&#34;&gt;Ida动态调试so&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_2ios逆向环境搭建&#34;&gt;2、Ios逆向环境搭建&lt;/h3&gt;&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_2_1越狱先&#34;&gt;2.1、越狱先&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_2_1_1_iphone越狱2020&#34;&gt;2.1.1、 &lt;a href=&#34;http://91fans.com.cn/post/iosroot/&#34;&gt;Iphone越狱2020&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_2_2开发环境&#34;&gt;2.2、开发环境&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_2_2_1_ios逆向环境搭建_一&#34;&gt;2.2.1、 &lt;a href=&#34;http://91fans.com.cn/post/iosstartone/&#34;&gt;Ios逆向环境搭建 (一)&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_第二章_进阶学习&#34;&gt;第二章  进阶学习&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_1android源码分析&#34;&gt;1、Android源码分析&lt;/h3&gt;&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_1_1源码编译&#34;&gt;1.1、源码编译&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_1_mac_10_14_x_下android_10源码qp1a_190711_020编译和刷机_pixel_2_xl&#34;&gt;1.1.1、 &lt;a href=&#34;http://91fans.com.cn/post/compileaosp/&#34;&gt;Mac 10.14.x 下Android 10源码（QP1A.190711.020）编译和刷机 (Pixel 2 XL)&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_2xposed&#34;&gt;2、Xposed&lt;/h3&gt;&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_2_1基础&#34;&gt;2.1、基础&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_2_1_1_最新的xposed模块编写教程2020&#34;&gt;2.1.1、 &lt;a href=&#34;http://91fans.com.cn/post/xposedone/&#34;&gt;最新的Xposed模块编写教程2020&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_3frida&#34;&gt;3、Frida&lt;/h3&gt;&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_3_1基础&#34;&gt;3.1、基础&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_3_1_1_手把手教你搭个frida_sekiro_rpc框架&#34;&gt;3.1.1、 &lt;a href=&#34;http://91fans.com.cn/post/fridasekirorpc/&#34;&gt;手把手教你搭个Frida + Sekiro Rpc框架&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_3_2实例&#34;&gt;3.2、实例&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_3_2_1http91fans_com_cnpostfridahttp在frida里面做http请求_聊聊jar_to_dex&#34;&gt;3.2.1、http://91fans.com.cn/post/fridahttp/[在Frida里面做http请求: 聊聊jar to dex]&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_4unicorn&#34;&gt;4、Unicorn&lt;/h3&gt;&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_4_1基础&#34;&gt;4.1、基础&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_4_1_1_unicorn用法示例一&#34;&gt;4.1.1、 &lt;a href=&#34;http://91fans.com.cn/post/unicornone/&#34;&gt;Unicorn用法示例(一)&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_4_1_2_unicorn用法示例二&#34;&gt;4.1.2、 &lt;a href=&#34;http://91fans.com.cn/post/unicorntwo/&#34;&gt;Unicorn用法示例(二)&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_第三章_arm汇编语言入门&#34;&gt;第三章 ARM汇编语言入门&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_1指令介绍&#34;&gt;1、指令介绍&lt;/h3&gt;&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_1_1&#34;&gt;1.1&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_1_代码还原的技术_arm汇编入门教程一_hello_world&#34;&gt;1.1.1、 &lt;a href=&#34;http://91fans.com.cn/post/reverseone/&#34;&gt;代码还原的技术 ARM汇编入门教程(一) Hello World!&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_2_代码还原的技术_arm汇编入门教程二_加减乘除&#34;&gt;1.1.2、 &lt;a href=&#34;http://91fans.com.cn/post/reversetwo/&#34;&gt;代码还原的技术 ARM汇编入门教程(二) 加减乘除&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_第四章_实用技巧&#34;&gt;第四章  实用技巧&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_1android&#34;&gt;1、Android&lt;/h3&gt;&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_1_1_2&#34;&gt;1.1&lt;/h4&gt;&lt;section class=&#34;doc-section level-4&#34;&gt;&lt;h5 id=&#34;_1_1_1_手把手教你从apk中取出算法&#34;&gt;1.1.1、 &lt;a href=&#34;http://91fans.com.cn/post/getcodeformapk/&#34;&gt;手把手教你从Apk中取出算法&lt;/a&gt;&lt;/h5&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;/div&gt;&lt;footer&gt;&lt;div id=&#34;footer-text&#34;&gt;&lt;br/&gt;Last updated 2026-04-27 18:48:41 +0800&lt;/div&gt;&lt;/footer&gt;
</description>
      
    </item>
    
    <item>
      <title>搜索</title>
      <link>http://91fans.com.cn/search/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://91fans.com.cn/search/</guid>
      
        <description>&lt;meta charset=&#34;UTF-8&#34;/&gt;&lt;meta http-equiv=&#34;X-UA-Compatible&#34; content=&#34;IE=edge&#34;/&gt;&lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;/&gt;&lt;meta name=&#34;generator&#34; content=&#34;Asciidoctor 2.0.20&#34;/&gt;&lt;title&gt;Untitled&lt;/title&gt;&lt;style&gt;/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import &#34;https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700&#34;; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:&#34;\201C&#34; &#34;\201D&#34; &#34;\2018&#34; &#34;\2019&#34;}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock&gt;.content&gt;.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock&gt;.content&gt;.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:&#34; &#34;;display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])&gt;code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre&gt;code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:&#34;[&#34;;padding:0 3px 0 2px}
b.button::after{content:&#34;]&#34;;padding:0 2px 0 3px}
p a&gt;code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:&#34; &#34;;display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header&gt;h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header&gt;h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header&gt;h1:only-child,body.toc2 #header&gt;h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:&#34;\00a0\2013\00a0&#34;}
#header .details br+span.author::before{content:&#34;\00a0\22c5\00a0&#34;;color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:&#34;\00a0|\00a0&#34;}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:&#34;\00a0&#34;}
#content&gt;h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc&gt;ul{margin-left:.125em}
#toc ul.sectlevel0&gt;li&gt;a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2&gt;ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2&gt;ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc&gt;:first-child{margin-top:0}
#content #toc&gt;:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1&gt;a.anchor,h2&gt;a.anchor,h3&gt;a.anchor,#toctitle&gt;a.anchor,.sidebarblock&gt;.content&gt;.title&gt;a.anchor,h4&gt;a.anchor,h5&gt;a.anchor,h6&gt;a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1&gt;a.anchor::before,h2&gt;a.anchor::before,h3&gt;a.anchor::before,#toctitle&gt;a.anchor::before,.sidebarblock&gt;.content&gt;.title&gt;a.anchor::before,h4&gt;a.anchor::before,h5&gt;a.anchor::before,h6&gt;a.anchor::before{content:&#34;\00A7&#34;;font-size:.85em;display:block;padding-top:.1em}
#content h1:hover&gt;a.anchor,#content h1&gt;a.anchor:hover,h2:hover&gt;a.anchor,h2&gt;a.anchor:hover,h3:hover&gt;a.anchor,#toctitle:hover&gt;a.anchor,.sidebarblock&gt;.content&gt;.title:hover&gt;a.anchor,h3&gt;a.anchor:hover,#toctitle&gt;a.anchor:hover,.sidebarblock&gt;.content&gt;.title&gt;a.anchor:hover,h4:hover&gt;a.anchor,h4&gt;a.anchor:hover,h5:hover&gt;a.anchor,h5&gt;a.anchor:hover,h6:hover&gt;a.anchor,h6&gt;a.anchor:hover{visibility:visible}
#content h1&gt;a.link,h2&gt;a.link,h3&gt;a.link,#toctitle&gt;a.link,.sidebarblock&gt;.content&gt;.title&gt;a.link,h4&gt;a.link,h5&gt;a.link,h6&gt;a.link{color:#ba3925;text-decoration:none}
#content h1&gt;a.link:hover,h2&gt;a.link:hover,h3&gt;a.link:hover,#toctitle&gt;a.link:hover,.sidebarblock&gt;.content&gt;.title&gt;a.link:hover,h4&gt;a.link:hover,h5&gt;a.link:hover,h6&gt;a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details&gt;summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details&gt;summary::-webkit-details-marker{display:none}
details&gt;summary::before{content:&#34;&#34;;border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]&gt;summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details&gt;summary::after{content:&#34;&#34;;width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{text-rendering:optimizeLegibility;text-align:left;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content&gt;caption.title{white-space:nowrap;width:0}
.paragraph.lead&gt;p,#preamble&gt;.sectionbody&gt;[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock&gt;table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock&gt;table td.icon{text-align:center;width:80px}
.admonitionblock&gt;table td.icon img{max-width:none}
.admonitionblock&gt;table td.icon .title{font-weight:bold;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;text-transform:uppercase}
.admonitionblock&gt;table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock&gt;table td.content&gt;:last-child&gt;:last-child{margin-bottom:0}
.exampleblock&gt;.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock&gt;.content&gt;.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock&gt;.content&gt;:first-child,.sidebarblock&gt;.content&gt;:first-child{margin-top:0}
.exampleblock&gt;.content&gt;:last-child,.exampleblock&gt;.content&gt;:last-child&gt;:last-child,.exampleblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child&gt;:last-child,.sidebarblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child{margin-bottom:0}
.literalblock pre,.listingblock&gt;.content&gt;pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:1em}}
.literalblock pre,.listingblock&gt;.content&gt;pre:not(.highlight),.listingblock&gt;.content&gt;pre[class=highlight],.listingblock&gt;.content&gt;pre[class^=&#34;highlight &#34;]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock&gt;.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:&#34;$&#34;}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs&gt;code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)&gt;.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:&#34;\201c&#34;;float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote&gt;.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract&gt;.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt&gt;blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock&gt;.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock&gt;.content&gt;:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all&gt;*&gt;tr&gt;*{border-width:1px}
table.grid-cols&gt;*&gt;tr&gt;*{border-width:0 1px}
table.grid-rows&gt;*&gt;tr&gt;*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none&gt;colgroup+*&gt;:first-child&gt;*,table.frame-sides&gt;colgroup+*&gt;:first-child&gt;*{border-top-width:0}
table.frame-none&gt;:last-child&gt;:last-child&gt;*,table.frame-sides&gt;:last-child&gt;:last-child&gt;*{border-bottom-width:0}
table.frame-none&gt;*&gt;tr&gt;:first-child,table.frame-ends&gt;*&gt;tr&gt;:first-child{border-left-width:0}
table.frame-none&gt;*&gt;tr&gt;:last-child,table.frame-ends&gt;*&gt;tr&gt;:last-child{border-right-width:0}
table.stripes-all&gt;*&gt;tr,table.stripes-odd&gt;*&gt;tr:nth-of-type(odd),table.stripes-even&gt;*&gt;tr:nth-of-type(even),table.stripes-hover&gt;*&gt;tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock&gt;code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child&gt;:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li&gt;p:empty:only-child::before{content:&#34;&#34;;display:inline-block}
ul.checklist&gt;li&gt;p:first-child{margin-left:-1em}
ul.checklist&gt;li&gt;p:first-child&gt;.fa-square-o:first-child,ul.checklist&gt;li&gt;p:first-child&gt;.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist&gt;li&gt;p:first-child&gt;input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline&gt;li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist&gt;table,.colist&gt;table{border:0;background:none}
.hdlist&gt;table&gt;tbody&gt;tr,.colist&gt;table&gt;tbody&gt;tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock&gt;.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb&gt;.title,.imageblock.th&gt;.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon&gt;.fa{cursor:default}
a span.icon&gt;.fa{cursor:inherit}
.admonitionblock td.icon [class^=&#34;fa icon-&#34;]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:&#34;\f05a&#34;;color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:&#34;\f0eb&#34;;text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:&#34;\f071&#34;;color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:&#34;\f06d&#34;;color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:&#34;\f06a&#34;;color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock&gt;.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^=&#34;#&#34;],a[href^=&#34;mailto:&#34;]{text-decoration:none!important}
a[href^=&#34;http:&#34;]:not(.bare)::after,a[href^=&#34;https:&#34;]:not(.bare)::after{content:&#34;(&#34; attr(href) &#34;)&#34;;display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:&#34; (&#34; attr(title) &#34;)&#34;}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock&gt;.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header&gt;h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1&gt;h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header&gt;h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}&lt;/style&gt;&lt;/head&gt;&lt;body class=&#34;article&#34;&gt;&lt;header&gt;&lt;/header&gt;&lt;div id=&#34;content&#34;&gt;&lt;/div&gt;&lt;footer&gt;&lt;div id=&#34;footer-text&#34;&gt;&lt;br/&gt;Last updated 2026-04-27 18:48:41 +0800&lt;/div&gt;&lt;/footer&gt;
</description>
      
    </item>
    
    <item>
      <title>Codex开始抢逆向饭碗了：一句话同时指挥Jadx MCP和IDA MCP</title>
      <link>http://91fans.com.cn/post/codexone/</link>
      <pubDate>Wed, 22 Apr 2026 12:00:00 +0800</pubDate>
      
      <guid>http://91fans.com.cn/post/codexone/</guid>
      
        <description>&lt;meta charset=&#34;UTF-8&#34;/&gt;&lt;meta http-equiv=&#34;X-UA-Compatible&#34; content=&#34;IE=edge&#34;/&gt;&lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;/&gt;&lt;meta name=&#34;generator&#34; content=&#34;Asciidoctor 2.0.20&#34;/&gt;&lt;title&gt;一、目标&lt;/title&gt;&lt;style&gt;/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import &#34;https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700&#34;; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:&#34;\201C&#34; &#34;\201D&#34; &#34;\2018&#34; &#34;\2019&#34;}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock&gt;.content&gt;.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock&gt;.content&gt;.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:&#34; &#34;;display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])&gt;code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre&gt;code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:&#34;[&#34;;padding:0 3px 0 2px}
b.button::after{content:&#34;]&#34;;padding:0 2px 0 3px}
p a&gt;code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:&#34; &#34;;display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header&gt;h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header&gt;h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header&gt;h1:only-child,body.toc2 #header&gt;h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:&#34;\00a0\2013\00a0&#34;}
#header .details br+span.author::before{content:&#34;\00a0\22c5\00a0&#34;;color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:&#34;\00a0|\00a0&#34;}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:&#34;\00a0&#34;}
#content&gt;h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc&gt;ul{margin-left:.125em}
#toc ul.sectlevel0&gt;li&gt;a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2&gt;ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2&gt;ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc&gt;:first-child{margin-top:0}
#content #toc&gt;:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1&gt;a.anchor,h2&gt;a.anchor,h3&gt;a.anchor,#toctitle&gt;a.anchor,.sidebarblock&gt;.content&gt;.title&gt;a.anchor,h4&gt;a.anchor,h5&gt;a.anchor,h6&gt;a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1&gt;a.anchor::before,h2&gt;a.anchor::before,h3&gt;a.anchor::before,#toctitle&gt;a.anchor::before,.sidebarblock&gt;.content&gt;.title&gt;a.anchor::before,h4&gt;a.anchor::before,h5&gt;a.anchor::before,h6&gt;a.anchor::before{content:&#34;\00A7&#34;;font-size:.85em;display:block;padding-top:.1em}
#content h1:hover&gt;a.anchor,#content h1&gt;a.anchor:hover,h2:hover&gt;a.anchor,h2&gt;a.anchor:hover,h3:hover&gt;a.anchor,#toctitle:hover&gt;a.anchor,.sidebarblock&gt;.content&gt;.title:hover&gt;a.anchor,h3&gt;a.anchor:hover,#toctitle&gt;a.anchor:hover,.sidebarblock&gt;.content&gt;.title&gt;a.anchor:hover,h4:hover&gt;a.anchor,h4&gt;a.anchor:hover,h5:hover&gt;a.anchor,h5&gt;a.anchor:hover,h6:hover&gt;a.anchor,h6&gt;a.anchor:hover{visibility:visible}
#content h1&gt;a.link,h2&gt;a.link,h3&gt;a.link,#toctitle&gt;a.link,.sidebarblock&gt;.content&gt;.title&gt;a.link,h4&gt;a.link,h5&gt;a.link,h6&gt;a.link{color:#ba3925;text-decoration:none}
#content h1&gt;a.link:hover,h2&gt;a.link:hover,h3&gt;a.link:hover,#toctitle&gt;a.link:hover,.sidebarblock&gt;.content&gt;.title&gt;a.link:hover,h4&gt;a.link:hover,h5&gt;a.link:hover,h6&gt;a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details&gt;summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details&gt;summary::-webkit-details-marker{display:none}
details&gt;summary::before{content:&#34;&#34;;border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]&gt;summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details&gt;summary::after{content:&#34;&#34;;width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{text-rendering:optimizeLegibility;text-align:left;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content&gt;caption.title{white-space:nowrap;width:0}
.paragraph.lead&gt;p,#preamble&gt;.sectionbody&gt;[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock&gt;table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock&gt;table td.icon{text-align:center;width:80px}
.admonitionblock&gt;table td.icon img{max-width:none}
.admonitionblock&gt;table td.icon .title{font-weight:bold;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;text-transform:uppercase}
.admonitionblock&gt;table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock&gt;table td.content&gt;:last-child&gt;:last-child{margin-bottom:0}
.exampleblock&gt;.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock&gt;.content&gt;.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock&gt;.content&gt;:first-child,.sidebarblock&gt;.content&gt;:first-child{margin-top:0}
.exampleblock&gt;.content&gt;:last-child,.exampleblock&gt;.content&gt;:last-child&gt;:last-child,.exampleblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child&gt;:last-child,.sidebarblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child{margin-bottom:0}
.literalblock pre,.listingblock&gt;.content&gt;pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:1em}}
.literalblock pre,.listingblock&gt;.content&gt;pre:not(.highlight),.listingblock&gt;.content&gt;pre[class=highlight],.listingblock&gt;.content&gt;pre[class^=&#34;highlight &#34;]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock&gt;.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:&#34;$&#34;}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs&gt;code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)&gt;.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:&#34;\201c&#34;;float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote&gt;.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract&gt;.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt&gt;blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock&gt;.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock&gt;.content&gt;:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all&gt;*&gt;tr&gt;*{border-width:1px}
table.grid-cols&gt;*&gt;tr&gt;*{border-width:0 1px}
table.grid-rows&gt;*&gt;tr&gt;*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none&gt;colgroup+*&gt;:first-child&gt;*,table.frame-sides&gt;colgroup+*&gt;:first-child&gt;*{border-top-width:0}
table.frame-none&gt;:last-child&gt;:last-child&gt;*,table.frame-sides&gt;:last-child&gt;:last-child&gt;*{border-bottom-width:0}
table.frame-none&gt;*&gt;tr&gt;:first-child,table.frame-ends&gt;*&gt;tr&gt;:first-child{border-left-width:0}
table.frame-none&gt;*&gt;tr&gt;:last-child,table.frame-ends&gt;*&gt;tr&gt;:last-child{border-right-width:0}
table.stripes-all&gt;*&gt;tr,table.stripes-odd&gt;*&gt;tr:nth-of-type(odd),table.stripes-even&gt;*&gt;tr:nth-of-type(even),table.stripes-hover&gt;*&gt;tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock&gt;code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child&gt;:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li&gt;p:empty:only-child::before{content:&#34;&#34;;display:inline-block}
ul.checklist&gt;li&gt;p:first-child{margin-left:-1em}
ul.checklist&gt;li&gt;p:first-child&gt;.fa-square-o:first-child,ul.checklist&gt;li&gt;p:first-child&gt;.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist&gt;li&gt;p:first-child&gt;input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline&gt;li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist&gt;table,.colist&gt;table{border:0;background:none}
.hdlist&gt;table&gt;tbody&gt;tr,.colist&gt;table&gt;tbody&gt;tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock&gt;.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb&gt;.title,.imageblock.th&gt;.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon&gt;.fa{cursor:default}
a span.icon&gt;.fa{cursor:inherit}
.admonitionblock td.icon [class^=&#34;fa icon-&#34;]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:&#34;\f05a&#34;;color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:&#34;\f0eb&#34;;text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:&#34;\f071&#34;;color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:&#34;\f06d&#34;;color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:&#34;\f06a&#34;;color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock&gt;.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^=&#34;#&#34;],a[href^=&#34;mailto:&#34;]{text-decoration:none!important}
a[href^=&#34;http:&#34;]:not(.bare)::after,a[href^=&#34;https:&#34;]:not(.bare)::after{content:&#34;(&#34; attr(href) &#34;)&#34;;display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:&#34; (&#34; attr(title) &#34;)&#34;}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock&gt;.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header&gt;h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1&gt;h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header&gt;h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}&lt;/style&gt;
&lt;style&gt;
/*! Stylesheet for CodeRay to loosely match GitHub themes | MIT License */
pre.CodeRay{background:#f7f7f8}
.CodeRay .line-numbers{border-right:1px solid;opacity:.35;padding:0 .5em 0 0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.CodeRay span.line-numbers{display:inline-block;margin-right:.75em}
.CodeRay .line-numbers strong{color:#000}
table.CodeRay{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.CodeRay td{vertical-align:top;line-height:inherit}
table.CodeRay td.line-numbers{text-align:right}
table.CodeRay td.code{padding:0 0 0 .75em}
.CodeRay .debug{color:#fff!important;background:navy!important}
.CodeRay .annotation{color:#007}
.CodeRay .attribute-name{color:navy}
.CodeRay .attribute-value{color:#700}
.CodeRay .binary{color:#509}
.CodeRay .comment{color:#998;font-style:italic}
.CodeRay .char{color:#04d}
.CodeRay .char .content{color:#04d}
.CodeRay .char .delimiter{color:#039}
.CodeRay .class{color:#458;font-weight:bold}
.CodeRay .complex{color:#a08}
.CodeRay .constant,.CodeRay .predefined-constant{color:teal}
.CodeRay .color{color:#099}
.CodeRay .class-variable{color:#369}
.CodeRay .decorator{color:#b0b}
.CodeRay .definition{color:#099}
.CodeRay .delimiter{color:#000}
.CodeRay .doc{color:#970}
.CodeRay .doctype{color:#34b}
.CodeRay .doc-string{color:#d42}
.CodeRay .escape{color:#666}
.CodeRay .entity{color:#800}
.CodeRay .error{color:#808}
.CodeRay .exception{color:inherit}
.CodeRay .filename{color:#099}
.CodeRay .function{color:#900;font-weight:bold}
.CodeRay .global-variable{color:teal}
.CodeRay .hex{color:#058}
.CodeRay .integer,.CodeRay .float{color:#099}
.CodeRay .include{color:#555}
.CodeRay .inline{color:#000}
.CodeRay .inline .inline{background:#ccc}
.CodeRay .inline .inline .inline{background:#bbb}
.CodeRay .inline .inline-delimiter{color:#d14}
.CodeRay .inline-delimiter{color:#d14}
.CodeRay .important{color:#555;font-weight:bold}
.CodeRay .interpreted{color:#b2b}
.CodeRay .instance-variable{color:teal}
.CodeRay .label{color:#970}
.CodeRay .local-variable{color:#963}
.CodeRay .octal{color:#40e}
.CodeRay .predefined{color:#369}
.CodeRay .preprocessor{color:#579}
.CodeRay .pseudo-class{color:#555}
.CodeRay .directive{font-weight:bold}
.CodeRay .type{font-weight:bold}
.CodeRay .predefined-type{color:inherit}
.CodeRay .reserved,.CodeRay .keyword{color:#000;font-weight:bold}
.CodeRay .key{color:#808}
.CodeRay .key .delimiter{color:#606}
.CodeRay .key .char{color:#80f}
.CodeRay .value{color:#088}
.CodeRay .regexp .delimiter{color:#808}
.CodeRay .regexp .content{color:#808}
.CodeRay .regexp .modifier{color:#808}
.CodeRay .regexp .char{color:#d14}
.CodeRay .regexp .function{color:#404;font-weight:bold}
.CodeRay .string{color:#d20}
.CodeRay .string .string .string{background:#ffd0d0}
.CodeRay .string .content{color:#d14}
.CodeRay .string .char{color:#d14}
.CodeRay .string .delimiter{color:#d14}
.CodeRay .shell{color:#d14}
.CodeRay .shell .delimiter{color:#d14}
.CodeRay .symbol{color:#990073}
.CodeRay .symbol .content{color:#a60}
.CodeRay .symbol .delimiter{color:#630}
.CodeRay .tag{color:teal}
.CodeRay .tag-special{color:#d70}
.CodeRay .variable{color:#036}
.CodeRay .insert{background:#afa}
.CodeRay .delete{background:#faa}
.CodeRay .change{color:#aaf;background:#007}
.CodeRay .head{color:#f8f;background:#505}
.CodeRay .insert .insert{color:#080}
.CodeRay .delete .delete{color:#800}
.CodeRay .change .change{color:#66f}
.CodeRay .head .head{color:#f4f}
&lt;/style&gt;&lt;/head&gt;&lt;body class=&#34;article&#34;&gt;&lt;header&gt;&lt;/header&gt;&lt;div id=&#34;content&#34;&gt;&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_一目标&#34;&gt;一、目标&lt;/h2&gt;&lt;p&gt;李老板：奋飞呀，现在AI都会写代码了，它到底能不能直接帮咱们做逆向？&lt;/p&gt;
&lt;p&gt;奋飞：光靠一张嘴不行，逆向这活得给它工具。你总不能让一个人闭着眼睛拆发动机吧？&lt;/p&gt;
&lt;p&gt;李老板：那你的意思是？&lt;/p&gt;
&lt;p&gt;奋飞：给它两双眼睛。&lt;/p&gt;
&lt;p&gt;一双给 &lt;mark&gt;Jadx MCP&lt;/mark&gt;，让它去看Java层。
一双给 &lt;mark&gt;IDA MCP&lt;/mark&gt;，让它去啃Native层。
然后中间再塞一个 &lt;mark&gt;Codex&lt;/mark&gt;，让它负责发号施令，顺便把两边的结果串起来。&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Codexone/codexmcpmain-v2.png&#34; alt=&#34;codexmcpmain v2&#34; height=&#34;50&#34;/&gt;
&lt;figcaption&gt;1:codexmcpmain&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;以前我们逆向一个App，经常是这样：&lt;/p&gt;
&lt;div class=&#34;olist arabic&#34;&gt;&lt;ol class=&#34;arabic&#34;&gt;&lt;li&gt;自己在Jadx里翻半天Java调用链&lt;/li&gt;&lt;li&gt;再去IDA里一点点找so入口&lt;/li&gt;&lt;li&gt;找到一半忘了前面Java层到底是谁调的谁&lt;/li&gt;&lt;li&gt;最后开着一堆窗口，像在打牌&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;今天咱们不搞复杂样本，就拿我自己的一个小Demo下手，看看Codex能不能把这套活先干一部分。&lt;/p&gt;
&lt;p&gt;这次的样本是一个Android Demo，Java入口在 &lt;code&gt;MainActivity&lt;/code&gt;，中间会调用 &lt;code&gt;com.qiyi.test.Test&lt;/code&gt; 和 &lt;code&gt;NativeHandler&lt;/code&gt;，最终进入一个 &lt;code&gt;libtest.so&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;今天的目标很简单：&lt;/p&gt;
&lt;div class=&#34;olist arabic&#34;&gt;&lt;ol class=&#34;arabic&#34;&gt;&lt;li&gt;让Codex通过Jadx MCP把Java层调用链摸出来&lt;/li&gt;&lt;li&gt;让Codex通过IDA MCP去分析 &lt;code&gt;libtest.so&lt;/code&gt;&lt;/li&gt;&lt;li&gt;最后让Codex把Java层和Native层拼成一条完整链路&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;如果这套流程跑顺了，那以后很多“先找入口、先串链路”的脏活，就可以先让AI去趟雷了。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_二准备&#34;&gt;二、准备&lt;/h2&gt;&lt;p&gt;样本的Java代码大概长这样：&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;java&#34;&gt;&lt;span class=&#34;directive&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;type&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;class&#34;&gt;MainActivity&lt;/span&gt; &lt;span class=&#34;directive&#34;&gt;extends&lt;/span&gt; AppCompatActivity {

    &lt;span class=&#34;directive&#34;&gt;static&lt;/span&gt; {
        &lt;span class=&#34;predefined-type&#34;&gt;System&lt;/span&gt;.loadLibrary(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;native-lib&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
    }

    &lt;span class=&#34;annotation&#34;&gt;@Override&lt;/span&gt;
    &lt;span class=&#34;directive&#34;&gt;protected&lt;/span&gt; &lt;span class=&#34;type&#34;&gt;void&lt;/span&gt; onCreate(Bundle savedInstanceState) {
        &lt;span class=&#34;local-variable&#34;&gt;super&lt;/span&gt;.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        com.qiyi.test.Test.getInstance().init();
        com.qiyi.test.Test.getInstance().start();

        TextView tv = findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());
    }

    &lt;span class=&#34;directive&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;directive&#34;&gt;native&lt;/span&gt; &lt;span class=&#34;predefined-type&#34;&gt;String&lt;/span&gt; stringFromJNI();
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;看到这里，经验丰富的同学鼻子应该已经动了一下。&lt;/p&gt;
&lt;p&gt;这个App自己先加载了一个 &lt;code&gt;native-lib&lt;/code&gt;，然后又通过 &lt;code&gt;Test.getInstance().init()&lt;/code&gt; 去加载另一个so，最后再调用 &lt;code&gt;start()&lt;/code&gt;。
这个结构就很适合拿来演示 &lt;mark&gt;Jadx看调用链，IDA看so实现&lt;/mark&gt;。&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Codexone/mainactivity-v2.png&#34; alt=&#34;mainactivity v2&#34; height=&#34;50&#34;/&gt;
&lt;figcaption&gt;1:mainactivity&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;Test.java&lt;/code&gt; 里面是这样的：&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;java&#34;&gt;&lt;span class=&#34;directive&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;type&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;class&#34;&gt;Test&lt;/span&gt; {
    &lt;span class=&#34;directive&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;directive&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;directive&#34;&gt;final&lt;/span&gt; Test ourInstance = &lt;span class=&#34;keyword&#34;&gt;new&lt;/span&gt; Test();

    &lt;span class=&#34;directive&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;directive&#34;&gt;static&lt;/span&gt; Test getInstance() {
        &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; ourInstance;
    }

    &lt;span class=&#34;directive&#34;&gt;private&lt;/span&gt; Test() {
    }

    &lt;span class=&#34;directive&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;directive&#34;&gt;synchronized&lt;/span&gt; &lt;span class=&#34;type&#34;&gt;void&lt;/span&gt; init() {
        &lt;span class=&#34;predefined-type&#34;&gt;System&lt;/span&gt;.loadLibrary(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;test&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
    }

    &lt;span class=&#34;directive&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;directive&#34;&gt;synchronized&lt;/span&gt; &lt;span class=&#34;type&#34;&gt;void&lt;/span&gt; start() {
        com.qiyi.test.NativeHandler.getInstance().start();
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;再看 &lt;code&gt;NativeHandler.java&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;java&#34;&gt;&lt;span class=&#34;directive&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;type&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;class&#34;&gt;NativeHandler&lt;/span&gt; {
    &lt;span class=&#34;directive&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;directive&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;directive&#34;&gt;final&lt;/span&gt; NativeHandler ourInstance = &lt;span class=&#34;keyword&#34;&gt;new&lt;/span&gt; NativeHandler();

    &lt;span class=&#34;directive&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;directive&#34;&gt;static&lt;/span&gt; NativeHandler getInstance() {
        &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; ourInstance;
    }

    &lt;span class=&#34;directive&#34;&gt;private&lt;/span&gt; NativeHandler() {
    }

    &lt;span class=&#34;directive&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;directive&#34;&gt;native&lt;/span&gt; &lt;span class=&#34;type&#34;&gt;void&lt;/span&gt; start();
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;到这里，其实已经很明确了：&lt;/p&gt;
&lt;div class=&#34;olist arabic&#34;&gt;&lt;ol class=&#34;arabic&#34;&gt;&lt;li&gt;Java层先加载 &lt;code&gt;native-lib&lt;/code&gt;&lt;/li&gt;&lt;li&gt;然后再加载 &lt;code&gt;test&lt;/code&gt;&lt;/li&gt;&lt;li&gt;最终 &lt;code&gt;NativeHandler.start()&lt;/code&gt; 这个native方法，大概率会落进 &lt;code&gt;libtest.so&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;如果是以前，我们下一步多半就是手工点Jadx，翻so，找JNI。
但今天咱们不自己干，今天要体验一下当李老板的快乐。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_三先让jadx干活&#34;&gt;三、先让Jadx干活&lt;/h2&gt;&lt;p&gt;先把APK丢给Jadx，然后在Codex里开口：&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;text&#34;&gt;连接 JADX MCP，先从 MainActivity 开始分析这个 APK 的调用链。重点找：
1. 哪些 so 被加载了
2. Java 层如何走到 native 方法
3. com.qiyi.test.Test 和 NativeHandler 分别负责什么
请用清晰的调用路径输出结果。&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Codexone/jadxprompt1-v2.png&#34; alt=&#34;jadxprompt1 v2&#34; height=&#34;50&#34;/&gt;
&lt;figcaption&gt;1:jadxprompt1&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;这种活很适合Jadx MCP。&lt;/p&gt;
&lt;p&gt;因为它擅长处理的，正是逆向前期最费手的那部分：&lt;/p&gt;
&lt;div class=&#34;olist arabic&#34;&gt;&lt;ol class=&#34;arabic&#34;&gt;&lt;li&gt;找类&lt;/li&gt;&lt;li&gt;找方法&lt;/li&gt;&lt;li&gt;找调用关系&lt;/li&gt;&lt;li&gt;先把零散入口收拢成一条主链&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;很快Codex就能把第一段链路摸出来：&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;text&#34;&gt;MainActivity.onCreate
  -&amp;gt; Test.getInstance().init()
  -&amp;gt; System.loadLibrary(&amp;#34;test&amp;#34;)
  -&amp;gt; Test.getInstance().start()
  -&amp;gt; NativeHandler.getInstance().start()
  -&amp;gt; native void start()&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Codexone/jadxresult1-v2.png&#34; alt=&#34;jadxresult1 v2&#34; height=&#34;50&#34;/&gt;
&lt;figcaption&gt;1:jadxresult1&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;这一步的价值看上去不惊艳，但很实用。&lt;/p&gt;
&lt;p&gt;因为很多时候逆向刚开始最烦的，不是算法太难，而是 &lt;mark&gt;入口太多&lt;/mark&gt;。
你明明知道东西在so里，但是Java层到底是谁把它调进去的，得先理顺。&lt;/p&gt;
&lt;p&gt;Jadx MCP 在这里干的活，本质上就是：&lt;/p&gt;
&lt;p&gt;“帮你先把门牌号找到。”&lt;/p&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_再追一步&#34;&gt;再追一步&lt;/h3&gt;&lt;p&gt;既然 &lt;code&gt;NativeHandler.start()&lt;/code&gt; 已经浮出来了，就继续让Codex问：&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;text&#34;&gt;继续在 JADX MCP 里分析 NativeHandler.start 对应的 native 声明位置，告诉我它最可能落到哪个 so，给出判断依据。&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这个问题比一句“帮我逆向一下”有效得多。&lt;/p&gt;
&lt;p&gt;范围收窄之后，Codex 给出的判断通常会稳很多。&lt;/p&gt;
&lt;p&gt;这里Codex通常会给出一个很合理的判断：&lt;/p&gt;
&lt;div class=&#34;olist arabic&#34;&gt;&lt;ol class=&#34;arabic&#34;&gt;&lt;li&gt;&lt;code&gt;NativeHandler.start()&lt;/code&gt; 是 native 方法&lt;/li&gt;&lt;li&gt;&lt;code&gt;Test.init()&lt;/code&gt; 显式加载了 &lt;code&gt;test&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;Test.start()&lt;/code&gt; 直接调用了 &lt;code&gt;NativeHandler.start()&lt;/code&gt;&lt;/li&gt;&lt;li&gt;所以这个native实现最可能在 &lt;code&gt;libtest.so&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;这一步的作用，不是立刻拍板结论，而是先把 native 落点缩到一个足够小的范围，方便后面进 IDA 继续核实。&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Codexone/jadxresult2-v2.png&#34; alt=&#34;jadxresult2 v2&#34; height=&#34;50&#34;/&gt;
&lt;figcaption&gt;1:jadxresult2&lt;/figcaption&gt;&lt;/figure&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_四轮到ida出场&#34;&gt;四、轮到IDA出场&lt;/h2&gt;&lt;p&gt;Jadx把Java层的路摸清楚之后，就该让IDA MCP接手了。&lt;/p&gt;
&lt;p&gt;这时候直接把 &lt;code&gt;libtest.so&lt;/code&gt; 丢进IDA，然后继续给Codex下命令：&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;text&#34;&gt;连接 IDA MCP，分析 libtest.so。
请优先做这几件事：
1. 列出导入函数和可疑入口
2. 查找 JNI 相关符号、JNI_OnLoad 或 native 注册痕迹
3. 判断 Java 层的 NativeHandler.start 最可能对应到 so 里的哪个实现
不要泛泛而谈，直接给定位过程。&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Codexone/idaprompt1-v2.png&#34; alt=&#34;idaprompt1 v2&#34; height=&#34;50&#34;/&gt;
&lt;figcaption&gt;1:idaprompt1&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;这个so有个特点，挺适合演示：&lt;/p&gt;
&lt;p&gt;它是个 stripped so。&lt;/p&gt;
&lt;p&gt;啥叫 stripped？
就是那种“脸洗得很干净，名字全没了”的状态。
你不能像看Java代码那样，直接看到一堆明晃晃的方法名。&lt;/p&gt;
&lt;p&gt;所以这时候IDA MCP的价值就出来了。&lt;/p&gt;
&lt;p&gt;它可以先看导入符号，再找JNI相关痕迹，再从函数行为去反推哪个地方像 &lt;code&gt;start()&lt;/code&gt; 的实现。&lt;/p&gt;
&lt;p&gt;这个so里比较显眼的一段逻辑，是对 &lt;code&gt;__android_log_print&lt;/code&gt; 做了处理。&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Codexone/idalibtest-v2.png&#34; alt=&#34;idalibtest v2&#34; height=&#34;50&#34;/&gt;
&lt;figcaption&gt;1:idalibtest&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;对应的native代码大概是这样：&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;directive&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;predefined-type&#34;&gt;int&lt;/span&gt; (*orig_log_print)(&lt;span class=&#34;predefined-type&#34;&gt;int&lt;/span&gt; prio, &lt;span class=&#34;directive&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;predefined-type&#34;&gt;char&lt;/span&gt;* tag, &lt;span class=&#34;directive&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;predefined-type&#34;&gt;char&lt;/span&gt;* fmt, ...);

&lt;span class=&#34;directive&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;predefined-type&#34;&gt;int&lt;/span&gt; my_libtest_log_print(&lt;span class=&#34;predefined-type&#34;&gt;int&lt;/span&gt; prio, &lt;span class=&#34;directive&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;predefined-type&#34;&gt;char&lt;/span&gt;* tag, &lt;span class=&#34;directive&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;predefined-type&#34;&gt;char&lt;/span&gt;* fmt, ...)
{
    va_list ap;
    &lt;span class=&#34;predefined-type&#34;&gt;char&lt;/span&gt; buf[&lt;span class=&#34;integer&#34;&gt;1024&lt;/span&gt;];
    &lt;span class=&#34;predefined-type&#34;&gt;int&lt;/span&gt; r;

    snprintf(buf, &lt;span class=&#34;keyword&#34;&gt;sizeof&lt;/span&gt;(buf), &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;[%s] %s&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, (&lt;span class=&#34;predefined-constant&#34;&gt;NULL&lt;/span&gt; == tag ? &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; : tag), (&lt;span class=&#34;predefined-constant&#34;&gt;NULL&lt;/span&gt; == fmt ? &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; : fmt));

    va_start(ap, fmt);
    r = __android_log_vprint(prio, &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;Dobby_libtest&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, buf, ap);
    va_end(ap);
    &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; r;
}

__attribute__((constructor)) &lt;span class=&#34;directive&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;directive&#34;&gt;void&lt;/span&gt; ctor() {
    DobbyHook((&lt;span class=&#34;directive&#34;&gt;void&lt;/span&gt; *) DobbySymbolResolver(&lt;span class=&#34;predefined-constant&#34;&gt;NULL&lt;/span&gt;, &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;__android_log_print&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;),
              (&lt;span class=&#34;directive&#34;&gt;void&lt;/span&gt; *) my_libtest_log_print,
              (&lt;span class=&#34;directive&#34;&gt;void&lt;/span&gt; **) &amp;amp;orig_log_print);
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;看到这段，基本味道就出来了。&lt;/p&gt;
&lt;p&gt;这不是单纯导出一个JNI函数完事，
它在库加载阶段就先用 &lt;code&gt;DobbyHook&lt;/code&gt; 把 &lt;code&gt;__android_log_print&lt;/code&gt; 给拦了。&lt;/p&gt;
&lt;p&gt;这就很适合写文章，因为它有戏剧性：&lt;/p&gt;
&lt;div class=&#34;olist arabic&#34;&gt;&lt;ol class=&#34;arabic&#34;&gt;&lt;li&gt;Java层负责把so请进来&lt;/li&gt;&lt;li&gt;so一进场就先动系统日志&lt;/li&gt;&lt;li&gt;然后再等Java层去调native方法&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_ida最擅长的是什么&#34;&gt;IDA最擅长的是什么&lt;/h3&gt;&lt;p&gt;很多同学会觉得，既然Jadx都能看Java层了，那IDA是不是只是锦上添花？&lt;/p&gt;
&lt;p&gt;还真不是。&lt;/p&gt;
&lt;p&gt;Jadx擅长的是：&lt;/p&gt;
&lt;div class=&#34;olist arabic&#34;&gt;&lt;ol class=&#34;arabic&#34;&gt;&lt;li&gt;帮你快速理解Java世界&lt;/li&gt;&lt;li&gt;找调用链&lt;/li&gt;&lt;li&gt;找native声明&lt;/li&gt;&lt;li&gt;看谁加载了哪个so&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;IDA擅长的是：&lt;/p&gt;
&lt;div class=&#34;olist arabic&#34;&gt;&lt;ol class=&#34;arabic&#34;&gt;&lt;li&gt;看so真实干了什么&lt;/li&gt;&lt;li&gt;在符号不全的时候继续往下走&lt;/li&gt;&lt;li&gt;看导入、交叉引用、构造函数、初始化逻辑&lt;/li&gt;&lt;li&gt;判断这段native代码到底是做计算、做注册、还是做hook&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;一个看楼上，一个看地下室。
你不能让Jadx去替IDA，也不能让IDA去替Jadx。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_五让codex两路会师&#34;&gt;五、让Codex两路会师&lt;/h2&gt;&lt;p&gt;前面这两步，单看都不新鲜。&lt;/p&gt;
&lt;p&gt;真正有意思的是第三步：
让Codex把两边结果收回来，自己拼成一条完整链路。&lt;/p&gt;
&lt;p&gt;这时候继续下指令：&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;text&#34;&gt;结合 JADX MCP 和 IDA MCP 的结果，把这条完整链路串起来：
MainActivity -&amp;gt; Test -&amp;gt; NativeHandler -&amp;gt; libtest.so
要求用逆向文章的写法输出，像是在给读者讲解，不要写成审计报告。&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Codexone/codexmerge-v2.png&#34; alt=&#34;codexmerge v2&#34; height=&#34;50&#34;/&gt;
&lt;figcaption&gt;1:codexmerge&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;这里我特意让它按“逆向讲解”的口吻来整理，目的很简单：输出要像一篇能直接拿来读的分析笔记，而不是一份生硬的审计摘要。&lt;/p&gt;
&lt;p&gt;Codex 收完两边结果之后，基本能整理出这样一条链路：&lt;/p&gt;
&lt;div class=&#34;olist arabic&#34;&gt;&lt;ol class=&#34;arabic&#34;&gt;&lt;li&gt;&lt;code&gt;MainActivity&lt;/code&gt; 启动时先加载 &lt;code&gt;native-lib&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;onCreate()&lt;/code&gt; 中调用 &lt;code&gt;Test.getInstance().init()&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;init()&lt;/code&gt; 里执行 &lt;code&gt;System.loadLibrary(&amp;#34;test&amp;#34;)&lt;/code&gt;，也就是加载 &lt;code&gt;libtest.so&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;libtest.so&lt;/code&gt; 在加载阶段通过 constructor 执行初始化逻辑&lt;/li&gt;&lt;li&gt;初始化逻辑里调用 &lt;code&gt;DobbyHook&lt;/code&gt;，把 &lt;code&gt;__android_log_print&lt;/code&gt; 做了替换&lt;/li&gt;&lt;li&gt;随后 Java 层执行 &lt;code&gt;Test.getInstance().start()&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;start()&lt;/code&gt; 再转到 &lt;code&gt;NativeHandler.start()&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;NativeHandler.start()&lt;/code&gt; 最终进入 &lt;code&gt;libtest.so&lt;/code&gt; 中对应的native实现&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;看到这里，文章的核心其实已经出来了。&lt;/p&gt;
&lt;p&gt;今天真正要演示的，不是某个算法有多牛。
而是 &lt;mark&gt;Codex 能不能替你把 Java 层和 Native 层的结果先串起来&lt;/mark&gt;。&lt;/p&gt;
&lt;p&gt;答案是：能，而且挺适合干这个。&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Codexone/callchain-v2.png&#34; alt=&#34;callchain v2&#34; height=&#34;50&#34;/&gt;
&lt;figcaption&gt;1:callchain&lt;/figcaption&gt;&lt;/figure&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_六再补一刀验证调用顺序&#34;&gt;六、再补一刀，验证调用顺序&lt;/h2&gt;&lt;p&gt;到这里，静态链路基本已经串起来了。
但逆向不能只停留在“看起来像”，最好还是再补一轮动态验证，把调用顺序真正钉死。&lt;/p&gt;
&lt;p&gt;这时候可以直接让 Codex 按当前上下文整理一版 Frida 验证思路：&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;text&#34;&gt;根据当前分析结果，生成一个 Frida hook 思路，验证 Java 层和 native 层的调用顺序，但不要写成大而全模板，只给关键点。&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Codexone/fridaprompt-v2.png&#34; alt=&#34;fridaprompt v2&#34; height=&#34;50&#34;/&gt;
&lt;figcaption&gt;1:fridaprompt&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;这时候让它出思路，会比一上来直接丢一句“写个 Frida 脚本”更靠谱。&lt;/p&gt;
&lt;p&gt;因为前面的上下文它已经都拿到了：&lt;/p&gt;
&lt;div class=&#34;olist arabic&#34;&gt;&lt;ol class=&#34;arabic&#34;&gt;&lt;li&gt;Java入口是谁&lt;/li&gt;&lt;li&gt;&lt;code&gt;System.loadLibrary(&amp;#34;test&amp;#34;)&lt;/code&gt; 在哪&lt;/li&gt;&lt;li&gt;&lt;code&gt;NativeHandler.start()&lt;/code&gt; 是关键点&lt;/li&gt;&lt;li&gt;&lt;code&gt;libtest.so&lt;/code&gt; 里还有日志hook行为&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;有了这些信息，再去生成 Hook 点位和验证顺序，命中率会高很多。&lt;/p&gt;
&lt;p&gt;这也是 MCP 最实用的地方之一：
先把样本喂到位，再让模型开口，输出通常会扎实不少。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_七总结&#34;&gt;七、总结&lt;/h2&gt;&lt;p&gt;以前的逆向流程，更像是你一个人左手拿Jadx，右手拿IDA，嘴里叼着Frida，脑子里还得记着前面谁调了谁。&lt;/p&gt;
&lt;p&gt;现在如果把Codex接进来，感觉就有点不一样了。&lt;/p&gt;
&lt;p&gt;它并不能直接替你变成逆向高手。
但它很适合先干这些活：&lt;/p&gt;
&lt;div class=&#34;olist arabic&#34;&gt;&lt;ol class=&#34;arabic&#34;&gt;&lt;li&gt;帮你找调用链&lt;/li&gt;&lt;li&gt;帮你整理类和方法关系&lt;/li&gt;&lt;li&gt;帮你在Jadx和IDA之间回收信息&lt;/li&gt;&lt;li&gt;帮你把“入口在哪、链路怎么走”先理顺&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;真正值钱的部分，还是你来判断：&lt;/p&gt;
&lt;div class=&#34;olist arabic&#34;&gt;&lt;ol class=&#34;arabic&#34;&gt;&lt;li&gt;这个native逻辑重要不重要&lt;/li&gt;&lt;li&gt;这个so里哪块值得深挖&lt;/li&gt;&lt;li&gt;这个Hook行为到底意味着什么&lt;/li&gt;&lt;li&gt;下一步是该上Frida，还是该继续IDA&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;说白了，Codex不是来抢你饭碗的。
它更像是刚入行的实习生，跑得快，记性好，不嫌累。
前提是你得告诉它先去哪、看什么、怎么回报。&lt;/p&gt;
&lt;p&gt;古法逆向有没有用？
当然有。&lt;/p&gt;
&lt;p&gt;但现在的问题已经不是“要不要用AI”，而是 &lt;mark&gt;你会不会让AI替你先把脏活干掉&lt;/mark&gt;。&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Codexone/ffshow-v2.png&#34; alt=&#34;ffshow v2&#34; height=&#34;50&#34;/&gt;
&lt;figcaption&gt;1:ffshow&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;mark&gt;多一双眼睛的人，不一定更聪明，但一定看得更快。&lt;/mark&gt;&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;本文目的仅限于交流逆向分析思路与技术方法，请勿用于任何非法用途，相关法律责任由使用者自行承担，与本文及作者无关。文中样本为自建 Demo。知识星球里我会补充这篇文章的完整提示词、操作截图、调用链整理方式，以及后续如何接 Frida 做动态验证。欢迎加入一起交流探讨，有问题也可以加我 wx：&lt;mark&gt;fenfei331&lt;/mark&gt;。&lt;/p&gt;&lt;/aside&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ffzsxq.jpg&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;
&lt;p&gt;关注微信公众号，最新技术干货实时推送&lt;/p&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ff330.png&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;&lt;/section&gt;&lt;/div&gt;&lt;footer&gt;&lt;div id=&#34;footer-text&#34;&gt;&lt;br/&gt;Last updated 2026-04-27 18:48:42 +0800&lt;/div&gt;&lt;/footer&gt;
</description>
      
    </item>
    
    <item>
      <title>Jadx也想要翅膀</title>
      <link>http://91fans.com.cn/post/jadxmcp/</link>
      <pubDate>Thu, 25 Dec 2025 16:38:38 +0800</pubDate>
      
      <guid>http://91fans.com.cn/post/jadxmcp/</guid>
      
        <description>&lt;meta charset=&#34;UTF-8&#34;/&gt;&lt;meta http-equiv=&#34;X-UA-Compatible&#34; content=&#34;IE=edge&#34;/&gt;&lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;/&gt;&lt;meta name=&#34;generator&#34; content=&#34;Asciidoctor 2.0.20&#34;/&gt;&lt;title&gt;一、目标&lt;/title&gt;&lt;style&gt;/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import &#34;https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700&#34;; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:&#34;\201C&#34; &#34;\201D&#34; &#34;\2018&#34; &#34;\2019&#34;}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock&gt;.content&gt;.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock&gt;.content&gt;.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:&#34; &#34;;display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])&gt;code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre&gt;code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:&#34;[&#34;;padding:0 3px 0 2px}
b.button::after{content:&#34;]&#34;;padding:0 2px 0 3px}
p a&gt;code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:&#34; &#34;;display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header&gt;h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header&gt;h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header&gt;h1:only-child,body.toc2 #header&gt;h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:&#34;\00a0\2013\00a0&#34;}
#header .details br+span.author::before{content:&#34;\00a0\22c5\00a0&#34;;color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:&#34;\00a0|\00a0&#34;}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:&#34;\00a0&#34;}
#content&gt;h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc&gt;ul{margin-left:.125em}
#toc ul.sectlevel0&gt;li&gt;a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2&gt;ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2&gt;ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc&gt;:first-child{margin-top:0}
#content #toc&gt;:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1&gt;a.anchor,h2&gt;a.anchor,h3&gt;a.anchor,#toctitle&gt;a.anchor,.sidebarblock&gt;.content&gt;.title&gt;a.anchor,h4&gt;a.anchor,h5&gt;a.anchor,h6&gt;a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1&gt;a.anchor::before,h2&gt;a.anchor::before,h3&gt;a.anchor::before,#toctitle&gt;a.anchor::before,.sidebarblock&gt;.content&gt;.title&gt;a.anchor::before,h4&gt;a.anchor::before,h5&gt;a.anchor::before,h6&gt;a.anchor::before{content:&#34;\00A7&#34;;font-size:.85em;display:block;padding-top:.1em}
#content h1:hover&gt;a.anchor,#content h1&gt;a.anchor:hover,h2:hover&gt;a.anchor,h2&gt;a.anchor:hover,h3:hover&gt;a.anchor,#toctitle:hover&gt;a.anchor,.sidebarblock&gt;.content&gt;.title:hover&gt;a.anchor,h3&gt;a.anchor:hover,#toctitle&gt;a.anchor:hover,.sidebarblock&gt;.content&gt;.title&gt;a.anchor:hover,h4:hover&gt;a.anchor,h4&gt;a.anchor:hover,h5:hover&gt;a.anchor,h5&gt;a.anchor:hover,h6:hover&gt;a.anchor,h6&gt;a.anchor:hover{visibility:visible}
#content h1&gt;a.link,h2&gt;a.link,h3&gt;a.link,#toctitle&gt;a.link,.sidebarblock&gt;.content&gt;.title&gt;a.link,h4&gt;a.link,h5&gt;a.link,h6&gt;a.link{color:#ba3925;text-decoration:none}
#content h1&gt;a.link:hover,h2&gt;a.link:hover,h3&gt;a.link:hover,#toctitle&gt;a.link:hover,.sidebarblock&gt;.content&gt;.title&gt;a.link:hover,h4&gt;a.link:hover,h5&gt;a.link:hover,h6&gt;a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details&gt;summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details&gt;summary::-webkit-details-marker{display:none}
details&gt;summary::before{content:&#34;&#34;;border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]&gt;summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details&gt;summary::after{content:&#34;&#34;;width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{text-rendering:optimizeLegibility;text-align:left;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content&gt;caption.title{white-space:nowrap;width:0}
.paragraph.lead&gt;p,#preamble&gt;.sectionbody&gt;[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock&gt;table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock&gt;table td.icon{text-align:center;width:80px}
.admonitionblock&gt;table td.icon img{max-width:none}
.admonitionblock&gt;table td.icon .title{font-weight:bold;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;text-transform:uppercase}
.admonitionblock&gt;table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock&gt;table td.content&gt;:last-child&gt;:last-child{margin-bottom:0}
.exampleblock&gt;.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock&gt;.content&gt;.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock&gt;.content&gt;:first-child,.sidebarblock&gt;.content&gt;:first-child{margin-top:0}
.exampleblock&gt;.content&gt;:last-child,.exampleblock&gt;.content&gt;:last-child&gt;:last-child,.exampleblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child&gt;:last-child,.sidebarblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child{margin-bottom:0}
.literalblock pre,.listingblock&gt;.content&gt;pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:1em}}
.literalblock pre,.listingblock&gt;.content&gt;pre:not(.highlight),.listingblock&gt;.content&gt;pre[class=highlight],.listingblock&gt;.content&gt;pre[class^=&#34;highlight &#34;]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock&gt;.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:&#34;$&#34;}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs&gt;code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)&gt;.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:&#34;\201c&#34;;float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote&gt;.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract&gt;.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt&gt;blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock&gt;.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock&gt;.content&gt;:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all&gt;*&gt;tr&gt;*{border-width:1px}
table.grid-cols&gt;*&gt;tr&gt;*{border-width:0 1px}
table.grid-rows&gt;*&gt;tr&gt;*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none&gt;colgroup+*&gt;:first-child&gt;*,table.frame-sides&gt;colgroup+*&gt;:first-child&gt;*{border-top-width:0}
table.frame-none&gt;:last-child&gt;:last-child&gt;*,table.frame-sides&gt;:last-child&gt;:last-child&gt;*{border-bottom-width:0}
table.frame-none&gt;*&gt;tr&gt;:first-child,table.frame-ends&gt;*&gt;tr&gt;:first-child{border-left-width:0}
table.frame-none&gt;*&gt;tr&gt;:last-child,table.frame-ends&gt;*&gt;tr&gt;:last-child{border-right-width:0}
table.stripes-all&gt;*&gt;tr,table.stripes-odd&gt;*&gt;tr:nth-of-type(odd),table.stripes-even&gt;*&gt;tr:nth-of-type(even),table.stripes-hover&gt;*&gt;tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock&gt;code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child&gt;:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li&gt;p:empty:only-child::before{content:&#34;&#34;;display:inline-block}
ul.checklist&gt;li&gt;p:first-child{margin-left:-1em}
ul.checklist&gt;li&gt;p:first-child&gt;.fa-square-o:first-child,ul.checklist&gt;li&gt;p:first-child&gt;.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist&gt;li&gt;p:first-child&gt;input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline&gt;li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist&gt;table,.colist&gt;table{border:0;background:none}
.hdlist&gt;table&gt;tbody&gt;tr,.colist&gt;table&gt;tbody&gt;tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock&gt;.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb&gt;.title,.imageblock.th&gt;.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon&gt;.fa{cursor:default}
a span.icon&gt;.fa{cursor:inherit}
.admonitionblock td.icon [class^=&#34;fa icon-&#34;]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:&#34;\f05a&#34;;color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:&#34;\f0eb&#34;;text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:&#34;\f071&#34;;color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:&#34;\f06d&#34;;color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:&#34;\f06a&#34;;color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock&gt;.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^=&#34;#&#34;],a[href^=&#34;mailto:&#34;]{text-decoration:none!important}
a[href^=&#34;http:&#34;]:not(.bare)::after,a[href^=&#34;https:&#34;]:not(.bare)::after{content:&#34;(&#34; attr(href) &#34;)&#34;;display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:&#34; (&#34; attr(title) &#34;)&#34;}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock&gt;.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header&gt;h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1&gt;h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header&gt;h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}&lt;/style&gt;
&lt;style&gt;
/*! Stylesheet for CodeRay to loosely match GitHub themes | MIT License */
pre.CodeRay{background:#f7f7f8}
.CodeRay .line-numbers{border-right:1px solid;opacity:.35;padding:0 .5em 0 0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.CodeRay span.line-numbers{display:inline-block;margin-right:.75em}
.CodeRay .line-numbers strong{color:#000}
table.CodeRay{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.CodeRay td{vertical-align:top;line-height:inherit}
table.CodeRay td.line-numbers{text-align:right}
table.CodeRay td.code{padding:0 0 0 .75em}
.CodeRay .debug{color:#fff!important;background:navy!important}
.CodeRay .annotation{color:#007}
.CodeRay .attribute-name{color:navy}
.CodeRay .attribute-value{color:#700}
.CodeRay .binary{color:#509}
.CodeRay .comment{color:#998;font-style:italic}
.CodeRay .char{color:#04d}
.CodeRay .char .content{color:#04d}
.CodeRay .char .delimiter{color:#039}
.CodeRay .class{color:#458;font-weight:bold}
.CodeRay .complex{color:#a08}
.CodeRay .constant,.CodeRay .predefined-constant{color:teal}
.CodeRay .color{color:#099}
.CodeRay .class-variable{color:#369}
.CodeRay .decorator{color:#b0b}
.CodeRay .definition{color:#099}
.CodeRay .delimiter{color:#000}
.CodeRay .doc{color:#970}
.CodeRay .doctype{color:#34b}
.CodeRay .doc-string{color:#d42}
.CodeRay .escape{color:#666}
.CodeRay .entity{color:#800}
.CodeRay .error{color:#808}
.CodeRay .exception{color:inherit}
.CodeRay .filename{color:#099}
.CodeRay .function{color:#900;font-weight:bold}
.CodeRay .global-variable{color:teal}
.CodeRay .hex{color:#058}
.CodeRay .integer,.CodeRay .float{color:#099}
.CodeRay .include{color:#555}
.CodeRay .inline{color:#000}
.CodeRay .inline .inline{background:#ccc}
.CodeRay .inline .inline .inline{background:#bbb}
.CodeRay .inline .inline-delimiter{color:#d14}
.CodeRay .inline-delimiter{color:#d14}
.CodeRay .important{color:#555;font-weight:bold}
.CodeRay .interpreted{color:#b2b}
.CodeRay .instance-variable{color:teal}
.CodeRay .label{color:#970}
.CodeRay .local-variable{color:#963}
.CodeRay .octal{color:#40e}
.CodeRay .predefined{color:#369}
.CodeRay .preprocessor{color:#579}
.CodeRay .pseudo-class{color:#555}
.CodeRay .directive{font-weight:bold}
.CodeRay .type{font-weight:bold}
.CodeRay .predefined-type{color:inherit}
.CodeRay .reserved,.CodeRay .keyword{color:#000;font-weight:bold}
.CodeRay .key{color:#808}
.CodeRay .key .delimiter{color:#606}
.CodeRay .key .char{color:#80f}
.CodeRay .value{color:#088}
.CodeRay .regexp .delimiter{color:#808}
.CodeRay .regexp .content{color:#808}
.CodeRay .regexp .modifier{color:#808}
.CodeRay .regexp .char{color:#d14}
.CodeRay .regexp .function{color:#404;font-weight:bold}
.CodeRay .string{color:#d20}
.CodeRay .string .string .string{background:#ffd0d0}
.CodeRay .string .content{color:#d14}
.CodeRay .string .char{color:#d14}
.CodeRay .string .delimiter{color:#d14}
.CodeRay .shell{color:#d14}
.CodeRay .shell .delimiter{color:#d14}
.CodeRay .symbol{color:#990073}
.CodeRay .symbol .content{color:#a60}
.CodeRay .symbol .delimiter{color:#630}
.CodeRay .tag{color:teal}
.CodeRay .tag-special{color:#d70}
.CodeRay .variable{color:#036}
.CodeRay .insert{background:#afa}
.CodeRay .delete{background:#faa}
.CodeRay .change{color:#aaf;background:#007}
.CodeRay .head{color:#f8f;background:#505}
.CodeRay .insert .insert{color:#080}
.CodeRay .delete .delete{color:#800}
.CodeRay .change .change{color:#66f}
.CodeRay .head .head{color:#f4f}
&lt;/style&gt;&lt;/head&gt;&lt;body class=&#34;article&#34;&gt;&lt;header&gt;&lt;/header&gt;&lt;div id=&#34;content&#34;&gt;&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_一目标&#34;&gt;一、目标&lt;/h2&gt;&lt;p&gt;Jadx : &amp;#34;我也很想进步，古法太繁琐了，现在的年轻人都玩不转。&amp;#34;&lt;/p&gt;
&lt;p&gt;fenfei : &amp;#34;这个可以有。&amp;#34;&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_二步骤&#34;&gt;二、步骤&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_安装&#34;&gt;安装&lt;/h3&gt;&lt;p&gt;mcp是什么咱们就不解释了，刚来的同学可以翻翻前情提要回顾一下 &lt;a href=&#34;http://91fans.com.cn/post/idamcp/&#34;&gt;http://91fans.com.cn/post/idamcp/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;今天我的新朋友是 &lt;mark&gt;jadx-ai-mcp&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/zinja-coder/jadx-ai-mcp&#34;&gt;https://github.com/zinja-coder/jadx-ai-mcp&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;她的安装分两部分&lt;/p&gt;
&lt;div class=&#34;ulist&#34;&gt;&lt;ul&gt;&lt;li&gt;去到 /Users/fenfei/Desktop/tool/jadx-1.5.3/bin 目录下面执行&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;./jadx plugins --install &amp;#34;github:zinja-coder:jadx-ai-mcp&amp;#34;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&#34;ulist&#34;&gt;&lt;ul&gt;&lt;li&gt;下载 &lt;mark&gt;jadx-mcp-server&lt;/mark&gt;  对接 AI 用&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/zinja-coder/jadx-ai-mcp/releases/download/v5.0.0/jadx-mcp-server-v5.0.0.zip&#34;&gt;https://github.com/zinja-coder/jadx-ai-mcp/releases/download/v5.0.0/jadx-mcp-server-v5.0.0.zip&lt;/a&gt;&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_开工&#34;&gt;开工&lt;/h3&gt;&lt;p&gt;找个软柿子捏一下&lt;/p&gt;
&lt;p&gt;就用之前的 &lt;a href=&#34;http://91fans.com.cn/post/txtread/&#34;&gt;http://91fans.com.cn/post/txtread/&lt;/a&gt; ,咱们换AI来搞
Jadx打开，然后 文件 → 首选项 → 插件&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Jadxmcp/jadxplugin.png&#34; alt=&#34;jadxplugin&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:jadxplugin&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;这说明插件部分安装OK&lt;/p&gt;
&lt;p&gt;然后给 AI IDE 配置上 MCP Server&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;{
  &amp;#34;mcpServers&amp;#34;: {
    &amp;#34;jadx&amp;#34;: {
      &amp;#34;command&amp;#34;: &amp;#34;/opt/miniconda3/envs/jadxmcp/bin/python&amp;#34;,
      &amp;#34;args&amp;#34;: [
        &amp;#34;/Users/fenfei/Desktop/tool/jadx-mcp-server/jadx_mcp_server.py&amp;#34;
      ],
      &amp;#34;alwaysAllow&amp;#34;: [
        &amp;#34;get_android_manifest&amp;#34;,
        &amp;#34;search_classes_by_keyword&amp;#34;,
        &amp;#34;get_class_source&amp;#34;,
        &amp;#34;search_method_by_name&amp;#34;
      ]
    }
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;细心的同学可能发现和之前IDA的MCP配置有很大的不一样。&lt;/p&gt;
&lt;p&gt;AI这玩意还在迅猛发展，百家争鸣，所以MCP的协议有很多种，具体这两种协议哪种先进，可以问问 AI。&lt;/p&gt;
&lt;p&gt;咱们是实用主义着，先不纠结原理了，连上了就行，在 AI IDE里呼唤神龙…​&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;连接jadx mcp, 定位 token=rOW60Ct5iGxgRX0Olulcz9IXtWiGmAO7cbL7Y%2FU0tOc%3D 这个 token计算的位置，然后写个Frida hook 脚本&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;然后就是默默的等待，想起了 Chrome的恐龙游戏，我感觉在等待 AI干活的过程中，应该来个 &lt;mark&gt;是男人就下500层&lt;/mark&gt; 的小游戏。怪不得李老板喜欢玩扫雷，原来他把我当AI了，发布命令，然后边玩扫雷，边等我的结果。&lt;/p&gt;
&lt;p&gt;有了AI 咱们也能过上李老板的日子了，越来越有盼头了。&lt;/p&gt;
&lt;p&gt;AI 写完了， 我就不贴代码了， (小声告诉你，贴 &lt;mark&gt;知识星球&lt;/mark&gt; 了)&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;任务完成
已成功定位token计算位置并创建Frida hook脚本 token_hook.js

Token生成流程分析
根据反编译代码，token rOW60Ct5iGxgRX0Olulcz9IXtWiGmAO7cbL7Y%2FU0tOc%3D 的生成流程：

主要方法: Token.Companion.m() - getToken方法

输入: URI路径 + 参数Map
计算: hash_timestamp 格式的字符串
使用AES加密（密钥: 7A3II/M5Ja0S4gdf）
Hash计算: Token.Companion.k()

拼接: uri + 排序后的参数 + &amp;#34;mVjdXyqwjlEptwYY&amp;#34;
使用MurmurHash算法计算hash值
AES加密: AES.Companion.b()
算法: AES/CBC/PKCS5Padding
密钥: 7A3II/M5Ja0S4gdf
IV: 16-Bytes--String
输出: Base64编码
Hook脚本功能
脚本会拦截以下关键方法：

Token.getToken() - 捕获token生成
MurmurHash.d() - 捕获hash计算
AES.encodeAES() / AES.decodeAES() - 捕获加解密
SignatureUtil.sign() - 捕获签名生成
Token.getHash() - 捕获内部hash计算
Token.getUrlParamsByMap() - 捕获参数拼接
使用方法：

frida -U -f &amp;lt;包名&amp;gt; -l token_hook.js --no-pause&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;说的有模有样的，赶紧跑下代码试试。&lt;/p&gt;
&lt;p&gt;我去，没效果&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;不对 没有hook到&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;AI 又开始干活了，咱们继续扫雷。&lt;/p&gt;
&lt;p&gt;过了几分钟，新的代码又搞完了，继续跑。 还是没有效果&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;还是没有&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;AI 继续干活，咕嘟嘟，干了一通，扔给我了一个新的代码&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;[+] TokenUtil.f() - Calculate Hash
    Input1: /v1/category/female
    Input2: channel=zxf2019_19206_001&amp;amp;os=Android&amp;amp;package=cn.ttkmfxs.novel&amp;amp;udid=01bb90d6de80f3cb01bb90d6de80f3cb&amp;amp;v=3.3.24.R
    Hash: -1926105764

[+] TokenUtil.e() - AES Encrypt
    Plain: -1926105764_1766754803859

[+] AES.b() - Encrypt
    Value: -1926105764_1766754803859
    Key: @cLjKxIl7hlto3tR
    Encrypted: nADo5PoDE0nEwN6gKB9L8WF9OzAmwqviEgy/ljE1DI0=
    Encrypted: nADo5PoDE0nEwN6gKB9L8WF9OzAmwqviEgy/ljE1DI0=
    Generated Token (URL encoded): nADo5PoDE0nEwN6gKB9L8WF9OzAmwqviEgy%2FljE1DI0%3D&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;oh yeah，这次成功了。感觉和玩大转盘差不多，多玩几次，总会有惊喜。&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;frida多准备几个版本，有时候v17不好使，我还能继续上v16.x&lt;/p&gt;&lt;/aside&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_三总结&#34;&gt;三、总结&lt;/h2&gt;&lt;p&gt;有种赛博求签的感觉，心诚则灵。理解了有些人有事就扑通跪倒在佛像前面，感情佛祖也是AI的一种。&lt;/p&gt;
&lt;p&gt;基本功还是得有的，不然被ai骗人都不知道咋回事。&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Jadxmcp/ffshow.png&#34; alt=&#34;ffshow&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ffshow&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;mark&gt;天地无穷期，生命则有穷期，去一日，便少一日；富贵有定数，学问则无定数，求一分，便得一分。&lt;/mark&gt;&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;: 本文的目的只有一个就是学习更多的逆向技巧和思路，如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担，和本文以及作者没关系，本文涉及到的代码项目可以去 &lt;mark&gt;奋飞的朋友们&lt;/mark&gt; 知识星球自取，欢迎加入知识星球一起学习探讨技术。有问题可以加我wx: &lt;mark&gt;fenfei331&lt;/mark&gt; 讨论下。&lt;/p&gt;&lt;/aside&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ffzsxq.jpg&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;
&lt;p&gt;关注微信公众号，最新技术干货实时推送&lt;/p&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ff330.png&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;&lt;/section&gt;&lt;/div&gt;&lt;footer&gt;&lt;div id=&#34;footer-text&#34;&gt;&lt;br/&gt;Last updated 2026-04-27 18:48:43 +0800&lt;/div&gt;&lt;/footer&gt;
</description>
      
    </item>
    
    <item>
      <title>不让我用？这个真不能忍 - 某视频App强制启动</title>
      <link>http://91fans.com.cn/post/gvpshow/</link>
      <pubDate>Sat, 20 Dec 2025 10:09:49 +0800</pubDate>
      
      <guid>http://91fans.com.cn/post/gvpshow/</guid>
      
        <description>&lt;meta charset=&#34;UTF-8&#34;/&gt;&lt;meta http-equiv=&#34;X-UA-Compatible&#34; content=&#34;IE=edge&#34;/&gt;&lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;/&gt;&lt;meta name=&#34;generator&#34; content=&#34;Asciidoctor 2.0.20&#34;/&gt;&lt;title&gt;一、目标&lt;/title&gt;&lt;style&gt;/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import &#34;https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700&#34;; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:&#34;\201C&#34; &#34;\201D&#34; &#34;\2018&#34; &#34;\2019&#34;}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock&gt;.content&gt;.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock&gt;.content&gt;.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:&#34; &#34;;display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])&gt;code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre&gt;code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:&#34;[&#34;;padding:0 3px 0 2px}
b.button::after{content:&#34;]&#34;;padding:0 2px 0 3px}
p a&gt;code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:&#34; &#34;;display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header&gt;h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header&gt;h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header&gt;h1:only-child,body.toc2 #header&gt;h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:&#34;\00a0\2013\00a0&#34;}
#header .details br+span.author::before{content:&#34;\00a0\22c5\00a0&#34;;color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:&#34;\00a0|\00a0&#34;}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:&#34;\00a0&#34;}
#content&gt;h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc&gt;ul{margin-left:.125em}
#toc ul.sectlevel0&gt;li&gt;a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2&gt;ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2&gt;ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc&gt;:first-child{margin-top:0}
#content #toc&gt;:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1&gt;a.anchor,h2&gt;a.anchor,h3&gt;a.anchor,#toctitle&gt;a.anchor,.sidebarblock&gt;.content&gt;.title&gt;a.anchor,h4&gt;a.anchor,h5&gt;a.anchor,h6&gt;a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1&gt;a.anchor::before,h2&gt;a.anchor::before,h3&gt;a.anchor::before,#toctitle&gt;a.anchor::before,.sidebarblock&gt;.content&gt;.title&gt;a.anchor::before,h4&gt;a.anchor::before,h5&gt;a.anchor::before,h6&gt;a.anchor::before{content:&#34;\00A7&#34;;font-size:.85em;display:block;padding-top:.1em}
#content h1:hover&gt;a.anchor,#content h1&gt;a.anchor:hover,h2:hover&gt;a.anchor,h2&gt;a.anchor:hover,h3:hover&gt;a.anchor,#toctitle:hover&gt;a.anchor,.sidebarblock&gt;.content&gt;.title:hover&gt;a.anchor,h3&gt;a.anchor:hover,#toctitle&gt;a.anchor:hover,.sidebarblock&gt;.content&gt;.title&gt;a.anchor:hover,h4:hover&gt;a.anchor,h4&gt;a.anchor:hover,h5:hover&gt;a.anchor,h5&gt;a.anchor:hover,h6:hover&gt;a.anchor,h6&gt;a.anchor:hover{visibility:visible}
#content h1&gt;a.link,h2&gt;a.link,h3&gt;a.link,#toctitle&gt;a.link,.sidebarblock&gt;.content&gt;.title&gt;a.link,h4&gt;a.link,h5&gt;a.link,h6&gt;a.link{color:#ba3925;text-decoration:none}
#content h1&gt;a.link:hover,h2&gt;a.link:hover,h3&gt;a.link:hover,#toctitle&gt;a.link:hover,.sidebarblock&gt;.content&gt;.title&gt;a.link:hover,h4&gt;a.link:hover,h5&gt;a.link:hover,h6&gt;a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details&gt;summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details&gt;summary::-webkit-details-marker{display:none}
details&gt;summary::before{content:&#34;&#34;;border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]&gt;summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details&gt;summary::after{content:&#34;&#34;;width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{text-rendering:optimizeLegibility;text-align:left;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content&gt;caption.title{white-space:nowrap;width:0}
.paragraph.lead&gt;p,#preamble&gt;.sectionbody&gt;[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock&gt;table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock&gt;table td.icon{text-align:center;width:80px}
.admonitionblock&gt;table td.icon img{max-width:none}
.admonitionblock&gt;table td.icon .title{font-weight:bold;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;text-transform:uppercase}
.admonitionblock&gt;table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock&gt;table td.content&gt;:last-child&gt;:last-child{margin-bottom:0}
.exampleblock&gt;.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock&gt;.content&gt;.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock&gt;.content&gt;:first-child,.sidebarblock&gt;.content&gt;:first-child{margin-top:0}
.exampleblock&gt;.content&gt;:last-child,.exampleblock&gt;.content&gt;:last-child&gt;:last-child,.exampleblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child&gt;:last-child,.sidebarblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child{margin-bottom:0}
.literalblock pre,.listingblock&gt;.content&gt;pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:1em}}
.literalblock pre,.listingblock&gt;.content&gt;pre:not(.highlight),.listingblock&gt;.content&gt;pre[class=highlight],.listingblock&gt;.content&gt;pre[class^=&#34;highlight &#34;]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock&gt;.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:&#34;$&#34;}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs&gt;code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)&gt;.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:&#34;\201c&#34;;float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote&gt;.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract&gt;.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt&gt;blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock&gt;.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock&gt;.content&gt;:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all&gt;*&gt;tr&gt;*{border-width:1px}
table.grid-cols&gt;*&gt;tr&gt;*{border-width:0 1px}
table.grid-rows&gt;*&gt;tr&gt;*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none&gt;colgroup+*&gt;:first-child&gt;*,table.frame-sides&gt;colgroup+*&gt;:first-child&gt;*{border-top-width:0}
table.frame-none&gt;:last-child&gt;:last-child&gt;*,table.frame-sides&gt;:last-child&gt;:last-child&gt;*{border-bottom-width:0}
table.frame-none&gt;*&gt;tr&gt;:first-child,table.frame-ends&gt;*&gt;tr&gt;:first-child{border-left-width:0}
table.frame-none&gt;*&gt;tr&gt;:last-child,table.frame-ends&gt;*&gt;tr&gt;:last-child{border-right-width:0}
table.stripes-all&gt;*&gt;tr,table.stripes-odd&gt;*&gt;tr:nth-of-type(odd),table.stripes-even&gt;*&gt;tr:nth-of-type(even),table.stripes-hover&gt;*&gt;tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock&gt;code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child&gt;:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li&gt;p:empty:only-child::before{content:&#34;&#34;;display:inline-block}
ul.checklist&gt;li&gt;p:first-child{margin-left:-1em}
ul.checklist&gt;li&gt;p:first-child&gt;.fa-square-o:first-child,ul.checklist&gt;li&gt;p:first-child&gt;.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist&gt;li&gt;p:first-child&gt;input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline&gt;li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist&gt;table,.colist&gt;table{border:0;background:none}
.hdlist&gt;table&gt;tbody&gt;tr,.colist&gt;table&gt;tbody&gt;tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock&gt;.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb&gt;.title,.imageblock.th&gt;.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon&gt;.fa{cursor:default}
a span.icon&gt;.fa{cursor:inherit}
.admonitionblock td.icon [class^=&#34;fa icon-&#34;]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:&#34;\f05a&#34;;color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:&#34;\f0eb&#34;;text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:&#34;\f071&#34;;color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:&#34;\f06d&#34;;color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:&#34;\f06a&#34;;color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock&gt;.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^=&#34;#&#34;],a[href^=&#34;mailto:&#34;]{text-decoration:none!important}
a[href^=&#34;http:&#34;]:not(.bare)::after,a[href^=&#34;https:&#34;]:not(.bare)::after{content:&#34;(&#34; attr(href) &#34;)&#34;;display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:&#34; (&#34; attr(title) &#34;)&#34;}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock&gt;.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header&gt;h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1&gt;h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header&gt;h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}&lt;/style&gt;
&lt;style&gt;
/*! Stylesheet for CodeRay to loosely match GitHub themes | MIT License */
pre.CodeRay{background:#f7f7f8}
.CodeRay .line-numbers{border-right:1px solid;opacity:.35;padding:0 .5em 0 0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.CodeRay span.line-numbers{display:inline-block;margin-right:.75em}
.CodeRay .line-numbers strong{color:#000}
table.CodeRay{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.CodeRay td{vertical-align:top;line-height:inherit}
table.CodeRay td.line-numbers{text-align:right}
table.CodeRay td.code{padding:0 0 0 .75em}
.CodeRay .debug{color:#fff!important;background:navy!important}
.CodeRay .annotation{color:#007}
.CodeRay .attribute-name{color:navy}
.CodeRay .attribute-value{color:#700}
.CodeRay .binary{color:#509}
.CodeRay .comment{color:#998;font-style:italic}
.CodeRay .char{color:#04d}
.CodeRay .char .content{color:#04d}
.CodeRay .char .delimiter{color:#039}
.CodeRay .class{color:#458;font-weight:bold}
.CodeRay .complex{color:#a08}
.CodeRay .constant,.CodeRay .predefined-constant{color:teal}
.CodeRay .color{color:#099}
.CodeRay .class-variable{color:#369}
.CodeRay .decorator{color:#b0b}
.CodeRay .definition{color:#099}
.CodeRay .delimiter{color:#000}
.CodeRay .doc{color:#970}
.CodeRay .doctype{color:#34b}
.CodeRay .doc-string{color:#d42}
.CodeRay .escape{color:#666}
.CodeRay .entity{color:#800}
.CodeRay .error{color:#808}
.CodeRay .exception{color:inherit}
.CodeRay .filename{color:#099}
.CodeRay .function{color:#900;font-weight:bold}
.CodeRay .global-variable{color:teal}
.CodeRay .hex{color:#058}
.CodeRay .integer,.CodeRay .float{color:#099}
.CodeRay .include{color:#555}
.CodeRay .inline{color:#000}
.CodeRay .inline .inline{background:#ccc}
.CodeRay .inline .inline .inline{background:#bbb}
.CodeRay .inline .inline-delimiter{color:#d14}
.CodeRay .inline-delimiter{color:#d14}
.CodeRay .important{color:#555;font-weight:bold}
.CodeRay .interpreted{color:#b2b}
.CodeRay .instance-variable{color:teal}
.CodeRay .label{color:#970}
.CodeRay .local-variable{color:#963}
.CodeRay .octal{color:#40e}
.CodeRay .predefined{color:#369}
.CodeRay .preprocessor{color:#579}
.CodeRay .pseudo-class{color:#555}
.CodeRay .directive{font-weight:bold}
.CodeRay .type{font-weight:bold}
.CodeRay .predefined-type{color:inherit}
.CodeRay .reserved,.CodeRay .keyword{color:#000;font-weight:bold}
.CodeRay .key{color:#808}
.CodeRay .key .delimiter{color:#606}
.CodeRay .key .char{color:#80f}
.CodeRay .value{color:#088}
.CodeRay .regexp .delimiter{color:#808}
.CodeRay .regexp .content{color:#808}
.CodeRay .regexp .modifier{color:#808}
.CodeRay .regexp .char{color:#d14}
.CodeRay .regexp .function{color:#404;font-weight:bold}
.CodeRay .string{color:#d20}
.CodeRay .string .string .string{background:#ffd0d0}
.CodeRay .string .content{color:#d14}
.CodeRay .string .char{color:#d14}
.CodeRay .string .delimiter{color:#d14}
.CodeRay .shell{color:#d14}
.CodeRay .shell .delimiter{color:#d14}
.CodeRay .symbol{color:#990073}
.CodeRay .symbol .content{color:#a60}
.CodeRay .symbol .delimiter{color:#630}
.CodeRay .tag{color:teal}
.CodeRay .tag-special{color:#d70}
.CodeRay .variable{color:#036}
.CodeRay .insert{background:#afa}
.CodeRay .delete{background:#faa}
.CodeRay .change{color:#aaf;background:#007}
.CodeRay .head{color:#f8f;background:#505}
.CodeRay .insert .insert{color:#080}
.CodeRay .delete .delete{color:#800}
.CodeRay .change .change{color:#66f}
.CodeRay .head .head{color:#f4f}
&lt;/style&gt;&lt;/head&gt;&lt;body class=&#34;article&#34;&gt;&lt;header&gt;&lt;/header&gt;&lt;div id=&#34;content&#34;&gt;&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_一目标&#34;&gt;一、目标&lt;/h2&gt;&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Gvpshow/show.png&#34; alt=&#34;show&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:show&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;朋友给我发了一个看直播的App,刚一启动，硕大的弹窗就崩脸上了。这个真忍不了，盘它。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_二步骤&#34;&gt;二、步骤&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_jadx&#34;&gt;Jadx&lt;/h3&gt;&lt;p&gt;先给他拆开，搜字符串， &lt;mark&gt;激活本应用&lt;/mark&gt;&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;&amp;lt;string name=&amp;#34;unknown_device&amp;#34;&amp;gt;当前设备暂不支持激活本应用。&amp;lt;/string&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;代码里面没找到痕迹，在资源里面居然找到了。 反编译的类列表太干净了，感觉可能加固了。&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Gvpshow/findstr.png&#34; alt=&#34;findstr&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:show&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;也没有发现这个字符串在代码中被调用的地方，肯定是加固了&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_关门上ai&#34;&gt;关门，上AI&lt;/h3&gt;&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;万能的AI，帮我生成一个 Frida hook脚本，捕获 res/layout/dialog_double_button.xml 弹窗显示位置和堆栈，&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;有了AI，人人都是工程师&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;&lt;span class=&#34;comment&#34;&gt;// Hook AlertDialog.show()&lt;/span&gt;
&lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; AlertDialog = Java.use(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;android.app.AlertDialog&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
AlertDialog.show.&lt;span class=&#34;function&#34;&gt;implementation&lt;/span&gt; = &lt;span class=&#34;keyword&#34;&gt;function&lt;/span&gt;() {
    console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;================================================================================&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
    console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;[*] AlertDialog.show() 被调用 &lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
    console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;================================================================================&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);

    console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;[*] 调用堆栈:&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
    console.log(Java.use(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;android.util.Log&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;).getStackTraceString(Java.use(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;java.lang.Exception&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;).&lt;span class=&#34;predefined&#34;&gt;$new&lt;/span&gt;()));
    console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;================================================================================&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);

    &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;local-variable&#34;&gt;this&lt;/span&gt;.show();
};&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;跑一下，没反应，frida直接挂了。&lt;/p&gt;
&lt;p&gt;先不急着问AI，咱们之前分析这个App大概率加固了，所以检测frida应该是基操。&lt;/p&gt;
&lt;p&gt;咱们换上魔改版的Frida&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/Ylarod/Florida&#34;&gt;https://github.com/Ylarod/Florida&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;再跑一下&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;================================================================================
[*] AlertDialog.show() 被调用
================================================================================

[*] 调用堆栈:
java.lang.Exception
        at android.app.Dialog.show(Native Method)
        at com.gXXX.tv.gXX.utils.x2.a(NoticeUtils.java:125)
        at com.gXXX.tv.gXX.activity.BaseActivity.g(BaseActivity.java:1)
        at com.gXXX.tv.gXX.activity.BaseActivity.onLoginEvent(BaseActivity.java:6)
        at com.gXXX.tv.gXX.activity.WelcomeActivity.onLoginEvent(WelcomeActivity.java:1)
        at java.lang.reflect.Method.invoke(Native Method)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这次比较顺利，逮住了&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_脱壳&#34;&gt;脱壳&lt;/h3&gt;&lt;p&gt;这次脱壳用的是老朋友 BlackDex&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/ZiTanIOI/newBlackDex&#34;&gt;https://github.com/ZiTanIOI/newBlackDex&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这次感觉是猛壳，所以在软件设置里 勾上 深度脱壳和主动调用&lt;/p&gt;
&lt;p&gt;双手合十，默念 &lt;mark&gt;芝麻开门&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;图灵保佑，壳拖出来了。&lt;/p&gt;
&lt;p&gt;Jadx一下，然后搜索 &lt;mark&gt;onLoginEvent&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;打开 BaseActivity.onLoginEvent&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Gvpshow/onLogin.png&#34; alt=&#34;onLogin&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:login&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;这哥们也真累，一堆判断，一言不合就掀桌子退出。&lt;/p&gt;
&lt;p&gt;不怕，哥是有AI的，把整个onLoginEvent函数的代码喂给AI&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;请帮我生成Frida Hook脚本，hook住onLoginEvent函数的所有判断，定位一下到底是在哪里退出的。&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;吭哧吭哧，AI给我生成了一堆代码，看的眼花缭乱。&lt;/p&gt;
&lt;p&gt;这不行，还得古法上，硅基暂时让步，碳基上位。我们观察一下这个函数的代码还是很规整的， &lt;mark&gt;每次判断退出都会有提示&lt;/mark&gt;。&lt;/p&gt;
&lt;p&gt;呼唤AI&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;请帮我生成Frida Hook脚本，hook住com.gXXX.tv.gXX.activity.BaseActivity.c , 加上异常处理，没有找到这个类就100毫秒之后重试 。&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;因为这个是加壳应用，所以需要给壳一个解密的时间，直接hook是找不到 &lt;mark&gt;com.gXXX.tv.gXX.activity.BaseActivity&lt;/mark&gt; 类的。&lt;/p&gt;
&lt;p&gt;AI写的代码就是漂亮&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;Java.perform(&lt;span class=&#34;keyword&#34;&gt;function&lt;/span&gt;() {
    console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;[*] 开始Hook BaseActivity.c&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);

    &lt;span class=&#34;keyword&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;function&#34;&gt;tryHook&lt;/span&gt;() {
        &lt;span class=&#34;keyword&#34;&gt;try&lt;/span&gt; {
            &lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; BaseActivity = Java.use(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;com.gXXX.tv.gXX.activity.BaseActivity&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);

            BaseActivity[&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;].overload(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;java.lang.String&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;).&lt;span class=&#34;function&#34;&gt;implementation&lt;/span&gt; = &lt;span class=&#34;keyword&#34;&gt;function&lt;/span&gt;(str) {
                console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;BaseActivity.c is called: str=&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; + str);
                &lt;span class=&#34;local-variable&#34;&gt;this&lt;/span&gt;[&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;](str);
            };


            console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;[+] BaseActivity.c Hook成功&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
            &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;predefined-constant&#34;&gt;true&lt;/span&gt;;

        } &lt;span class=&#34;keyword&#34;&gt;catch&lt;/span&gt; (e) {
            console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;[-] Hook失败: &lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; + e.message);
            &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;predefined-constant&#34;&gt;false&lt;/span&gt;;
        }
    }

    &lt;span class=&#34;keyword&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;function&#34;&gt;hookWithRetry&lt;/span&gt;() {
        &lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; (!tryHook()) {
            console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;[*] 100ms后重试...&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
            setTimeout(hookWithRetry, &lt;span class=&#34;integer&#34;&gt;100&lt;/span&gt;);
        }
    }

    hookWithRetry();
});&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;好了，发现提示&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;onLoginEvent false showErrorTerminalDialog and SendErrorPingback&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;原来第一个判断 &lt;mark&gt;isTerminalFailStatus&lt;/mark&gt; 就挂掉了&lt;/p&gt;
&lt;p&gt;啥也不说了，增加一个 Hook&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;let BaseLoginTask = Java.use(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;com.gXXX.tv.gXX.service.task.BaseLoginTask&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
BaseLoginTask[&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;isTerminalFailStatus&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;].&lt;span class=&#34;function&#34;&gt;implementation&lt;/span&gt; = &lt;span class=&#34;keyword&#34;&gt;function&lt;/span&gt; (i) {
    console.log(&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;BaseLoginTask.isTerminalFailStatus is called: i=&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{i}&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;);
    let result = &lt;span class=&#34;local-variable&#34;&gt;this&lt;/span&gt;[&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;isTerminalFailStatus&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;](i);
    console.log(&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;BaseLoginTask.isTerminalFailStatus result=&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{result}&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;);
    &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;predefined-constant&#34;&gt;false&lt;/span&gt;;
    &lt;span class=&#34;comment&#34;&gt;// return result;&lt;/span&gt;
};&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;完美收工。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_三总结&#34;&gt;三、总结&lt;/h2&gt;&lt;p&gt;不要给你的对手太明显的提示。&lt;/p&gt;
&lt;p&gt;不要太相信AI，如果你不知道自己在干什么，AI也不知道。&lt;/p&gt;
&lt;p&gt;脱壳是玄学，多试几个方案，万一运气到了呢？&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Gvpshow/ffshow.png&#34; alt=&#34;ffshow&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ffshow&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;mark&gt;雪之妙在能积，云之妙在不留，月之妙在有圆有缺&lt;/mark&gt;&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;: 本文的目的只有一个就是学习更多的逆向技巧和思路，如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担，和本文以及作者没关系，本文涉及到的代码项目可以去 &lt;mark&gt;奋飞的朋友们&lt;/mark&gt; 知识星球自取，欢迎加入知识星球一起学习探讨技术。有问题可以加我wx: &lt;mark&gt;fenfei331&lt;/mark&gt; 讨论下。&lt;/p&gt;&lt;/aside&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ffzsxq.jpg&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;
&lt;p&gt;关注微信公众号，最新技术干货实时推送&lt;/p&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ff330.png&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;&lt;/section&gt;&lt;/div&gt;&lt;footer&gt;&lt;div id=&#34;footer-text&#34;&gt;&lt;br/&gt;Last updated 2026-04-27 18:48:43 +0800&lt;/div&gt;&lt;/footer&gt;
</description>
      
    </item>
    
    <item>
      <title>给你的Ida插上翅膀</title>
      <link>http://91fans.com.cn/post/idamcp/</link>
      <pubDate>Fri, 19 Dec 2025 11:46:43 +0800</pubDate>
      
      <guid>http://91fans.com.cn/post/idamcp/</guid>
      
        <description>&lt;meta charset=&#34;UTF-8&#34;/&gt;&lt;meta http-equiv=&#34;X-UA-Compatible&#34; content=&#34;IE=edge&#34;/&gt;&lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;/&gt;&lt;meta name=&#34;generator&#34; content=&#34;Asciidoctor 2.0.20&#34;/&gt;&lt;title&gt;一、目标&lt;/title&gt;&lt;style&gt;/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import &#34;https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700&#34;; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:&#34;\201C&#34; &#34;\201D&#34; &#34;\2018&#34; &#34;\2019&#34;}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock&gt;.content&gt;.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock&gt;.content&gt;.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:&#34; &#34;;display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])&gt;code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre&gt;code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:&#34;[&#34;;padding:0 3px 0 2px}
b.button::after{content:&#34;]&#34;;padding:0 2px 0 3px}
p a&gt;code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:&#34; &#34;;display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header&gt;h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header&gt;h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header&gt;h1:only-child,body.toc2 #header&gt;h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:&#34;\00a0\2013\00a0&#34;}
#header .details br+span.author::before{content:&#34;\00a0\22c5\00a0&#34;;color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:&#34;\00a0|\00a0&#34;}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:&#34;\00a0&#34;}
#content&gt;h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc&gt;ul{margin-left:.125em}
#toc ul.sectlevel0&gt;li&gt;a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2&gt;ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2&gt;ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc&gt;:first-child{margin-top:0}
#content #toc&gt;:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1&gt;a.anchor,h2&gt;a.anchor,h3&gt;a.anchor,#toctitle&gt;a.anchor,.sidebarblock&gt;.content&gt;.title&gt;a.anchor,h4&gt;a.anchor,h5&gt;a.anchor,h6&gt;a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1&gt;a.anchor::before,h2&gt;a.anchor::before,h3&gt;a.anchor::before,#toctitle&gt;a.anchor::before,.sidebarblock&gt;.content&gt;.title&gt;a.anchor::before,h4&gt;a.anchor::before,h5&gt;a.anchor::before,h6&gt;a.anchor::before{content:&#34;\00A7&#34;;font-size:.85em;display:block;padding-top:.1em}
#content h1:hover&gt;a.anchor,#content h1&gt;a.anchor:hover,h2:hover&gt;a.anchor,h2&gt;a.anchor:hover,h3:hover&gt;a.anchor,#toctitle:hover&gt;a.anchor,.sidebarblock&gt;.content&gt;.title:hover&gt;a.anchor,h3&gt;a.anchor:hover,#toctitle&gt;a.anchor:hover,.sidebarblock&gt;.content&gt;.title&gt;a.anchor:hover,h4:hover&gt;a.anchor,h4&gt;a.anchor:hover,h5:hover&gt;a.anchor,h5&gt;a.anchor:hover,h6:hover&gt;a.anchor,h6&gt;a.anchor:hover{visibility:visible}
#content h1&gt;a.link,h2&gt;a.link,h3&gt;a.link,#toctitle&gt;a.link,.sidebarblock&gt;.content&gt;.title&gt;a.link,h4&gt;a.link,h5&gt;a.link,h6&gt;a.link{color:#ba3925;text-decoration:none}
#content h1&gt;a.link:hover,h2&gt;a.link:hover,h3&gt;a.link:hover,#toctitle&gt;a.link:hover,.sidebarblock&gt;.content&gt;.title&gt;a.link:hover,h4&gt;a.link:hover,h5&gt;a.link:hover,h6&gt;a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details&gt;summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details&gt;summary::-webkit-details-marker{display:none}
details&gt;summary::before{content:&#34;&#34;;border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]&gt;summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details&gt;summary::after{content:&#34;&#34;;width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{text-rendering:optimizeLegibility;text-align:left;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content&gt;caption.title{white-space:nowrap;width:0}
.paragraph.lead&gt;p,#preamble&gt;.sectionbody&gt;[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock&gt;table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock&gt;table td.icon{text-align:center;width:80px}
.admonitionblock&gt;table td.icon img{max-width:none}
.admonitionblock&gt;table td.icon .title{font-weight:bold;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;text-transform:uppercase}
.admonitionblock&gt;table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock&gt;table td.content&gt;:last-child&gt;:last-child{margin-bottom:0}
.exampleblock&gt;.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock&gt;.content&gt;.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock&gt;.content&gt;:first-child,.sidebarblock&gt;.content&gt;:first-child{margin-top:0}
.exampleblock&gt;.content&gt;:last-child,.exampleblock&gt;.content&gt;:last-child&gt;:last-child,.exampleblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child&gt;:last-child,.sidebarblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child{margin-bottom:0}
.literalblock pre,.listingblock&gt;.content&gt;pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:1em}}
.literalblock pre,.listingblock&gt;.content&gt;pre:not(.highlight),.listingblock&gt;.content&gt;pre[class=highlight],.listingblock&gt;.content&gt;pre[class^=&#34;highlight &#34;]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock&gt;.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:&#34;$&#34;}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs&gt;code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)&gt;.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:&#34;\201c&#34;;float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote&gt;.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract&gt;.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt&gt;blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock&gt;.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock&gt;.content&gt;:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all&gt;*&gt;tr&gt;*{border-width:1px}
table.grid-cols&gt;*&gt;tr&gt;*{border-width:0 1px}
table.grid-rows&gt;*&gt;tr&gt;*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none&gt;colgroup+*&gt;:first-child&gt;*,table.frame-sides&gt;colgroup+*&gt;:first-child&gt;*{border-top-width:0}
table.frame-none&gt;:last-child&gt;:last-child&gt;*,table.frame-sides&gt;:last-child&gt;:last-child&gt;*{border-bottom-width:0}
table.frame-none&gt;*&gt;tr&gt;:first-child,table.frame-ends&gt;*&gt;tr&gt;:first-child{border-left-width:0}
table.frame-none&gt;*&gt;tr&gt;:last-child,table.frame-ends&gt;*&gt;tr&gt;:last-child{border-right-width:0}
table.stripes-all&gt;*&gt;tr,table.stripes-odd&gt;*&gt;tr:nth-of-type(odd),table.stripes-even&gt;*&gt;tr:nth-of-type(even),table.stripes-hover&gt;*&gt;tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock&gt;code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child&gt;:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li&gt;p:empty:only-child::before{content:&#34;&#34;;display:inline-block}
ul.checklist&gt;li&gt;p:first-child{margin-left:-1em}
ul.checklist&gt;li&gt;p:first-child&gt;.fa-square-o:first-child,ul.checklist&gt;li&gt;p:first-child&gt;.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist&gt;li&gt;p:first-child&gt;input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline&gt;li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist&gt;table,.colist&gt;table{border:0;background:none}
.hdlist&gt;table&gt;tbody&gt;tr,.colist&gt;table&gt;tbody&gt;tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock&gt;.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb&gt;.title,.imageblock.th&gt;.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon&gt;.fa{cursor:default}
a span.icon&gt;.fa{cursor:inherit}
.admonitionblock td.icon [class^=&#34;fa icon-&#34;]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:&#34;\f05a&#34;;color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:&#34;\f0eb&#34;;text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:&#34;\f071&#34;;color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:&#34;\f06d&#34;;color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:&#34;\f06a&#34;;color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock&gt;.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^=&#34;#&#34;],a[href^=&#34;mailto:&#34;]{text-decoration:none!important}
a[href^=&#34;http:&#34;]:not(.bare)::after,a[href^=&#34;https:&#34;]:not(.bare)::after{content:&#34;(&#34; attr(href) &#34;)&#34;;display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:&#34; (&#34; attr(title) &#34;)&#34;}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock&gt;.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header&gt;h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1&gt;h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header&gt;h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}&lt;/style&gt;
&lt;style&gt;
/*! Stylesheet for CodeRay to loosely match GitHub themes | MIT License */
pre.CodeRay{background:#f7f7f8}
.CodeRay .line-numbers{border-right:1px solid;opacity:.35;padding:0 .5em 0 0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.CodeRay span.line-numbers{display:inline-block;margin-right:.75em}
.CodeRay .line-numbers strong{color:#000}
table.CodeRay{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.CodeRay td{vertical-align:top;line-height:inherit}
table.CodeRay td.line-numbers{text-align:right}
table.CodeRay td.code{padding:0 0 0 .75em}
.CodeRay .debug{color:#fff!important;background:navy!important}
.CodeRay .annotation{color:#007}
.CodeRay .attribute-name{color:navy}
.CodeRay .attribute-value{color:#700}
.CodeRay .binary{color:#509}
.CodeRay .comment{color:#998;font-style:italic}
.CodeRay .char{color:#04d}
.CodeRay .char .content{color:#04d}
.CodeRay .char .delimiter{color:#039}
.CodeRay .class{color:#458;font-weight:bold}
.CodeRay .complex{color:#a08}
.CodeRay .constant,.CodeRay .predefined-constant{color:teal}
.CodeRay .color{color:#099}
.CodeRay .class-variable{color:#369}
.CodeRay .decorator{color:#b0b}
.CodeRay .definition{color:#099}
.CodeRay .delimiter{color:#000}
.CodeRay .doc{color:#970}
.CodeRay .doctype{color:#34b}
.CodeRay .doc-string{color:#d42}
.CodeRay .escape{color:#666}
.CodeRay .entity{color:#800}
.CodeRay .error{color:#808}
.CodeRay .exception{color:inherit}
.CodeRay .filename{color:#099}
.CodeRay .function{color:#900;font-weight:bold}
.CodeRay .global-variable{color:teal}
.CodeRay .hex{color:#058}
.CodeRay .integer,.CodeRay .float{color:#099}
.CodeRay .include{color:#555}
.CodeRay .inline{color:#000}
.CodeRay .inline .inline{background:#ccc}
.CodeRay .inline .inline .inline{background:#bbb}
.CodeRay .inline .inline-delimiter{color:#d14}
.CodeRay .inline-delimiter{color:#d14}
.CodeRay .important{color:#555;font-weight:bold}
.CodeRay .interpreted{color:#b2b}
.CodeRay .instance-variable{color:teal}
.CodeRay .label{color:#970}
.CodeRay .local-variable{color:#963}
.CodeRay .octal{color:#40e}
.CodeRay .predefined{color:#369}
.CodeRay .preprocessor{color:#579}
.CodeRay .pseudo-class{color:#555}
.CodeRay .directive{font-weight:bold}
.CodeRay .type{font-weight:bold}
.CodeRay .predefined-type{color:inherit}
.CodeRay .reserved,.CodeRay .keyword{color:#000;font-weight:bold}
.CodeRay .key{color:#808}
.CodeRay .key .delimiter{color:#606}
.CodeRay .key .char{color:#80f}
.CodeRay .value{color:#088}
.CodeRay .regexp .delimiter{color:#808}
.CodeRay .regexp .content{color:#808}
.CodeRay .regexp .modifier{color:#808}
.CodeRay .regexp .char{color:#d14}
.CodeRay .regexp .function{color:#404;font-weight:bold}
.CodeRay .string{color:#d20}
.CodeRay .string .string .string{background:#ffd0d0}
.CodeRay .string .content{color:#d14}
.CodeRay .string .char{color:#d14}
.CodeRay .string .delimiter{color:#d14}
.CodeRay .shell{color:#d14}
.CodeRay .shell .delimiter{color:#d14}
.CodeRay .symbol{color:#990073}
.CodeRay .symbol .content{color:#a60}
.CodeRay .symbol .delimiter{color:#630}
.CodeRay .tag{color:teal}
.CodeRay .tag-special{color:#d70}
.CodeRay .variable{color:#036}
.CodeRay .insert{background:#afa}
.CodeRay .delete{background:#faa}
.CodeRay .change{color:#aaf;background:#007}
.CodeRay .head{color:#f8f;background:#505}
.CodeRay .insert .insert{color:#080}
.CodeRay .delete .delete{color:#800}
.CodeRay .change .change{color:#66f}
.CodeRay .head .head{color:#f4f}
&lt;/style&gt;&lt;/head&gt;&lt;body class=&#34;article&#34;&gt;&lt;header&gt;&lt;/header&gt;&lt;div id=&#34;content&#34;&gt;&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_一目标&#34;&gt;一、目标&lt;/h2&gt;&lt;p&gt;“小x同学，把0x1011218f 的函数中的花指令去除掉”。&lt;/p&gt;
&lt;p&gt;最近飞哥已经陷入到AI中无法自拔，感觉以后古法分析都快要成非遗了，以后的标题都得是&amp;#34;传承三十年，古法纯手工去花指令，定位关键算法&amp;#34;。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_二步骤&#34;&gt;二、步骤&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_你的ida_python在哪里&#34;&gt;你的Ida Python在哪里？&lt;/h3&gt;&lt;p&gt;首先你得知道你的ida python是谁？ 在哪里？&lt;/p&gt;
&lt;p&gt;原则一，不要用系统的python，不然你乱七八糟装一堆包，把系统的python干坏了，就废了，最好创建一个虚拟环境，这个python只给ida用&lt;/p&gt;
&lt;p&gt;/Applications/IDA Professional 9.1.app/Contents/MacOS&lt;/p&gt;
&lt;p&gt;目录下面找到 idapyswitch&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;fenfei@fenfei-Mac-Studio MacOS % ./idapyswitch
The following Python installations were found:
    #0: 3.13.0 (&amp;#39;&amp;#39;) (/opt/homebrew/Cellar/python@3.13/3.13.5/Frameworks/Python.framework/Versions/3.13/Python)
    #1: 3.12.0 (&amp;#39;&amp;#39;) (/opt/homebrew/Cellar/python@3.12/3.12.10/Frameworks/Python.framework/Versions/3.12/Python)
    #2: 3.11.0 (&amp;#39;&amp;#39;) (/opt/homebrew/Cellar/python@3.11/3.11.12/Frameworks/Python.framework/Versions/3.11/Python)
    #3: 3.10.0 (&amp;#39;&amp;#39;) (/opt/homebrew/Cellar/python@3.10/3.10.17/Frameworks/Python.framework/Versions/3.10/Python)
    #4: 3.9.0 (&amp;#39;&amp;#39;) (/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Python3)
    #5: 3.9.0 (&amp;#39;&amp;#39;) (/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/Python3)
Please pick a number between 0 and 5 (default: 0)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;可以看到 我现在ida 用的是 py3.13&lt;/p&gt;
&lt;p&gt;然后使用 conda 装个虚拟环境，然后里面也装python3.13&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;conda create -n ida_env python=3.13&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;修改
/Applications/IDA Professional 9.1.app/Contents/MacOS/python/init.py&lt;/p&gt;
&lt;p&gt;增加一行
sys.path.append(&amp;#34;/opt/miniconda3/envs/ida_env/lib/python3.13/site-packages&amp;#34;)&lt;/p&gt;
&lt;p&gt;恭喜你，从此以后你的ida python就专款专用了&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;从ida  File → Script command…​ 执行
import sys
print(sys.path)&lt;/p&gt;&lt;/aside&gt;
&lt;p&gt;可以确认一下你的配置是否正确，&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_插上翅膀&#34;&gt;插上翅膀&lt;/h3&gt;&lt;p&gt;&lt;a href=&#34;https://github.com/mrexodia/ida-pro-mcp&#34;&gt;https://github.com/mrexodia/ida-pro-mcp&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;mcp是什么？这个得问ai&lt;/p&gt;
&lt;p&gt;MCP 一般指的是 Model Context Protocol（模型上下文协议）。&lt;/p&gt;
&lt;p&gt;一句话版理解（先看这个）&lt;/p&gt;
&lt;div class=&#34;literal-block&#34;&gt;&lt;pre&gt;MCP = 给 AI 规定的一套“插件 / 外挂接口标准”&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;就像：&lt;/p&gt;
&lt;div class=&#34;ulist&#34;&gt;&lt;ul&gt;&lt;li&gt;USB 是硬件接口标准&lt;/li&gt;&lt;li&gt;HTTP 是网络接口标准&lt;/li&gt;&lt;li&gt;MCP 是 AI 调用外部能力的接口标准&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
&lt;p&gt;其实你就理解成，ida mcp 可以让AI ide 直接操作你的ida&lt;/p&gt;
&lt;p&gt;我们开始安装 ida mcp&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;# 进入ida专用py环境
conda activate ida_env
pip uninstall ida-pro-mcp
pip install https://github.com/mrexodia/ida-pro-mcp/archive/refs/heads/main.zip
ida-pro-mcp --install&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;ok了， 安装完毕， 打开 ida ，找个样本反编译，然后 Edit → Plugins → MCP&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;[MCP] Server started:
  Streamable HTTP: http://127.0.0.1:13337/mcp
  SSE: http://127.0.0.1:13337/sse
  Config: http://127.0.0.1:13337/config.html&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这就是启动成功，&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;有时候端口会是  13338 ,根据实际情况配置 AI IDE&lt;/p&gt;&lt;/aside&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_配置ai_ide&#34;&gt;配置AI IDE&lt;/h3&gt;&lt;p&gt;打开你常用的 AI IDE， 包括不限于 Cursor / CodeGeeX / Trae / Codebuddy&lt;/p&gt;
&lt;p&gt;配置 MCP&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;{&amp;#34;mcpServers&amp;#34;:{&amp;#34;ida&amp;#34;:{&amp;#34;transport&amp;#34;:&amp;#34;sse&amp;#34;,&amp;#34;url&amp;#34;:&amp;#34;http://127.0.0.1:13337/sse&amp;#34;,&amp;#34;alwaysAllow&amp;#34;:[&amp;#34;idb_meta&amp;#34;,&amp;#34;list_funcs&amp;#34;,&amp;#34;disasm&amp;#34;,&amp;#34;decompile&amp;#34;,&amp;#34;lookup_funcs&amp;#34;,&amp;#34;analyze_funcs&amp;#34;,&amp;#34;get_bytes&amp;#34;]}}}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;出来这个效果&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Idamcp/idamcp.png&#34; alt=&#34;idamcp&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:idamcp&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;可以开始了&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;从ida mcp中，请把 0x101159B88 函数的花指令去掉

从ida mcp中，请帮我分析一下 xid 是如何生成的， 生成frida hook 脚本 跟踪一下。&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;嗯 真香&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_三总结&#34;&gt;三、总结&lt;/h2&gt;&lt;p&gt;感觉ai进步了，以前红极一时的 AI Prompt 没那么重要了，反正我说的 AI 基本都能听懂。&lt;/p&gt;
&lt;p&gt;古法纯手工还有没有意义？ 有个网友说过 &lt;mark&gt;你不会的别指望 ai 会，你能用 ai 搞出来是因为你会&lt;/mark&gt;&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Idamcp/ffshow.png&#34; alt=&#34;ffshow&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ffshow&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;mark&gt;插上翅膀的人是天使，插上翅膀的老鼠是蝙蝠&lt;/mark&gt;&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;: 本文的目的只有一个就是学习更多的逆向技巧和思路，如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担，和本文以及作者没关系，本文涉及到的代码项目可以去 &lt;mark&gt;奋飞的朋友们&lt;/mark&gt; 知识星球自取，欢迎加入知识星球一起学习探讨技术。有问题可以加我wx: &lt;mark&gt;fenfei331&lt;/mark&gt; 讨论下。&lt;/p&gt;&lt;/aside&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ffzsxq.jpg&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;
&lt;p&gt;关注微信公众号，最新技术干货实时推送&lt;/p&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ff330.png&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;&lt;/section&gt;&lt;/div&gt;&lt;footer&gt;&lt;div id=&#34;footer-text&#34;&gt;&lt;br/&gt;Last updated 2026-04-27 18:48:43 +0800&lt;/div&gt;&lt;/footer&gt;
</description>
      
    </item>
    
    <item>
      <title>别被外壳骗了，那只是柔软的伪装 - 某小说App Token算法分析</title>
      <link>http://91fans.com.cn/post/txtread/</link>
      <pubDate>Mon, 13 Oct 2025 13:18:21 +0800</pubDate>
      
      <guid>http://91fans.com.cn/post/txtread/</guid>
      
        <description>&lt;meta charset=&#34;UTF-8&#34;/&gt;&lt;meta http-equiv=&#34;X-UA-Compatible&#34; content=&#34;IE=edge&#34;/&gt;&lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;/&gt;&lt;meta name=&#34;generator&#34; content=&#34;Asciidoctor 2.0.20&#34;/&gt;&lt;title&gt;一、目标&lt;/title&gt;&lt;style&gt;/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import &#34;https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700&#34;; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:&#34;\201C&#34; &#34;\201D&#34; &#34;\2018&#34; &#34;\2019&#34;}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock&gt;.content&gt;.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock&gt;.content&gt;.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:&#34; &#34;;display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])&gt;code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre&gt;code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:&#34;[&#34;;padding:0 3px 0 2px}
b.button::after{content:&#34;]&#34;;padding:0 2px 0 3px}
p a&gt;code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:&#34; &#34;;display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header&gt;h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header&gt;h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header&gt;h1:only-child,body.toc2 #header&gt;h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:&#34;\00a0\2013\00a0&#34;}
#header .details br+span.author::before{content:&#34;\00a0\22c5\00a0&#34;;color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:&#34;\00a0|\00a0&#34;}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:&#34;\00a0&#34;}
#content&gt;h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc&gt;ul{margin-left:.125em}
#toc ul.sectlevel0&gt;li&gt;a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2&gt;ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2&gt;ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc&gt;:first-child{margin-top:0}
#content #toc&gt;:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1&gt;a.anchor,h2&gt;a.anchor,h3&gt;a.anchor,#toctitle&gt;a.anchor,.sidebarblock&gt;.content&gt;.title&gt;a.anchor,h4&gt;a.anchor,h5&gt;a.anchor,h6&gt;a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1&gt;a.anchor::before,h2&gt;a.anchor::before,h3&gt;a.anchor::before,#toctitle&gt;a.anchor::before,.sidebarblock&gt;.content&gt;.title&gt;a.anchor::before,h4&gt;a.anchor::before,h5&gt;a.anchor::before,h6&gt;a.anchor::before{content:&#34;\00A7&#34;;font-size:.85em;display:block;padding-top:.1em}
#content h1:hover&gt;a.anchor,#content h1&gt;a.anchor:hover,h2:hover&gt;a.anchor,h2&gt;a.anchor:hover,h3:hover&gt;a.anchor,#toctitle:hover&gt;a.anchor,.sidebarblock&gt;.content&gt;.title:hover&gt;a.anchor,h3&gt;a.anchor:hover,#toctitle&gt;a.anchor:hover,.sidebarblock&gt;.content&gt;.title&gt;a.anchor:hover,h4:hover&gt;a.anchor,h4&gt;a.anchor:hover,h5:hover&gt;a.anchor,h5&gt;a.anchor:hover,h6:hover&gt;a.anchor,h6&gt;a.anchor:hover{visibility:visible}
#content h1&gt;a.link,h2&gt;a.link,h3&gt;a.link,#toctitle&gt;a.link,.sidebarblock&gt;.content&gt;.title&gt;a.link,h4&gt;a.link,h5&gt;a.link,h6&gt;a.link{color:#ba3925;text-decoration:none}
#content h1&gt;a.link:hover,h2&gt;a.link:hover,h3&gt;a.link:hover,#toctitle&gt;a.link:hover,.sidebarblock&gt;.content&gt;.title&gt;a.link:hover,h4&gt;a.link:hover,h5&gt;a.link:hover,h6&gt;a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details&gt;summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details&gt;summary::-webkit-details-marker{display:none}
details&gt;summary::before{content:&#34;&#34;;border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]&gt;summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details&gt;summary::after{content:&#34;&#34;;width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{text-rendering:optimizeLegibility;text-align:left;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content&gt;caption.title{white-space:nowrap;width:0}
.paragraph.lead&gt;p,#preamble&gt;.sectionbody&gt;[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock&gt;table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock&gt;table td.icon{text-align:center;width:80px}
.admonitionblock&gt;table td.icon img{max-width:none}
.admonitionblock&gt;table td.icon .title{font-weight:bold;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;text-transform:uppercase}
.admonitionblock&gt;table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock&gt;table td.content&gt;:last-child&gt;:last-child{margin-bottom:0}
.exampleblock&gt;.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock&gt;.content&gt;.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock&gt;.content&gt;:first-child,.sidebarblock&gt;.content&gt;:first-child{margin-top:0}
.exampleblock&gt;.content&gt;:last-child,.exampleblock&gt;.content&gt;:last-child&gt;:last-child,.exampleblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child&gt;:last-child,.sidebarblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child{margin-bottom:0}
.literalblock pre,.listingblock&gt;.content&gt;pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:1em}}
.literalblock pre,.listingblock&gt;.content&gt;pre:not(.highlight),.listingblock&gt;.content&gt;pre[class=highlight],.listingblock&gt;.content&gt;pre[class^=&#34;highlight &#34;]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock&gt;.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:&#34;$&#34;}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs&gt;code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)&gt;.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:&#34;\201c&#34;;float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote&gt;.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract&gt;.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt&gt;blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock&gt;.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock&gt;.content&gt;:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all&gt;*&gt;tr&gt;*{border-width:1px}
table.grid-cols&gt;*&gt;tr&gt;*{border-width:0 1px}
table.grid-rows&gt;*&gt;tr&gt;*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none&gt;colgroup+*&gt;:first-child&gt;*,table.frame-sides&gt;colgroup+*&gt;:first-child&gt;*{border-top-width:0}
table.frame-none&gt;:last-child&gt;:last-child&gt;*,table.frame-sides&gt;:last-child&gt;:last-child&gt;*{border-bottom-width:0}
table.frame-none&gt;*&gt;tr&gt;:first-child,table.frame-ends&gt;*&gt;tr&gt;:first-child{border-left-width:0}
table.frame-none&gt;*&gt;tr&gt;:last-child,table.frame-ends&gt;*&gt;tr&gt;:last-child{border-right-width:0}
table.stripes-all&gt;*&gt;tr,table.stripes-odd&gt;*&gt;tr:nth-of-type(odd),table.stripes-even&gt;*&gt;tr:nth-of-type(even),table.stripes-hover&gt;*&gt;tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock&gt;code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child&gt;:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li&gt;p:empty:only-child::before{content:&#34;&#34;;display:inline-block}
ul.checklist&gt;li&gt;p:first-child{margin-left:-1em}
ul.checklist&gt;li&gt;p:first-child&gt;.fa-square-o:first-child,ul.checklist&gt;li&gt;p:first-child&gt;.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist&gt;li&gt;p:first-child&gt;input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline&gt;li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist&gt;table,.colist&gt;table{border:0;background:none}
.hdlist&gt;table&gt;tbody&gt;tr,.colist&gt;table&gt;tbody&gt;tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock&gt;.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb&gt;.title,.imageblock.th&gt;.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon&gt;.fa{cursor:default}
a span.icon&gt;.fa{cursor:inherit}
.admonitionblock td.icon [class^=&#34;fa icon-&#34;]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:&#34;\f05a&#34;;color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:&#34;\f0eb&#34;;text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:&#34;\f071&#34;;color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:&#34;\f06d&#34;;color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:&#34;\f06a&#34;;color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock&gt;.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^=&#34;#&#34;],a[href^=&#34;mailto:&#34;]{text-decoration:none!important}
a[href^=&#34;http:&#34;]:not(.bare)::after,a[href^=&#34;https:&#34;]:not(.bare)::after{content:&#34;(&#34; attr(href) &#34;)&#34;;display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:&#34; (&#34; attr(title) &#34;)&#34;}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock&gt;.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header&gt;h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1&gt;h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header&gt;h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}&lt;/style&gt;
&lt;style&gt;
/*! Stylesheet for CodeRay to loosely match GitHub themes | MIT License */
pre.CodeRay{background:#f7f7f8}
.CodeRay .line-numbers{border-right:1px solid;opacity:.35;padding:0 .5em 0 0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.CodeRay span.line-numbers{display:inline-block;margin-right:.75em}
.CodeRay .line-numbers strong{color:#000}
table.CodeRay{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.CodeRay td{vertical-align:top;line-height:inherit}
table.CodeRay td.line-numbers{text-align:right}
table.CodeRay td.code{padding:0 0 0 .75em}
.CodeRay .debug{color:#fff!important;background:navy!important}
.CodeRay .annotation{color:#007}
.CodeRay .attribute-name{color:navy}
.CodeRay .attribute-value{color:#700}
.CodeRay .binary{color:#509}
.CodeRay .comment{color:#998;font-style:italic}
.CodeRay .char{color:#04d}
.CodeRay .char .content{color:#04d}
.CodeRay .char .delimiter{color:#039}
.CodeRay .class{color:#458;font-weight:bold}
.CodeRay .complex{color:#a08}
.CodeRay .constant,.CodeRay .predefined-constant{color:teal}
.CodeRay .color{color:#099}
.CodeRay .class-variable{color:#369}
.CodeRay .decorator{color:#b0b}
.CodeRay .definition{color:#099}
.CodeRay .delimiter{color:#000}
.CodeRay .doc{color:#970}
.CodeRay .doctype{color:#34b}
.CodeRay .doc-string{color:#d42}
.CodeRay .escape{color:#666}
.CodeRay .entity{color:#800}
.CodeRay .error{color:#808}
.CodeRay .exception{color:inherit}
.CodeRay .filename{color:#099}
.CodeRay .function{color:#900;font-weight:bold}
.CodeRay .global-variable{color:teal}
.CodeRay .hex{color:#058}
.CodeRay .integer,.CodeRay .float{color:#099}
.CodeRay .include{color:#555}
.CodeRay .inline{color:#000}
.CodeRay .inline .inline{background:#ccc}
.CodeRay .inline .inline .inline{background:#bbb}
.CodeRay .inline .inline-delimiter{color:#d14}
.CodeRay .inline-delimiter{color:#d14}
.CodeRay .important{color:#555;font-weight:bold}
.CodeRay .interpreted{color:#b2b}
.CodeRay .instance-variable{color:teal}
.CodeRay .label{color:#970}
.CodeRay .local-variable{color:#963}
.CodeRay .octal{color:#40e}
.CodeRay .predefined{color:#369}
.CodeRay .preprocessor{color:#579}
.CodeRay .pseudo-class{color:#555}
.CodeRay .directive{font-weight:bold}
.CodeRay .type{font-weight:bold}
.CodeRay .predefined-type{color:inherit}
.CodeRay .reserved,.CodeRay .keyword{color:#000;font-weight:bold}
.CodeRay .key{color:#808}
.CodeRay .key .delimiter{color:#606}
.CodeRay .key .char{color:#80f}
.CodeRay .value{color:#088}
.CodeRay .regexp .delimiter{color:#808}
.CodeRay .regexp .content{color:#808}
.CodeRay .regexp .modifier{color:#808}
.CodeRay .regexp .char{color:#d14}
.CodeRay .regexp .function{color:#404;font-weight:bold}
.CodeRay .string{color:#d20}
.CodeRay .string .string .string{background:#ffd0d0}
.CodeRay .string .content{color:#d14}
.CodeRay .string .char{color:#d14}
.CodeRay .string .delimiter{color:#d14}
.CodeRay .shell{color:#d14}
.CodeRay .shell .delimiter{color:#d14}
.CodeRay .symbol{color:#990073}
.CodeRay .symbol .content{color:#a60}
.CodeRay .symbol .delimiter{color:#630}
.CodeRay .tag{color:teal}
.CodeRay .tag-special{color:#d70}
.CodeRay .variable{color:#036}
.CodeRay .insert{background:#afa}
.CodeRay .delete{background:#faa}
.CodeRay .change{color:#aaf;background:#007}
.CodeRay .head{color:#f8f;background:#505}
.CodeRay .insert .insert{color:#080}
.CodeRay .delete .delete{color:#800}
.CodeRay .change .change{color:#66f}
.CodeRay .head .head{color:#f4f}
&lt;/style&gt;&lt;/head&gt;&lt;body class=&#34;article&#34;&gt;&lt;header&gt;&lt;/header&gt;&lt;div id=&#34;content&#34;&gt;&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_一目标&#34;&gt;一、目标&lt;/h2&gt;&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Txtread/token.png&#34; alt=&#34;token&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:token&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;今天的目标是这个 &lt;mark&gt;token&lt;/mark&gt; 参数的算法,这个样本比较适合初学者，难度1星。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_二步骤&#34;&gt;二、步骤&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_脱壳&#34;&gt;脱壳&lt;/h3&gt;&lt;p&gt;先把apk拉进jadx&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Txtread/qihoo.png&#34; alt=&#34;qihoo&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ke&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;很明显不对劲，这种只有2-3个类的，就是加壳之后的明显特征，至于加了什么壳， &lt;mark&gt;qihoo&lt;/mark&gt; 已经很明白告诉我们了，就是数字壳。&lt;/p&gt;
&lt;p&gt;之前的教程我们介绍过 FRIDA-DEXDump脱壳或者刷个脱壳rom， 当然最方便的还是找个脱壳云服务。(私信给我，我把云服务的地址发你)&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_字符串查找&#34;&gt;字符串查找&lt;/h3&gt;&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Txtread/tokenshow.png&#34; alt=&#34;tokenshow&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:token&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;这种 com.bytexxx / com.baidx / com.ss 之类的看上去就很妖艳的都是大厂的sdk，都是来迷惑你的道心的。&lt;/p&gt;
&lt;p&gt;只有像这种带着app包名中类似单词的才是你的小清新。&lt;/p&gt;
&lt;p&gt;token长得很想base64，所以我们点 com.novel.basic.token.Base64 进去看看,看上去是一个自己实现的base64类。&lt;/p&gt;
&lt;p&gt;没看出有啥特别的，先不管，我们从左边展开类名，看看 com.novel.basic.token 包下面还有哪些类？&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Txtread/tokensrc1.png&#34; alt=&#34;tokensrc1&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:tokensrc1&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;神奇的是，我们没有找到 com.novel.basic.token 包，也许是dump的时候丢了。更神奇的是，我们找到了一个 com.novel.basic.token.xz 包，里面有个看上去浓眉大眼的 TokenUtil类&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;java&#34;&gt;&lt;span class=&#34;directive&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;type&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;class&#34;&gt;TokenUtil&lt;/span&gt; {
    ...

public &lt;span class=&#34;directive&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;predefined-type&#34;&gt;String&lt;/span&gt; g(&lt;span class=&#34;predefined-type&#34;&gt;Map&lt;/span&gt;&amp;lt;&lt;span class=&#34;predefined-type&#34;&gt;String&lt;/span&gt;, &lt;span class=&#34;predefined-type&#34;&gt;String&lt;/span&gt;&amp;gt; map) {
        &lt;span class=&#34;predefined-type&#34;&gt;ArrayList&lt;/span&gt;&amp;lt;&lt;span class=&#34;predefined-type&#34;&gt;String&lt;/span&gt;&amp;gt; arrayList = &lt;span class=&#34;keyword&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;predefined-type&#34;&gt;ArrayList&lt;/span&gt;(map.keySet());
        &lt;span class=&#34;predefined-type&#34;&gt;Collections&lt;/span&gt;.sort(arrayList);
        &lt;span class=&#34;predefined-type&#34;&gt;StringBuffer&lt;/span&gt; stringBuffer = &lt;span class=&#34;keyword&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;predefined-type&#34;&gt;StringBuffer&lt;/span&gt;();
        &lt;span class=&#34;keyword&#34;&gt;for&lt;/span&gt; (&lt;span class=&#34;predefined-type&#34;&gt;String&lt;/span&gt; str : arrayList) {
            &lt;span class=&#34;predefined-type&#34;&gt;String&lt;/span&gt; str2 = map.get(str);
            stringBuffer.append(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
            stringBuffer.append(str + &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; + str2);
        }
        &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; stringBuffer.toString().substring(&lt;span class=&#34;integer&#34;&gt;1&lt;/span&gt;, stringBuffer.length());
    }

    &lt;span class=&#34;directive&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;directive&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;predefined-type&#34;&gt;String&lt;/span&gt; h(&lt;span class=&#34;predefined-type&#34;&gt;String&lt;/span&gt; str, &lt;span class=&#34;predefined-type&#34;&gt;String&lt;/span&gt; str2) {
        &lt;span class=&#34;predefined-type&#34;&gt;String&lt;/span&gt; str3;
        &lt;span class=&#34;keyword&#34;&gt;try&lt;/span&gt; {
            str3 = e(f(str, str2) + &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; + &lt;span class=&#34;predefined-type&#34;&gt;System&lt;/span&gt;.currentTimeMillis());
        } &lt;span class=&#34;keyword&#34;&gt;catch&lt;/span&gt; (&lt;span class=&#34;exception&#34;&gt;Exception&lt;/span&gt; e) {
            e.printStackTrace();
            str3 = &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;;
        }
        &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; d(str3);
    }

    &lt;span class=&#34;directive&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;directive&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;type&#34;&gt;void&lt;/span&gt; i(&lt;span class=&#34;predefined-type&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;type&#34;&gt;[]&lt;/span&gt; strArr) &lt;span class=&#34;directive&#34;&gt;throws&lt;/span&gt; &lt;span class=&#34;exception&#34;&gt;Exception&lt;/span&gt; {
        &lt;span class=&#34;predefined-type&#34;&gt;HashMap&lt;/span&gt; hashMap = &lt;span class=&#34;keyword&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;predefined-type&#34;&gt;HashMap&lt;/span&gt;();
        hashMap.put(PackageDocumentBase.OPFTags.packageTag, &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;com.mianfeinovel&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
        hashMap.put(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;android&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
        hashMap.put(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;1.0.1&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
        hashMap.put(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;channel&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;blf1298_12243_001&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
        hashMap.put(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;udid&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;aaaaaaaaaaaa&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
        &lt;span class=&#34;predefined-type&#34;&gt;String&lt;/span&gt; g = g(hashMap);
        &lt;span class=&#34;predefined-type&#34;&gt;System&lt;/span&gt;.out.println(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;/v1/recommend/female?&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; + g + &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;&amp;amp;token=&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; + h(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;/v1/recommend/female&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, g));
    }

...
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;从 i 函数上分析， token的运算很有可能是 h函数干的， 那就啥也不说了，hook先&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_hook验证&#34;&gt;Hook验证&lt;/h3&gt;&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;java&#34;&gt;function main() {
    Java.perform(function () {
        &lt;span class=&#34;type&#34;&gt;var&lt;/span&gt; threadef = Java.use(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;java.lang.Thread&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;);
        &lt;span class=&#34;type&#34;&gt;var&lt;/span&gt; threadinstance = threadef.&lt;span class=&#34;error&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;keyword&#34;&gt;new&lt;/span&gt;();

        let TokenUtil = Java.use(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;com.novel.basic.token.xz.TokenUtil&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
        TokenUtil[&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;h&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;].implementation = function (str, str2) {
            console.log(&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;TokenUtil.h is called: str=&lt;span class=&#34;error&#34;&gt;$&lt;/span&gt;{str}, str2=&lt;span class=&#34;error&#34;&gt;$&lt;/span&gt;{str2}&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;);
            let result = &lt;span class=&#34;local-variable&#34;&gt;this&lt;/span&gt;[&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;h&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;](str, str2);
            console.log(&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;TokenUtil.h result=&lt;span class=&#34;error&#34;&gt;$&lt;/span&gt;{result}&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;);
            &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; result;
        };

    });
}

setTimeout(main, &lt;span class=&#34;integer&#34;&gt;5000&lt;/span&gt;);
&lt;span class=&#34;comment&#34;&gt;// setImmediate(main);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;由于是加壳应用，所以需要延迟个几秒再去hook对应的函数，给壳一点加载的时间。&lt;/p&gt;
&lt;p&gt;跑一下，运气不错，就是我们要的结果&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;[M2010J19SC::cn.ttkmfxs.novel ]-&amp;gt; TokenUtil.h is called: str=/v1/ipcn, str2=channel=zxf2019_19206_001&amp;amp;ip=&amp;amp;os=Android&amp;amp;package=cn.ttkmfxs.novel&amp;amp;udid=01bb90d6de80f3cb01bb90d6de80f3cb&amp;amp;v=3.3.24.R
TokenUtil.h result=B993s65X5IwPTsXrgV%2F2rNvCYKcIjT4lyXrthojQ0LY%3D&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_三总结&#34;&gt;三、总结&lt;/h2&gt;&lt;p&gt;这个样本的算法比较清晰，可以直接扣出java代码，或者让ai转成其他的语言。&lt;/p&gt;
&lt;p&gt;很多加壳应用最大的难点就是壳，敲开壳之后就是一马平川了。&lt;/p&gt;
&lt;p&gt;做逆向运气很重要，真的。&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Txtread/ffshow.png&#34; alt=&#34;ffshow&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ffshow&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;mark&gt;坚硬只是表现&lt;/mark&gt;&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;: 本文的目的只有一个就是学习更多的逆向技巧和思路，如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担，和本文以及作者没关系，本文涉及到的代码项目可以去 &lt;mark&gt;奋飞的朋友们&lt;/mark&gt; 知识星球自取，欢迎加入知识星球一起学习探讨技术。有问题可以加我wx: &lt;mark&gt;fenfei331&lt;/mark&gt; 讨论下。&lt;/p&gt;&lt;/aside&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ffzsxq.jpg&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;
&lt;p&gt;关注微信公众号，最新技术干货实时推送&lt;/p&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ff330.png&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;&lt;/section&gt;&lt;/div&gt;&lt;footer&gt;&lt;div id=&#34;footer-text&#34;&gt;&lt;br/&gt;Last updated 2026-04-27 18:48:45 +0800&lt;/div&gt;&lt;/footer&gt;
</description>
      
    </item>
    
    <item>
      <title>程序员跑路了，李老板要求把App换个图标和名称</title>
      <link>http://91fans.com.cn/post/modifyapk/</link>
      <pubDate>Mon, 19 May 2025 12:48:32 +0800</pubDate>
      
      <guid>http://91fans.com.cn/post/modifyapk/</guid>
      
        <description>&lt;meta charset=&#34;UTF-8&#34;/&gt;&lt;meta http-equiv=&#34;X-UA-Compatible&#34; content=&#34;IE=edge&#34;/&gt;&lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;/&gt;&lt;meta name=&#34;generator&#34; content=&#34;Asciidoctor 2.0.20&#34;/&gt;&lt;title&gt;一、目标&lt;/title&gt;&lt;style&gt;/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import &#34;https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700&#34;; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:&#34;\201C&#34; &#34;\201D&#34; &#34;\2018&#34; &#34;\2019&#34;}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock&gt;.content&gt;.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock&gt;.content&gt;.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:&#34; &#34;;display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])&gt;code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre&gt;code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:&#34;[&#34;;padding:0 3px 0 2px}
b.button::after{content:&#34;]&#34;;padding:0 2px 0 3px}
p a&gt;code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:&#34; &#34;;display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header&gt;h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header&gt;h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header&gt;h1:only-child,body.toc2 #header&gt;h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:&#34;\00a0\2013\00a0&#34;}
#header .details br+span.author::before{content:&#34;\00a0\22c5\00a0&#34;;color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:&#34;\00a0|\00a0&#34;}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:&#34;\00a0&#34;}
#content&gt;h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc&gt;ul{margin-left:.125em}
#toc ul.sectlevel0&gt;li&gt;a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2&gt;ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2&gt;ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc&gt;:first-child{margin-top:0}
#content #toc&gt;:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1&gt;a.anchor,h2&gt;a.anchor,h3&gt;a.anchor,#toctitle&gt;a.anchor,.sidebarblock&gt;.content&gt;.title&gt;a.anchor,h4&gt;a.anchor,h5&gt;a.anchor,h6&gt;a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1&gt;a.anchor::before,h2&gt;a.anchor::before,h3&gt;a.anchor::before,#toctitle&gt;a.anchor::before,.sidebarblock&gt;.content&gt;.title&gt;a.anchor::before,h4&gt;a.anchor::before,h5&gt;a.anchor::before,h6&gt;a.anchor::before{content:&#34;\00A7&#34;;font-size:.85em;display:block;padding-top:.1em}
#content h1:hover&gt;a.anchor,#content h1&gt;a.anchor:hover,h2:hover&gt;a.anchor,h2&gt;a.anchor:hover,h3:hover&gt;a.anchor,#toctitle:hover&gt;a.anchor,.sidebarblock&gt;.content&gt;.title:hover&gt;a.anchor,h3&gt;a.anchor:hover,#toctitle&gt;a.anchor:hover,.sidebarblock&gt;.content&gt;.title&gt;a.anchor:hover,h4:hover&gt;a.anchor,h4&gt;a.anchor:hover,h5:hover&gt;a.anchor,h5&gt;a.anchor:hover,h6:hover&gt;a.anchor,h6&gt;a.anchor:hover{visibility:visible}
#content h1&gt;a.link,h2&gt;a.link,h3&gt;a.link,#toctitle&gt;a.link,.sidebarblock&gt;.content&gt;.title&gt;a.link,h4&gt;a.link,h5&gt;a.link,h6&gt;a.link{color:#ba3925;text-decoration:none}
#content h1&gt;a.link:hover,h2&gt;a.link:hover,h3&gt;a.link:hover,#toctitle&gt;a.link:hover,.sidebarblock&gt;.content&gt;.title&gt;a.link:hover,h4&gt;a.link:hover,h5&gt;a.link:hover,h6&gt;a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details&gt;summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details&gt;summary::-webkit-details-marker{display:none}
details&gt;summary::before{content:&#34;&#34;;border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]&gt;summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details&gt;summary::after{content:&#34;&#34;;width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{text-rendering:optimizeLegibility;text-align:left;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content&gt;caption.title{white-space:nowrap;width:0}
.paragraph.lead&gt;p,#preamble&gt;.sectionbody&gt;[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock&gt;table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock&gt;table td.icon{text-align:center;width:80px}
.admonitionblock&gt;table td.icon img{max-width:none}
.admonitionblock&gt;table td.icon .title{font-weight:bold;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;text-transform:uppercase}
.admonitionblock&gt;table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock&gt;table td.content&gt;:last-child&gt;:last-child{margin-bottom:0}
.exampleblock&gt;.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock&gt;.content&gt;.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock&gt;.content&gt;:first-child,.sidebarblock&gt;.content&gt;:first-child{margin-top:0}
.exampleblock&gt;.content&gt;:last-child,.exampleblock&gt;.content&gt;:last-child&gt;:last-child,.exampleblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child&gt;:last-child,.sidebarblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child{margin-bottom:0}
.literalblock pre,.listingblock&gt;.content&gt;pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:1em}}
.literalblock pre,.listingblock&gt;.content&gt;pre:not(.highlight),.listingblock&gt;.content&gt;pre[class=highlight],.listingblock&gt;.content&gt;pre[class^=&#34;highlight &#34;]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock&gt;.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:&#34;$&#34;}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs&gt;code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)&gt;.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:&#34;\201c&#34;;float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote&gt;.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract&gt;.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt&gt;blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock&gt;.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock&gt;.content&gt;:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all&gt;*&gt;tr&gt;*{border-width:1px}
table.grid-cols&gt;*&gt;tr&gt;*{border-width:0 1px}
table.grid-rows&gt;*&gt;tr&gt;*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none&gt;colgroup+*&gt;:first-child&gt;*,table.frame-sides&gt;colgroup+*&gt;:first-child&gt;*{border-top-width:0}
table.frame-none&gt;:last-child&gt;:last-child&gt;*,table.frame-sides&gt;:last-child&gt;:last-child&gt;*{border-bottom-width:0}
table.frame-none&gt;*&gt;tr&gt;:first-child,table.frame-ends&gt;*&gt;tr&gt;:first-child{border-left-width:0}
table.frame-none&gt;*&gt;tr&gt;:last-child,table.frame-ends&gt;*&gt;tr&gt;:last-child{border-right-width:0}
table.stripes-all&gt;*&gt;tr,table.stripes-odd&gt;*&gt;tr:nth-of-type(odd),table.stripes-even&gt;*&gt;tr:nth-of-type(even),table.stripes-hover&gt;*&gt;tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock&gt;code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child&gt;:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li&gt;p:empty:only-child::before{content:&#34;&#34;;display:inline-block}
ul.checklist&gt;li&gt;p:first-child{margin-left:-1em}
ul.checklist&gt;li&gt;p:first-child&gt;.fa-square-o:first-child,ul.checklist&gt;li&gt;p:first-child&gt;.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist&gt;li&gt;p:first-child&gt;input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline&gt;li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist&gt;table,.colist&gt;table{border:0;background:none}
.hdlist&gt;table&gt;tbody&gt;tr,.colist&gt;table&gt;tbody&gt;tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock&gt;.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb&gt;.title,.imageblock.th&gt;.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon&gt;.fa{cursor:default}
a span.icon&gt;.fa{cursor:inherit}
.admonitionblock td.icon [class^=&#34;fa icon-&#34;]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:&#34;\f05a&#34;;color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:&#34;\f0eb&#34;;text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:&#34;\f071&#34;;color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:&#34;\f06d&#34;;color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:&#34;\f06a&#34;;color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock&gt;.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^=&#34;#&#34;],a[href^=&#34;mailto:&#34;]{text-decoration:none!important}
a[href^=&#34;http:&#34;]:not(.bare)::after,a[href^=&#34;https:&#34;]:not(.bare)::after{content:&#34;(&#34; attr(href) &#34;)&#34;;display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:&#34; (&#34; attr(title) &#34;)&#34;}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock&gt;.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header&gt;h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1&gt;h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header&gt;h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}&lt;/style&gt;
&lt;style&gt;
/*! Stylesheet for CodeRay to loosely match GitHub themes | MIT License */
pre.CodeRay{background:#f7f7f8}
.CodeRay .line-numbers{border-right:1px solid;opacity:.35;padding:0 .5em 0 0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.CodeRay span.line-numbers{display:inline-block;margin-right:.75em}
.CodeRay .line-numbers strong{color:#000}
table.CodeRay{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.CodeRay td{vertical-align:top;line-height:inherit}
table.CodeRay td.line-numbers{text-align:right}
table.CodeRay td.code{padding:0 0 0 .75em}
.CodeRay .debug{color:#fff!important;background:navy!important}
.CodeRay .annotation{color:#007}
.CodeRay .attribute-name{color:navy}
.CodeRay .attribute-value{color:#700}
.CodeRay .binary{color:#509}
.CodeRay .comment{color:#998;font-style:italic}
.CodeRay .char{color:#04d}
.CodeRay .char .content{color:#04d}
.CodeRay .char .delimiter{color:#039}
.CodeRay .class{color:#458;font-weight:bold}
.CodeRay .complex{color:#a08}
.CodeRay .constant,.CodeRay .predefined-constant{color:teal}
.CodeRay .color{color:#099}
.CodeRay .class-variable{color:#369}
.CodeRay .decorator{color:#b0b}
.CodeRay .definition{color:#099}
.CodeRay .delimiter{color:#000}
.CodeRay .doc{color:#970}
.CodeRay .doctype{color:#34b}
.CodeRay .doc-string{color:#d42}
.CodeRay .escape{color:#666}
.CodeRay .entity{color:#800}
.CodeRay .error{color:#808}
.CodeRay .exception{color:inherit}
.CodeRay .filename{color:#099}
.CodeRay .function{color:#900;font-weight:bold}
.CodeRay .global-variable{color:teal}
.CodeRay .hex{color:#058}
.CodeRay .integer,.CodeRay .float{color:#099}
.CodeRay .include{color:#555}
.CodeRay .inline{color:#000}
.CodeRay .inline .inline{background:#ccc}
.CodeRay .inline .inline .inline{background:#bbb}
.CodeRay .inline .inline-delimiter{color:#d14}
.CodeRay .inline-delimiter{color:#d14}
.CodeRay .important{color:#555;font-weight:bold}
.CodeRay .interpreted{color:#b2b}
.CodeRay .instance-variable{color:teal}
.CodeRay .label{color:#970}
.CodeRay .local-variable{color:#963}
.CodeRay .octal{color:#40e}
.CodeRay .predefined{color:#369}
.CodeRay .preprocessor{color:#579}
.CodeRay .pseudo-class{color:#555}
.CodeRay .directive{font-weight:bold}
.CodeRay .type{font-weight:bold}
.CodeRay .predefined-type{color:inherit}
.CodeRay .reserved,.CodeRay .keyword{color:#000;font-weight:bold}
.CodeRay .key{color:#808}
.CodeRay .key .delimiter{color:#606}
.CodeRay .key .char{color:#80f}
.CodeRay .value{color:#088}
.CodeRay .regexp .delimiter{color:#808}
.CodeRay .regexp .content{color:#808}
.CodeRay .regexp .modifier{color:#808}
.CodeRay .regexp .char{color:#d14}
.CodeRay .regexp .function{color:#404;font-weight:bold}
.CodeRay .string{color:#d20}
.CodeRay .string .string .string{background:#ffd0d0}
.CodeRay .string .content{color:#d14}
.CodeRay .string .char{color:#d14}
.CodeRay .string .delimiter{color:#d14}
.CodeRay .shell{color:#d14}
.CodeRay .shell .delimiter{color:#d14}
.CodeRay .symbol{color:#990073}
.CodeRay .symbol .content{color:#a60}
.CodeRay .symbol .delimiter{color:#630}
.CodeRay .tag{color:teal}
.CodeRay .tag-special{color:#d70}
.CodeRay .variable{color:#036}
.CodeRay .insert{background:#afa}
.CodeRay .delete{background:#faa}
.CodeRay .change{color:#aaf;background:#007}
.CodeRay .head{color:#f8f;background:#505}
.CodeRay .insert .insert{color:#080}
.CodeRay .delete .delete{color:#800}
.CodeRay .change .change{color:#66f}
.CodeRay .head .head{color:#f4f}
&lt;/style&gt;&lt;/head&gt;&lt;body class=&#34;article&#34;&gt;&lt;header&gt;&lt;/header&gt;&lt;div id=&#34;content&#34;&gt;&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_一目标&#34;&gt;一、目标&lt;/h2&gt;&lt;p&gt;李老板：奋飞呀，给咱们开发Android App的程序员删库跑路了，明天投资人就要过来，咱们得把App换个图标和名字呀？&lt;/p&gt;
&lt;p&gt;奋飞：这个得先把五一的加班费结一下。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_二步骤&#34;&gt;二、步骤&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_拆包&#34;&gt;拆包&lt;/h3&gt;&lt;p&gt;Android App的安装包Apk文件本质上是一个zip压缩包，直接把后缀改成zip，就可以解压，然后修改完再压缩回去不就行了？ &lt;mark&gt;本文完……&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;现实是没有那么简单的，作为逆向工程师，必须要把 &lt;mark&gt;简单的事情复杂化&lt;/mark&gt;，这样才能体现你的价值。&lt;/p&gt;
&lt;p&gt;解压在我们这里不叫解压，叫拆开安装包，简称 &lt;mark&gt;拆包&lt;/mark&gt;。是不是立马高大上了。&lt;/p&gt;
&lt;p&gt;因为Apk的安装包有一些特殊处理，所以我们需要用特殊的工具去拆包 &lt;a href=&#34;https://apktool.org&#34;&gt;apktool&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;# d 拆包
# f 待拆包的apk
# o 输出拆包结果的文件夹
apktool d -f example.apk -o tmp_apk_dir&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_修改文件&#34;&gt;修改文件&lt;/h3&gt;&lt;p&gt;App的名字等字符串信息一般都是放在&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;…​/tmp_apk_dir/res/values/strings.xml&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;这个xml文件里面&lt;/p&gt;
&lt;p&gt;把 &amp;lt;string name=&amp;#34;app_name&amp;#34;&amp;gt;xx本子&amp;lt;/string&amp;gt;&lt;/p&gt;
&lt;p&gt;改成 &amp;lt;string name=&amp;#34;app_name&amp;#34;&amp;gt;李老板本子&amp;lt;/string&amp;gt;&lt;/p&gt;
&lt;p&gt;App的图标一般都是放在&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;tmp_apk_dir/res/mipmap-xhdpi/icon.png&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;其他的mipmap-xxx文件夹是不同分辨率下的图标，可以统统给他换了。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_打包签名&#34;&gt;打包，签名&lt;/h3&gt;&lt;p&gt;修改好了之后就可以用 apktool重新打包了&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;apktool b tmp_apk_dir -o unsigned_new.apk&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;签名文件是为了证明这个apk是你的，防止被别人篡改，所以咱们修改了apk之后，由于没有原始的签名文件，只能生成一个新的。&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;keytool -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias mykey&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;参数解释：&lt;/p&gt;
&lt;p&gt;-keystore my-release-key.jks：生成的签名文件名。&lt;/p&gt;
&lt;p&gt;-keyalg RSA：加密算法。&lt;/p&gt;
&lt;p&gt;-keysize 2048：密钥长度。&lt;/p&gt;
&lt;p&gt;-validity 10000：证书有效期（单位：天）。&lt;/p&gt;
&lt;p&gt;-alias mykey：密钥别名，可自定义。&lt;/p&gt;
&lt;p&gt;最后一步就是给重新打包的apk做签名了&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;apksigner sign --ks my-release-key.jks --ks-pass pass:fenfei --ks-key-alias mykey --out your_app_new.apk unsigned_new.apk&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;apksigner一般在你安装的android SDK里面 /Users/xxx/Library/Android/sdk/build-tools/34.0.0/apksigner&lt;/p&gt;&lt;/aside&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Modifyapk/setup.png&#34; alt=&#34;setup&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:setup&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;看上去没啥问题，不过我们细心的码农还是会启动验证一下,看看有没有问题。&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Modifyapk/start1.png&#34; alt=&#34;start1&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:start1&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;坏蛋，果然给我们埋坑了。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_过坑&#34;&gt;过坑&lt;/h3&gt;&lt;p&gt;跑路的程序员还是厚道，明明白白告诉咱们是由于签名被篡改了。&lt;/p&gt;
&lt;p&gt;上jadx，搜索  &lt;mark&gt;签名被篡改&lt;/mark&gt;&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Modifyapk/modify1.png&#34; alt=&#34;modify1&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:modify1&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;需要把这个 if判断干掉&lt;/p&gt;
&lt;p&gt;问了一下AI，把对应的 Smail 代码中对应的 if-nez p1 改成  if-eqz p1 就行了&lt;/p&gt;
&lt;p&gt;TIP:&lt;/p&gt;
&lt;p&gt;| &lt;code&gt;if-nez p1&lt;/code&gt; | 如果 &lt;code&gt;p1 != 0&lt;/code&gt;，则跳转（非零成立） |&lt;/p&gt;
&lt;p&gt;| &lt;code&gt;if-eqz p1&lt;/code&gt; | 如果 &lt;code&gt;p1 == 0&lt;/code&gt;，则跳转（零成立）  |&lt;/p&gt;
&lt;p&gt;真的没必要去学Smail语法了，现成的AI在嗷嗷待哺&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_三总结&#34;&gt;三、总结&lt;/h2&gt;&lt;p&gt;由于apk修改起来太容易了，所以程序员gg们会在里面埋更多的坑。加壳 反调试 混淆 前面还有无数困难等着你。&lt;/p&gt;
&lt;p&gt;李老板决定还是招个程序员鼓励师比较靠谱。&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Modifyapk/ffshow.png&#34; alt=&#34;ffshow&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ffshow&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;mark&gt;非真空不宜谈禅，非真旷不宜饮酒。&lt;/mark&gt;&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;本文的目的只有一个就是学习更多的逆向技巧和思路，如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担，和本文以及作者没关系，本文涉及到的代码项目可以去 &lt;mark&gt;奋飞的朋友们&lt;/mark&gt; 知识星球自取，欢迎加入知识星球一起学习探讨技术。有问题可以加我wx: &lt;mark&gt;fenfei331&lt;/mark&gt; 讨论下。&lt;/p&gt;&lt;/aside&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ffzsxq.jpg&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;
&lt;p&gt;关注微信公众号，最新技术干货实时推送&lt;/p&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ff330.png&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;&lt;/section&gt;&lt;/div&gt;&lt;footer&gt;&lt;div id=&#34;footer-text&#34;&gt;&lt;br/&gt;Last updated 2026-04-27 18:48:44 +0800&lt;/div&gt;&lt;/footer&gt;
</description>
      
    </item>
    
    <item>
      <title>结合AI对WhatsApp的分析（三）</title>
      <link>http://91fans.com.cn/post/whatsappthr/</link>
      <pubDate>Sun, 13 Apr 2025 11:52:20 +0800</pubDate>
      
      <guid>http://91fans.com.cn/post/whatsappthr/</guid>
      
        <description>&lt;meta charset=&#34;UTF-8&#34;/&gt;&lt;meta http-equiv=&#34;X-UA-Compatible&#34; content=&#34;IE=edge&#34;/&gt;&lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;/&gt;&lt;meta name=&#34;generator&#34; content=&#34;Asciidoctor 2.0.20&#34;/&gt;&lt;title&gt;一、目标&lt;/title&gt;&lt;style&gt;/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import &#34;https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700&#34;; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:&#34;\201C&#34; &#34;\201D&#34; &#34;\2018&#34; &#34;\2019&#34;}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock&gt;.content&gt;.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock&gt;.content&gt;.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:&#34; &#34;;display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])&gt;code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre&gt;code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:&#34;[&#34;;padding:0 3px 0 2px}
b.button::after{content:&#34;]&#34;;padding:0 2px 0 3px}
p a&gt;code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:&#34; &#34;;display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header&gt;h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header&gt;h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header&gt;h1:only-child,body.toc2 #header&gt;h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:&#34;\00a0\2013\00a0&#34;}
#header .details br+span.author::before{content:&#34;\00a0\22c5\00a0&#34;;color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:&#34;\00a0|\00a0&#34;}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:&#34;\00a0&#34;}
#content&gt;h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc&gt;ul{margin-left:.125em}
#toc ul.sectlevel0&gt;li&gt;a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2&gt;ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2&gt;ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc&gt;:first-child{margin-top:0}
#content #toc&gt;:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1&gt;a.anchor,h2&gt;a.anchor,h3&gt;a.anchor,#toctitle&gt;a.anchor,.sidebarblock&gt;.content&gt;.title&gt;a.anchor,h4&gt;a.anchor,h5&gt;a.anchor,h6&gt;a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1&gt;a.anchor::before,h2&gt;a.anchor::before,h3&gt;a.anchor::before,#toctitle&gt;a.anchor::before,.sidebarblock&gt;.content&gt;.title&gt;a.anchor::before,h4&gt;a.anchor::before,h5&gt;a.anchor::before,h6&gt;a.anchor::before{content:&#34;\00A7&#34;;font-size:.85em;display:block;padding-top:.1em}
#content h1:hover&gt;a.anchor,#content h1&gt;a.anchor:hover,h2:hover&gt;a.anchor,h2&gt;a.anchor:hover,h3:hover&gt;a.anchor,#toctitle:hover&gt;a.anchor,.sidebarblock&gt;.content&gt;.title:hover&gt;a.anchor,h3&gt;a.anchor:hover,#toctitle&gt;a.anchor:hover,.sidebarblock&gt;.content&gt;.title&gt;a.anchor:hover,h4:hover&gt;a.anchor,h4&gt;a.anchor:hover,h5:hover&gt;a.anchor,h5&gt;a.anchor:hover,h6:hover&gt;a.anchor,h6&gt;a.anchor:hover{visibility:visible}
#content h1&gt;a.link,h2&gt;a.link,h3&gt;a.link,#toctitle&gt;a.link,.sidebarblock&gt;.content&gt;.title&gt;a.link,h4&gt;a.link,h5&gt;a.link,h6&gt;a.link{color:#ba3925;text-decoration:none}
#content h1&gt;a.link:hover,h2&gt;a.link:hover,h3&gt;a.link:hover,#toctitle&gt;a.link:hover,.sidebarblock&gt;.content&gt;.title&gt;a.link:hover,h4&gt;a.link:hover,h5&gt;a.link:hover,h6&gt;a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details&gt;summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details&gt;summary::-webkit-details-marker{display:none}
details&gt;summary::before{content:&#34;&#34;;border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]&gt;summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details&gt;summary::after{content:&#34;&#34;;width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{text-rendering:optimizeLegibility;text-align:left;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content&gt;caption.title{white-space:nowrap;width:0}
.paragraph.lead&gt;p,#preamble&gt;.sectionbody&gt;[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock&gt;table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock&gt;table td.icon{text-align:center;width:80px}
.admonitionblock&gt;table td.icon img{max-width:none}
.admonitionblock&gt;table td.icon .title{font-weight:bold;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;text-transform:uppercase}
.admonitionblock&gt;table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock&gt;table td.content&gt;:last-child&gt;:last-child{margin-bottom:0}
.exampleblock&gt;.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock&gt;.content&gt;.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock&gt;.content&gt;:first-child,.sidebarblock&gt;.content&gt;:first-child{margin-top:0}
.exampleblock&gt;.content&gt;:last-child,.exampleblock&gt;.content&gt;:last-child&gt;:last-child,.exampleblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child&gt;:last-child,.sidebarblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child{margin-bottom:0}
.literalblock pre,.listingblock&gt;.content&gt;pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:1em}}
.literalblock pre,.listingblock&gt;.content&gt;pre:not(.highlight),.listingblock&gt;.content&gt;pre[class=highlight],.listingblock&gt;.content&gt;pre[class^=&#34;highlight &#34;]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock&gt;.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:&#34;$&#34;}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs&gt;code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)&gt;.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:&#34;\201c&#34;;float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote&gt;.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract&gt;.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt&gt;blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock&gt;.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock&gt;.content&gt;:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all&gt;*&gt;tr&gt;*{border-width:1px}
table.grid-cols&gt;*&gt;tr&gt;*{border-width:0 1px}
table.grid-rows&gt;*&gt;tr&gt;*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none&gt;colgroup+*&gt;:first-child&gt;*,table.frame-sides&gt;colgroup+*&gt;:first-child&gt;*{border-top-width:0}
table.frame-none&gt;:last-child&gt;:last-child&gt;*,table.frame-sides&gt;:last-child&gt;:last-child&gt;*{border-bottom-width:0}
table.frame-none&gt;*&gt;tr&gt;:first-child,table.frame-ends&gt;*&gt;tr&gt;:first-child{border-left-width:0}
table.frame-none&gt;*&gt;tr&gt;:last-child,table.frame-ends&gt;*&gt;tr&gt;:last-child{border-right-width:0}
table.stripes-all&gt;*&gt;tr,table.stripes-odd&gt;*&gt;tr:nth-of-type(odd),table.stripes-even&gt;*&gt;tr:nth-of-type(even),table.stripes-hover&gt;*&gt;tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock&gt;code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child&gt;:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li&gt;p:empty:only-child::before{content:&#34;&#34;;display:inline-block}
ul.checklist&gt;li&gt;p:first-child{margin-left:-1em}
ul.checklist&gt;li&gt;p:first-child&gt;.fa-square-o:first-child,ul.checklist&gt;li&gt;p:first-child&gt;.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist&gt;li&gt;p:first-child&gt;input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline&gt;li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist&gt;table,.colist&gt;table{border:0;background:none}
.hdlist&gt;table&gt;tbody&gt;tr,.colist&gt;table&gt;tbody&gt;tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock&gt;.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb&gt;.title,.imageblock.th&gt;.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon&gt;.fa{cursor:default}
a span.icon&gt;.fa{cursor:inherit}
.admonitionblock td.icon [class^=&#34;fa icon-&#34;]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:&#34;\f05a&#34;;color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:&#34;\f0eb&#34;;text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:&#34;\f071&#34;;color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:&#34;\f06d&#34;;color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:&#34;\f06a&#34;;color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock&gt;.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^=&#34;#&#34;],a[href^=&#34;mailto:&#34;]{text-decoration:none!important}
a[href^=&#34;http:&#34;]:not(.bare)::after,a[href^=&#34;https:&#34;]:not(.bare)::after{content:&#34;(&#34; attr(href) &#34;)&#34;;display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:&#34; (&#34; attr(title) &#34;)&#34;}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock&gt;.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header&gt;h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1&gt;h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header&gt;h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}&lt;/style&gt;
&lt;style&gt;
/*! Stylesheet for CodeRay to loosely match GitHub themes | MIT License */
pre.CodeRay{background:#f7f7f8}
.CodeRay .line-numbers{border-right:1px solid;opacity:.35;padding:0 .5em 0 0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.CodeRay span.line-numbers{display:inline-block;margin-right:.75em}
.CodeRay .line-numbers strong{color:#000}
table.CodeRay{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.CodeRay td{vertical-align:top;line-height:inherit}
table.CodeRay td.line-numbers{text-align:right}
table.CodeRay td.code{padding:0 0 0 .75em}
.CodeRay .debug{color:#fff!important;background:navy!important}
.CodeRay .annotation{color:#007}
.CodeRay .attribute-name{color:navy}
.CodeRay .attribute-value{color:#700}
.CodeRay .binary{color:#509}
.CodeRay .comment{color:#998;font-style:italic}
.CodeRay .char{color:#04d}
.CodeRay .char .content{color:#04d}
.CodeRay .char .delimiter{color:#039}
.CodeRay .class{color:#458;font-weight:bold}
.CodeRay .complex{color:#a08}
.CodeRay .constant,.CodeRay .predefined-constant{color:teal}
.CodeRay .color{color:#099}
.CodeRay .class-variable{color:#369}
.CodeRay .decorator{color:#b0b}
.CodeRay .definition{color:#099}
.CodeRay .delimiter{color:#000}
.CodeRay .doc{color:#970}
.CodeRay .doctype{color:#34b}
.CodeRay .doc-string{color:#d42}
.CodeRay .escape{color:#666}
.CodeRay .entity{color:#800}
.CodeRay .error{color:#808}
.CodeRay .exception{color:inherit}
.CodeRay .filename{color:#099}
.CodeRay .function{color:#900;font-weight:bold}
.CodeRay .global-variable{color:teal}
.CodeRay .hex{color:#058}
.CodeRay .integer,.CodeRay .float{color:#099}
.CodeRay .include{color:#555}
.CodeRay .inline{color:#000}
.CodeRay .inline .inline{background:#ccc}
.CodeRay .inline .inline .inline{background:#bbb}
.CodeRay .inline .inline-delimiter{color:#d14}
.CodeRay .inline-delimiter{color:#d14}
.CodeRay .important{color:#555;font-weight:bold}
.CodeRay .interpreted{color:#b2b}
.CodeRay .instance-variable{color:teal}
.CodeRay .label{color:#970}
.CodeRay .local-variable{color:#963}
.CodeRay .octal{color:#40e}
.CodeRay .predefined{color:#369}
.CodeRay .preprocessor{color:#579}
.CodeRay .pseudo-class{color:#555}
.CodeRay .directive{font-weight:bold}
.CodeRay .type{font-weight:bold}
.CodeRay .predefined-type{color:inherit}
.CodeRay .reserved,.CodeRay .keyword{color:#000;font-weight:bold}
.CodeRay .key{color:#808}
.CodeRay .key .delimiter{color:#606}
.CodeRay .key .char{color:#80f}
.CodeRay .value{color:#088}
.CodeRay .regexp .delimiter{color:#808}
.CodeRay .regexp .content{color:#808}
.CodeRay .regexp .modifier{color:#808}
.CodeRay .regexp .char{color:#d14}
.CodeRay .regexp .function{color:#404;font-weight:bold}
.CodeRay .string{color:#d20}
.CodeRay .string .string .string{background:#ffd0d0}
.CodeRay .string .content{color:#d14}
.CodeRay .string .char{color:#d14}
.CodeRay .string .delimiter{color:#d14}
.CodeRay .shell{color:#d14}
.CodeRay .shell .delimiter{color:#d14}
.CodeRay .symbol{color:#990073}
.CodeRay .symbol .content{color:#a60}
.CodeRay .symbol .delimiter{color:#630}
.CodeRay .tag{color:teal}
.CodeRay .tag-special{color:#d70}
.CodeRay .variable{color:#036}
.CodeRay .insert{background:#afa}
.CodeRay .delete{background:#faa}
.CodeRay .change{color:#aaf;background:#007}
.CodeRay .head{color:#f8f;background:#505}
.CodeRay .insert .insert{color:#080}
.CodeRay .delete .delete{color:#800}
.CodeRay .change .change{color:#66f}
.CodeRay .head .head{color:#f4f}
&lt;/style&gt;&lt;/head&gt;&lt;body class=&#34;article&#34;&gt;&lt;header&gt;&lt;/header&gt;&lt;div id=&#34;content&#34;&gt;&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_一目标&#34;&gt;一、目标&lt;/h2&gt;&lt;p&gt;书接上文 &lt;a href=&#34;http://91fans.com.cn/post/whatsapptow/&#34;&gt;结合AI对WhatsApp的分析（二）&lt;/a&gt; ，我们找到了 &lt;mark&gt;jnidispatchOO&lt;/mark&gt; ，下一步就是搞定它的具体算法。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_二步骤&#34;&gt;二、步骤&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_先hook&#34;&gt;先HOOK&lt;/h3&gt;&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;let JniBridge = Java.use(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;com.whatsapp.wamsys.JniBridge&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
JniBridge[&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;jnidispatchOO&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;].&lt;span class=&#34;function&#34;&gt;implementation&lt;/span&gt; = &lt;span class=&#34;keyword&#34;&gt;function&lt;/span&gt; (i, obj) {

        let bCls = Java.use(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;[B&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;)

        &lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt;(i == &lt;span class=&#34;integer&#34;&gt;3&lt;/span&gt;){
                let buffer = Java.cast(obj, bCls);
                let rc1 = Java.array(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;byte&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;, buffer);

                console.log(&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt; ---- JniBridge.jnidispatchOO is called: i=&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{i}, obj=&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{buf2hex(rc1)}&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;);
        }

        let result = &lt;span class=&#34;local-variable&#34;&gt;this&lt;/span&gt;[&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;jnidispatchOO&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;](i, obj);

        &lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt;(i == &lt;span class=&#34;integer&#34;&gt;3&lt;/span&gt;){
                let buffer2 = Java.cast(result, bCls);
                let rc2 = Java.array(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;byte&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;, buffer2);

                console.log(&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt; ---- JniBridge.jnidispatchOO result = &lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{buf2hex(rc2)}&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;);
        }
        &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; result;
};&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;跑一下&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt; ---- JniBridge.jnidispatchOO result = &lt;span class=&#34;integer&#34;&gt;3045022031&lt;/span&gt;c495bb8bf2bbe39124b0c539cc0929e3d6cf1960874ecd019a0e7412160506022100a056754c60d842fd2e12aa06fd00aae06999d8808e213875424e4489ce26ff28

&lt;span class=&#34;comment&#34;&gt;// 对应的 base64 = MEUCIDHElbuL8rvjkSSwxTnMCSnj1s8ZYIdOzQGaDnQSFgUGAiEAoFZ1TGDYQv0uEqoG/QCq4GmZ2ICOITh1Qk5Eic4m/yg=&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;确认了眼神，这次没错了&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_上jadx&#34;&gt;上Jadx&lt;/h3&gt;&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;&lt;span class=&#34;reserved&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;reserved&#34;&gt;static&lt;/span&gt; Object jnidispatchOO(&lt;span class=&#34;reserved&#34;&gt;int&lt;/span&gt; i, Object obj) {
    ...
     &lt;span class=&#34;keyword&#34;&gt;case&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;3&lt;/span&gt;:
        &lt;span class=&#34;reserved&#34;&gt;byte&lt;/span&gt;[] bArr2 = (&lt;span class=&#34;reserved&#34;&gt;byte&lt;/span&gt;[]) obj;
        C51032Wh c51032Wh = (C51032Wh) INSTANCE.jniCallbacksIJniCallbacks.A04.get();
        &lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; (!AbstractC17350u8.A01() || bArr2 == &lt;span class=&#34;predefined-constant&#34;&gt;null&lt;/span&gt;) {
            &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;predefined-constant&#34;&gt;null&lt;/span&gt;;
        }
        &lt;span class=&#34;comment&#34;&gt;// 这个 A01.A07 应该就是计算H的位置&lt;/span&gt;
        &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; c51032Wh.A01.A07(bArr2, c51032Wh.A00.A0J());
    ...
}

&lt;span class=&#34;comment&#34;&gt;// X.17J&lt;/span&gt;
 &lt;span class=&#34;reserved&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;reserved&#34;&gt;byte&lt;/span&gt;[] A07(&lt;span class=&#34;reserved&#34;&gt;byte&lt;/span&gt;[] bArr, &lt;span class=&#34;reserved&#34;&gt;byte&lt;/span&gt;[] bArr2) {
        &lt;span class=&#34;reserved&#34;&gt;byte&lt;/span&gt;[] bArr3 = &lt;span class=&#34;predefined-constant&#34;&gt;null&lt;/span&gt;;
        &lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; (!A06()) {
            &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;predefined-constant&#34;&gt;null&lt;/span&gt;;
        }
        A02(C00Q.A01, bArr2);
        &lt;span class=&#34;reserved&#34;&gt;long&lt;/span&gt; elapsedRealtime = SystemClock.elapsedRealtime();
        &lt;span class=&#34;keyword&#34;&gt;try&lt;/span&gt; {
            &lt;span class=&#34;keyword&#34;&gt;try&lt;/span&gt; {
                                &lt;span class=&#34;comment&#34;&gt;// 从android的KeyStore拿到密钥&lt;/span&gt;
                KeyStore keyStore = KeyStore.getInstance(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;AndroidKeyStore&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
                keyStore.load(&lt;span class=&#34;predefined-constant&#34;&gt;null&lt;/span&gt;);
                KeyStore.Entry entry = keyStore.getEntry(A01(), &lt;span class=&#34;predefined-constant&#34;&gt;null&lt;/span&gt;);
                &lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; (entry &lt;span class=&#34;keyword&#34;&gt;instanceof&lt;/span&gt; KeyStore.PrivateKeyEntry) {
                    Signature signature = Signature.getInstance(AbstractC15060oI.A01(C15080oK.A02, &lt;span class=&#34;local-variable&#34;&gt;this&lt;/span&gt;.A02, &lt;span class=&#34;integer&#34;&gt;2075&lt;/span&gt;));
                    signature.initSign(((KeyStore.PrivateKeyEntry) entry).getPrivateKey());
                    signature.update(bArr);
                                        &lt;span class=&#34;comment&#34;&gt;// H 就是这里来的&lt;/span&gt;
                    bArr3 = signature.sign();
                } &lt;span class=&#34;keyword&#34;&gt;else&lt;/span&gt; {
                    Log.e(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;blacknoise/Not an instance of a PKEntry&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
                    &lt;span class=&#34;local-variable&#34;&gt;this&lt;/span&gt;.A04.A0H(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;attestation-nosign&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;cannot sign payload, att pair missing&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&#34;predefined-constant&#34;&gt;true&lt;/span&gt;);
                }
            } &lt;span class=&#34;keyword&#34;&gt;catch&lt;/span&gt; (Exception e) {
                Log.e(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;blacknoise/exception on pair sign&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, e);
                AbstractC213314r abstractC213314r = &lt;span class=&#34;local-variable&#34;&gt;this&lt;/span&gt;.A04;
                StringBuilder sb = &lt;span class=&#34;keyword&#34;&gt;new&lt;/span&gt; StringBuilder();
                sb.append(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;unable to sign payload: &lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
                sb.append(e.getMessage());
                abstractC213314r.A0F(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;attestation-nosign&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, sb.toString(), e);
            }
            &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; bArr3;
        } &lt;span class=&#34;keyword&#34;&gt;finally&lt;/span&gt; {
            C17K c17k = &lt;span class=&#34;keyword&#34;&gt;new&lt;/span&gt; C17K();
            c17k.A00 = Long.valueOf(SystemClock.elapsedRealtime() - elapsedRealtime);
            c17k.A02 = &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;att-sign&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;;
            &lt;span class=&#34;local-variable&#34;&gt;this&lt;/span&gt;.A06.CG2(c17k);
        }
    }&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;我们再 Hook一下 java.security.Signature.getInstance&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; Signature = Java.use(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;java.security.Signature&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);

Signature.getInstance.overload(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;java.lang.String&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;).&lt;span class=&#34;function&#34;&gt;implementation&lt;/span&gt; = &lt;span class=&#34;keyword&#34;&gt;function&lt;/span&gt;(algorithm) {
        console.log(&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;comment&#34;&gt;/* TID ${gettid()} */&lt;/span&gt;&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt; + &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;[*] Hooked Signature.getInstance&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
        console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;    Algorithm: &lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; + algorithm);
    &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;local-variable&#34;&gt;this&lt;/span&gt;.getInstance(algorithm);
};

&lt;span class=&#34;comment&#34;&gt;// 打印&lt;/span&gt;
&lt;span class=&#34;comment&#34;&gt;/* TID 10091 */&lt;/span&gt;[*] Hooked Signature.getInstance
    Algorithm: SHA256withECDSA&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这次形势明朗了 SHA256withECDSA&lt;/p&gt;
&lt;p&gt;App生成一对ECDSA的公钥和私钥，本地用私钥给数据做sign，把公钥和sign结果传给服务器，服务器用公钥去做verify。&lt;/p&gt;
&lt;p&gt;把这些数据扔给AI，AI轻松就把Demo代码写好了。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_新的问题证书不对&#34;&gt;新的问题，证书不对。&lt;/h3&gt;&lt;p&gt;公钥上传的位置只有一种可能，放在请求头的 &lt;mark&gt;Authorization&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;新的问题是，AI给我生成的公钥是91个字节，明显小于 &lt;mark&gt;Authorization&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;继续问AI&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;ME: MIIFHDCCAwSgAwIBAgIJANUP8luj8tazMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV(完整的Authorization头贴上去) 为什么这个证书这么长，我只需要SHA256withECDSA的公钥证书，应该是91个字节才对

AI: 你贴的是一大串 Base64 编码后的证书链，这其实是**X.509 证书（或多个）**的完整内容，被编码成了一大段字符串，常见于 .pem 或 .crt 文件中。
确实看起来非常长，但这并不是“公钥”的长度，而是整个证书的编码内容。

解答你的两个关键疑问：
❓ 1. 为什么这个证书这么长？
因为它不仅仅包含公钥，而是包含了：

签名算法标识（如 SHA256withECDSA）
公钥（你想要的）
证书所有者信息（issuer, subject, 序列号等）
有效期（not before / not after）
签名值
扩展字段（可能还包含 CA 标识、密钥用法等）
这些内容都被 ASN.1/DER 格式编码，然后再被 base64 编码，所以变得很长。

❓ 2. 我只需要 SHA256withECDSA 的公钥部分，应该是 91 字节左右，怎么提取？
你说的“91字节”是 ECDSA P-256（secp256r1）曲线上的压缩公钥长度：

压缩格式：33 字节
未压缩格式：65 字节
公钥 DER 编码结构，整体会有 91 个字节左右（SEQUENCE -&amp;gt; BIT STRING -&amp;gt; ECPoint）

需要哪种？可以直接发一句：“帮我提取公钥（hex）”之类的，我马上给你。&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;必须要，帮我写个python代码把里面的 SHA256withECDSA 提取出来，然后写个 verify 的Demo。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_三总结&#34;&gt;三、总结&lt;/h2&gt;&lt;p&gt;AI不能直接帮你写好ws的H算法，但是能按照你的思路辅助你把H算法写出来。&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Whatsappthr/ffshow.png&#34; alt=&#34;ffshow&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ffshow&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;mark&gt;AI只是强健的四肢+翅膀，你才是大脑，决定飞向哪里&lt;/mark&gt;&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;: 本文的目的只有一个就是学习更多的逆向技巧和思路，如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担，和本文以及作者没关系，本文涉及到的代码项目可以去 &lt;mark&gt;奋飞的朋友们&lt;/mark&gt; 知识星球自取，欢迎加入知识星球一起学习探讨技术。有问题可以加我wx: &lt;mark&gt;fenfei331&lt;/mark&gt; 讨论下。&lt;/p&gt;&lt;/aside&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ffzsxq.jpg&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;
&lt;p&gt;关注微信公众号，最新技术干货实时推送&lt;/p&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ff330.png&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;&lt;/section&gt;&lt;/div&gt;&lt;footer&gt;&lt;div id=&#34;footer-text&#34;&gt;&lt;br/&gt;Last updated 2026-04-27 18:48:46 +0800&lt;/div&gt;&lt;/footer&gt;
</description>
      
    </item>
    
    <item>
      <title>结合AI对WhatsApp的分析（二）</title>
      <link>http://91fans.com.cn/post/whatsapptwo/</link>
      <pubDate>Sat, 29 Mar 2025 11:52:07 +0800</pubDate>
      
      <guid>http://91fans.com.cn/post/whatsapptwo/</guid>
      
        <description>&lt;meta charset=&#34;UTF-8&#34;/&gt;&lt;meta http-equiv=&#34;X-UA-Compatible&#34; content=&#34;IE=edge&#34;/&gt;&lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;/&gt;&lt;meta name=&#34;generator&#34; content=&#34;Asciidoctor 2.0.20&#34;/&gt;&lt;title&gt;一、目标&lt;/title&gt;&lt;style&gt;/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import &#34;https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700&#34;; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:&#34;\201C&#34; &#34;\201D&#34; &#34;\2018&#34; &#34;\2019&#34;}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock&gt;.content&gt;.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock&gt;.content&gt;.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:&#34; &#34;;display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])&gt;code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre&gt;code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:&#34;[&#34;;padding:0 3px 0 2px}
b.button::after{content:&#34;]&#34;;padding:0 2px 0 3px}
p a&gt;code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:&#34; &#34;;display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header&gt;h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header&gt;h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header&gt;h1:only-child,body.toc2 #header&gt;h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:&#34;\00a0\2013\00a0&#34;}
#header .details br+span.author::before{content:&#34;\00a0\22c5\00a0&#34;;color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:&#34;\00a0|\00a0&#34;}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:&#34;\00a0&#34;}
#content&gt;h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc&gt;ul{margin-left:.125em}
#toc ul.sectlevel0&gt;li&gt;a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2&gt;ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2&gt;ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc&gt;:first-child{margin-top:0}
#content #toc&gt;:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1&gt;a.anchor,h2&gt;a.anchor,h3&gt;a.anchor,#toctitle&gt;a.anchor,.sidebarblock&gt;.content&gt;.title&gt;a.anchor,h4&gt;a.anchor,h5&gt;a.anchor,h6&gt;a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1&gt;a.anchor::before,h2&gt;a.anchor::before,h3&gt;a.anchor::before,#toctitle&gt;a.anchor::before,.sidebarblock&gt;.content&gt;.title&gt;a.anchor::before,h4&gt;a.anchor::before,h5&gt;a.anchor::before,h6&gt;a.anchor::before{content:&#34;\00A7&#34;;font-size:.85em;display:block;padding-top:.1em}
#content h1:hover&gt;a.anchor,#content h1&gt;a.anchor:hover,h2:hover&gt;a.anchor,h2&gt;a.anchor:hover,h3:hover&gt;a.anchor,#toctitle:hover&gt;a.anchor,.sidebarblock&gt;.content&gt;.title:hover&gt;a.anchor,h3&gt;a.anchor:hover,#toctitle&gt;a.anchor:hover,.sidebarblock&gt;.content&gt;.title&gt;a.anchor:hover,h4:hover&gt;a.anchor,h4&gt;a.anchor:hover,h5:hover&gt;a.anchor,h5&gt;a.anchor:hover,h6:hover&gt;a.anchor,h6&gt;a.anchor:hover{visibility:visible}
#content h1&gt;a.link,h2&gt;a.link,h3&gt;a.link,#toctitle&gt;a.link,.sidebarblock&gt;.content&gt;.title&gt;a.link,h4&gt;a.link,h5&gt;a.link,h6&gt;a.link{color:#ba3925;text-decoration:none}
#content h1&gt;a.link:hover,h2&gt;a.link:hover,h3&gt;a.link:hover,#toctitle&gt;a.link:hover,.sidebarblock&gt;.content&gt;.title&gt;a.link:hover,h4&gt;a.link:hover,h5&gt;a.link:hover,h6&gt;a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details&gt;summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details&gt;summary::-webkit-details-marker{display:none}
details&gt;summary::before{content:&#34;&#34;;border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]&gt;summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details&gt;summary::after{content:&#34;&#34;;width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{text-rendering:optimizeLegibility;text-align:left;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content&gt;caption.title{white-space:nowrap;width:0}
.paragraph.lead&gt;p,#preamble&gt;.sectionbody&gt;[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock&gt;table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock&gt;table td.icon{text-align:center;width:80px}
.admonitionblock&gt;table td.icon img{max-width:none}
.admonitionblock&gt;table td.icon .title{font-weight:bold;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;text-transform:uppercase}
.admonitionblock&gt;table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock&gt;table td.content&gt;:last-child&gt;:last-child{margin-bottom:0}
.exampleblock&gt;.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock&gt;.content&gt;.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock&gt;.content&gt;:first-child,.sidebarblock&gt;.content&gt;:first-child{margin-top:0}
.exampleblock&gt;.content&gt;:last-child,.exampleblock&gt;.content&gt;:last-child&gt;:last-child,.exampleblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child&gt;:last-child,.sidebarblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child{margin-bottom:0}
.literalblock pre,.listingblock&gt;.content&gt;pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:1em}}
.literalblock pre,.listingblock&gt;.content&gt;pre:not(.highlight),.listingblock&gt;.content&gt;pre[class=highlight],.listingblock&gt;.content&gt;pre[class^=&#34;highlight &#34;]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock&gt;.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:&#34;$&#34;}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs&gt;code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)&gt;.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:&#34;\201c&#34;;float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote&gt;.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract&gt;.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt&gt;blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock&gt;.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock&gt;.content&gt;:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all&gt;*&gt;tr&gt;*{border-width:1px}
table.grid-cols&gt;*&gt;tr&gt;*{border-width:0 1px}
table.grid-rows&gt;*&gt;tr&gt;*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none&gt;colgroup+*&gt;:first-child&gt;*,table.frame-sides&gt;colgroup+*&gt;:first-child&gt;*{border-top-width:0}
table.frame-none&gt;:last-child&gt;:last-child&gt;*,table.frame-sides&gt;:last-child&gt;:last-child&gt;*{border-bottom-width:0}
table.frame-none&gt;*&gt;tr&gt;:first-child,table.frame-ends&gt;*&gt;tr&gt;:first-child{border-left-width:0}
table.frame-none&gt;*&gt;tr&gt;:last-child,table.frame-ends&gt;*&gt;tr&gt;:last-child{border-right-width:0}
table.stripes-all&gt;*&gt;tr,table.stripes-odd&gt;*&gt;tr:nth-of-type(odd),table.stripes-even&gt;*&gt;tr:nth-of-type(even),table.stripes-hover&gt;*&gt;tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock&gt;code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child&gt;:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li&gt;p:empty:only-child::before{content:&#34;&#34;;display:inline-block}
ul.checklist&gt;li&gt;p:first-child{margin-left:-1em}
ul.checklist&gt;li&gt;p:first-child&gt;.fa-square-o:first-child,ul.checklist&gt;li&gt;p:first-child&gt;.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist&gt;li&gt;p:first-child&gt;input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline&gt;li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist&gt;table,.colist&gt;table{border:0;background:none}
.hdlist&gt;table&gt;tbody&gt;tr,.colist&gt;table&gt;tbody&gt;tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock&gt;.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb&gt;.title,.imageblock.th&gt;.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon&gt;.fa{cursor:default}
a span.icon&gt;.fa{cursor:inherit}
.admonitionblock td.icon [class^=&#34;fa icon-&#34;]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:&#34;\f05a&#34;;color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:&#34;\f0eb&#34;;text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:&#34;\f071&#34;;color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:&#34;\f06d&#34;;color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:&#34;\f06a&#34;;color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock&gt;.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^=&#34;#&#34;],a[href^=&#34;mailto:&#34;]{text-decoration:none!important}
a[href^=&#34;http:&#34;]:not(.bare)::after,a[href^=&#34;https:&#34;]:not(.bare)::after{content:&#34;(&#34; attr(href) &#34;)&#34;;display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:&#34; (&#34; attr(title) &#34;)&#34;}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock&gt;.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header&gt;h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1&gt;h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header&gt;h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}&lt;/style&gt;
&lt;style&gt;
/*! Stylesheet for CodeRay to loosely match GitHub themes | MIT License */
pre.CodeRay{background:#f7f7f8}
.CodeRay .line-numbers{border-right:1px solid;opacity:.35;padding:0 .5em 0 0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.CodeRay span.line-numbers{display:inline-block;margin-right:.75em}
.CodeRay .line-numbers strong{color:#000}
table.CodeRay{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.CodeRay td{vertical-align:top;line-height:inherit}
table.CodeRay td.line-numbers{text-align:right}
table.CodeRay td.code{padding:0 0 0 .75em}
.CodeRay .debug{color:#fff!important;background:navy!important}
.CodeRay .annotation{color:#007}
.CodeRay .attribute-name{color:navy}
.CodeRay .attribute-value{color:#700}
.CodeRay .binary{color:#509}
.CodeRay .comment{color:#998;font-style:italic}
.CodeRay .char{color:#04d}
.CodeRay .char .content{color:#04d}
.CodeRay .char .delimiter{color:#039}
.CodeRay .class{color:#458;font-weight:bold}
.CodeRay .complex{color:#a08}
.CodeRay .constant,.CodeRay .predefined-constant{color:teal}
.CodeRay .color{color:#099}
.CodeRay .class-variable{color:#369}
.CodeRay .decorator{color:#b0b}
.CodeRay .definition{color:#099}
.CodeRay .delimiter{color:#000}
.CodeRay .doc{color:#970}
.CodeRay .doctype{color:#34b}
.CodeRay .doc-string{color:#d42}
.CodeRay .escape{color:#666}
.CodeRay .entity{color:#800}
.CodeRay .error{color:#808}
.CodeRay .exception{color:inherit}
.CodeRay .filename{color:#099}
.CodeRay .function{color:#900;font-weight:bold}
.CodeRay .global-variable{color:teal}
.CodeRay .hex{color:#058}
.CodeRay .integer,.CodeRay .float{color:#099}
.CodeRay .include{color:#555}
.CodeRay .inline{color:#000}
.CodeRay .inline .inline{background:#ccc}
.CodeRay .inline .inline .inline{background:#bbb}
.CodeRay .inline .inline-delimiter{color:#d14}
.CodeRay .inline-delimiter{color:#d14}
.CodeRay .important{color:#555;font-weight:bold}
.CodeRay .interpreted{color:#b2b}
.CodeRay .instance-variable{color:teal}
.CodeRay .label{color:#970}
.CodeRay .local-variable{color:#963}
.CodeRay .octal{color:#40e}
.CodeRay .predefined{color:#369}
.CodeRay .preprocessor{color:#579}
.CodeRay .pseudo-class{color:#555}
.CodeRay .directive{font-weight:bold}
.CodeRay .type{font-weight:bold}
.CodeRay .predefined-type{color:inherit}
.CodeRay .reserved,.CodeRay .keyword{color:#000;font-weight:bold}
.CodeRay .key{color:#808}
.CodeRay .key .delimiter{color:#606}
.CodeRay .key .char{color:#80f}
.CodeRay .value{color:#088}
.CodeRay .regexp .delimiter{color:#808}
.CodeRay .regexp .content{color:#808}
.CodeRay .regexp .modifier{color:#808}
.CodeRay .regexp .char{color:#d14}
.CodeRay .regexp .function{color:#404;font-weight:bold}
.CodeRay .string{color:#d20}
.CodeRay .string .string .string{background:#ffd0d0}
.CodeRay .string .content{color:#d14}
.CodeRay .string .char{color:#d14}
.CodeRay .string .delimiter{color:#d14}
.CodeRay .shell{color:#d14}
.CodeRay .shell .delimiter{color:#d14}
.CodeRay .symbol{color:#990073}
.CodeRay .symbol .content{color:#a60}
.CodeRay .symbol .delimiter{color:#630}
.CodeRay .tag{color:teal}
.CodeRay .tag-special{color:#d70}
.CodeRay .variable{color:#036}
.CodeRay .insert{background:#afa}
.CodeRay .delete{background:#faa}
.CodeRay .change{color:#aaf;background:#007}
.CodeRay .head{color:#f8f;background:#505}
.CodeRay .insert .insert{color:#080}
.CodeRay .delete .delete{color:#800}
.CodeRay .change .change{color:#66f}
.CodeRay .head .head{color:#f4f}
&lt;/style&gt;&lt;/head&gt;&lt;body class=&#34;article&#34;&gt;&lt;header&gt;&lt;/header&gt;&lt;div id=&#34;content&#34;&gt;&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_一目标&#34;&gt;一、目标&lt;/h2&gt;&lt;p&gt;书接上文 &lt;a href=&#34;http://91fans.com.cn/post/whatsappone/&#34;&gt;结合AI对WhatsApp的分析（一）&lt;/a&gt; ，我们已经定位了 &lt;mark&gt;H&lt;/mark&gt; 参数，下一步就是分析一下它的来历。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_二步骤&#34;&gt;二、步骤&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_堆栈定位&#34;&gt;堆栈定位&lt;/h3&gt;&lt;p&gt;H 被计算的位置有两种可能，一种是java层，一种是Native层，我们先顺着堆栈往上找&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Whatsapptwo/stack1.png&#34; alt=&#34;stack1&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:stack1&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;柿子得找软的捏，我们先从java层找起，hook 这个  com.whatsapp.wamsys.JniBridge.jvidispatchIOOOOOOOOOO&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;let JniBridge = Java.use(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;com.whatsapp.wamsys.JniBridge&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);

JniBridge[&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;jvidispatchIOOOOOOOOOO&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;].&lt;span class=&#34;function&#34;&gt;implementation&lt;/span&gt; = &lt;span class=&#34;keyword&#34;&gt;function&lt;/span&gt; (i, obj, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10) {
    console.log(&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;======== JniBridge.jvidispatchIOOOOOOOOOO is called: i=&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{i}, obj=&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{obj}, obj2=&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{obj2}, obj3=&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{obj3}, obj4=&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{obj4}, obj5=&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{obj5}, obj6=&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{obj6}, obj7=&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{obj7}, obj8=&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{obj8}, obj9=&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{obj9}, obj10=&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{obj10}&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;);


    let bCls = Java.use(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;[B&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;)
    let buffer = Java.cast(obj6, bCls);
    let rc = Java.array(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;byte&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;, buffer);

    console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;obj6 = &lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; + buf2hex(rc));

    buffer = Java.cast(obj7, bCls);
    rc = Java.array(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;byte&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;, buffer);
    console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;obj7 = &lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; + buf2hex(rc));

    let result = &lt;span class=&#34;local-variable&#34;&gt;this&lt;/span&gt;[&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;jvidispatchIOOOOOOOOOO&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;](i, obj, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10);
    console.log(&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt; ======== JniBridge.jvidispatchIOOOOOOOOOO result=&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{result}&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;);
    &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; result;
};&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;跑这个 hook 的时候，可以先把之前的Base64的hook代码注释掉，这样看上去清晰一些。&lt;/p&gt;
&lt;p&gt;jvidispatchIOOOOOOOOOO 的入参是一大堆明文，返回值 是 0 。 貌似是成功的意思，&lt;/p&gt;
&lt;p&gt;摸不到头脑，这时候不得不怀疑 H 是在Native层去计算的，下一步的解决方案就是Native层的Trace，然后汇编层一行一行去找。不过悲催的是，这条路是错的，我就不给大家展开了，下次走对了，我再介绍这个玩法。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_frida模块化编程代码也要精致生活&#34;&gt;frida模块化编程,代码也要精致生活&lt;/h3&gt;&lt;p&gt;在进行下一步之前，我们先把代码整整，一个js越写越多，多的都有几千行了，太不帅了，咱们得搞个起码的模块化，把一些常用的函数封装到单独的js中，buf2hex 之类的&lt;/p&gt;
&lt;p&gt;首先新建一个目录 utils ,在目录下面新建一个byteTolib.js，然后把buf2hex拷贝进去，函数名之前加一个export&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;&lt;span class=&#34;comment&#34;&gt;// 将意大利面条代码改造成米其林餐厅&lt;/span&gt;
&lt;span class=&#34;comment&#34;&gt;// ./utils/byteTolib.js&lt;/span&gt;
&lt;span class=&#34;reserved&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;function&#34;&gt;buf2hex&lt;/span&gt;(buffer) {
....
}

&lt;span class=&#34;comment&#34;&gt;// ws2demo.js&lt;/span&gt;
&lt;span class=&#34;reserved&#34;&gt;import&lt;/span&gt; {
    buf2hex,
} from &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;./utils/byteTolib.js&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;然后在ws2demo.js加一个import就可以调用buf2hex函数了。&lt;/p&gt;
&lt;p&gt;实际跑的时候不再是直接跑ws2demo.js&lt;/p&gt;
&lt;p&gt;而是先启动一个控制台&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;frida-compile -w ws2demo.js -o ws2demo-agent.js&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;把ws2demo.js编译成ws2demo-agent.js，&lt;mark&gt;这个控制台就不要关了&lt;/mark&gt; ，他会监控原始文件的修改，实时生成编译后的文件。&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;frida -Uf com.whatsapp --runtime=v8 -l ws2demo-agent.js&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;在另外一个控制台中实际执行ws2demo-agent.js，这下代码就清晰多了&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_jni_trace&#34;&gt;JNI Trace&lt;/h3&gt;&lt;p&gt;飞哥已经花了几天功夫走了一下弯路，证明了H的计算不在Native里面，但是我们从java的堆栈X.6zL这些类里面又没有发现蛛丝马迹。&lt;/p&gt;
&lt;p&gt;真相只有一个，那就是Native中通过JNI调用java来计算。要分析这种类型的调用，我们只需要参照以前的文章 &lt;a href=&#34;http://91fans.com.cn/post/traceinfo&#34;&gt;Trace大盘点&lt;/a&gt; ,用上飞哥独家定制的jniTreace工具。&lt;/p&gt;
&lt;p&gt;在hook jvidispatchIOOOOOOOOOO的时候增加一个 hook_all_jni()&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;ffJNITrace: ======== &lt;span class=&#34;comment&#34;&gt;/* TID 18362 */&lt;/span&gt; JNIENv-&amp;gt;CallObjectMethod java/lang/Class-&amp;gt;&lt;span class=&#34;hex&#34;&gt;0x6f6eb168&lt;/span&gt; &lt;span class=&#34;hex&#34;&gt;0x81&lt;/span&gt;
...
ffJNITrace: ======== &lt;span class=&#34;comment&#34;&gt;/* TID 18362 */&lt;/span&gt; JNIENv-&amp;gt;CallStaticObjectMethodV java/lang/Class-&amp;gt;&lt;span class=&#34;hex&#34;&gt;0x7082dd30&lt;/span&gt; rc = &lt;span class=&#34;hex&#34;&gt;0x75&lt;/span&gt;
...

ffJNITrace:&lt;span class=&#34;comment&#34;&gt;/* TID 18362 */&lt;/span&gt;  JNIENv-&amp;gt;GetByteArrayElements was called args[&lt;span class=&#34;integer&#34;&gt;1&lt;/span&gt;] = &lt;span class=&#34;hex&#34;&gt;0x29&lt;/span&gt;, args[&lt;span class=&#34;integer&#34;&gt;2&lt;/span&gt;] = &lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt;
ffJNITrace: ======== byteLen = &lt;span class=&#34;integer&#34;&gt;71&lt;/span&gt;
ffJNITrace: ======== &lt;span class=&#34;integer&#34;&gt;3045022100830&lt;/span&gt;c97dd97a5526a29d6b8639b26b341a50b629d40462ed0b992b8521e47972502200e09492a06883ddb4d4350bb65ef9f1796d309e5c87245cba4842d994d14302b&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;又接近了一点，本以为可以从 CallObjectMethod 或者 CallStaticObjectMethodV 找到线索，也许是我的hook代码有问题，这里还是没有精准定位的东西。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_traceclass&#34;&gt;traceClass&lt;/h3&gt;&lt;p&gt;从之前的分析来看 com.whatsapp.wamsys.JniBridge 类可能是个很重要的类，我们把它也trace上&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;traceClass(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;com.whatsapp.wamsys.JniBridge&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;再跑一下，&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;....
*** exiting com.whatsapp.wamsys.JniBridge.jnidispatchOO
ffJNITrace: ======== &lt;span class=&#34;comment&#34;&gt;/* TID 18938 */&lt;/span&gt; JNIENv-&amp;gt;CallStaticObjectMethodV java/lang/Class-&amp;gt;&lt;span class=&#34;hex&#34;&gt;0x9e37e2e0&lt;/span&gt; rc = &lt;span class=&#34;hex&#34;&gt;0x29&lt;/span&gt;
ffJNITrace:&lt;span class=&#34;comment&#34;&gt;/* TID 18938 */&lt;/span&gt;  JNIENv-&amp;gt;GetByteArrayElements was called args[&lt;span class=&#34;integer&#34;&gt;1&lt;/span&gt;] = &lt;span class=&#34;hex&#34;&gt;0x29&lt;/span&gt;, args[&lt;span class=&#34;integer&#34;&gt;2&lt;/span&gt;] = &lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt;
ffJNITrace: ======== byteLen = &lt;span class=&#34;integer&#34;&gt;70&lt;/span&gt;
ffJNITrace: ======== &lt;span class=&#34;integer&#34;&gt;304402205492&lt;/span&gt;ecfb34b84941e1179d1e7aab840f6430e55a279f7f6958f20d29a2efefbd022006a9dce0cebc6d02b6e3359384bfb82a30c0e77c9fdd8aed89e2963e3029da29&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;兄弟们，这下跑不掉了，就是 &lt;mark&gt;jnidispatchOO&lt;/mark&gt;&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_三总结&#34;&gt;三、总结&lt;/h2&gt;&lt;p&gt;当Java层过于干净时，记得检查它有没有Native层的&amp;#34;外国亲戚&amp;#34;，每个完美的隐身，都可能在JNI调用中露出马脚。&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Whatsapptwo/ffshow.png&#34; alt=&#34;ffshow&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ffshow&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;mark&gt;你要是一直被带着跑，就像跟着波浪起起伏伏；但如果你能看透一切波动，直接做那片安静的水，那你就赢了！&lt;/mark&gt;&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;: 本文的目的只有一个就是学习更多的逆向技巧和思路，如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担，和本文以及作者没关系，本文涉及到的代码项目可以去 &lt;mark&gt;奋飞的朋友们&lt;/mark&gt; 知识星球自取，欢迎加入知识星球一起学习探讨技术。有问题可以加我wx: &lt;mark&gt;fenfei331&lt;/mark&gt; 讨论下。&lt;/p&gt;&lt;/aside&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ffzsxq.jpg&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;
&lt;p&gt;关注微信公众号，最新技术干货实时推送&lt;/p&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ff330.png&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;&lt;/section&gt;&lt;/div&gt;&lt;footer&gt;&lt;div id=&#34;footer-text&#34;&gt;&lt;br/&gt;Last updated 2026-04-27 18:48:46 +0800&lt;/div&gt;&lt;/footer&gt;
</description>
      
    </item>
    
    <item>
      <title>结合AI对WhatsApp的分析 (一) </title>
      <link>http://91fans.com.cn/post/whatsappone/</link>
      <pubDate>Thu, 13 Mar 2025 15:46:38 +0800</pubDate>
      
      <guid>http://91fans.com.cn/post/whatsappone/</guid>
      
        <description>&lt;meta charset=&#34;UTF-8&#34;/&gt;&lt;meta http-equiv=&#34;X-UA-Compatible&#34; content=&#34;IE=edge&#34;/&gt;&lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;/&gt;&lt;meta name=&#34;generator&#34; content=&#34;Asciidoctor 2.0.20&#34;/&gt;&lt;title&gt;一、目标&lt;/title&gt;&lt;style&gt;/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import &#34;https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700&#34;; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:&#34;\201C&#34; &#34;\201D&#34; &#34;\2018&#34; &#34;\2019&#34;}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock&gt;.content&gt;.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock&gt;.content&gt;.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:&#34; &#34;;display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])&gt;code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre&gt;code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:&#34;[&#34;;padding:0 3px 0 2px}
b.button::after{content:&#34;]&#34;;padding:0 2px 0 3px}
p a&gt;code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:&#34; &#34;;display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header&gt;h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header&gt;h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header&gt;h1:only-child,body.toc2 #header&gt;h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:&#34;\00a0\2013\00a0&#34;}
#header .details br+span.author::before{content:&#34;\00a0\22c5\00a0&#34;;color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:&#34;\00a0|\00a0&#34;}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:&#34;\00a0&#34;}
#content&gt;h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc&gt;ul{margin-left:.125em}
#toc ul.sectlevel0&gt;li&gt;a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2&gt;ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2&gt;ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc&gt;:first-child{margin-top:0}
#content #toc&gt;:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1&gt;a.anchor,h2&gt;a.anchor,h3&gt;a.anchor,#toctitle&gt;a.anchor,.sidebarblock&gt;.content&gt;.title&gt;a.anchor,h4&gt;a.anchor,h5&gt;a.anchor,h6&gt;a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1&gt;a.anchor::before,h2&gt;a.anchor::before,h3&gt;a.anchor::before,#toctitle&gt;a.anchor::before,.sidebarblock&gt;.content&gt;.title&gt;a.anchor::before,h4&gt;a.anchor::before,h5&gt;a.anchor::before,h6&gt;a.anchor::before{content:&#34;\00A7&#34;;font-size:.85em;display:block;padding-top:.1em}
#content h1:hover&gt;a.anchor,#content h1&gt;a.anchor:hover,h2:hover&gt;a.anchor,h2&gt;a.anchor:hover,h3:hover&gt;a.anchor,#toctitle:hover&gt;a.anchor,.sidebarblock&gt;.content&gt;.title:hover&gt;a.anchor,h3&gt;a.anchor:hover,#toctitle&gt;a.anchor:hover,.sidebarblock&gt;.content&gt;.title&gt;a.anchor:hover,h4:hover&gt;a.anchor,h4&gt;a.anchor:hover,h5:hover&gt;a.anchor,h5&gt;a.anchor:hover,h6:hover&gt;a.anchor,h6&gt;a.anchor:hover{visibility:visible}
#content h1&gt;a.link,h2&gt;a.link,h3&gt;a.link,#toctitle&gt;a.link,.sidebarblock&gt;.content&gt;.title&gt;a.link,h4&gt;a.link,h5&gt;a.link,h6&gt;a.link{color:#ba3925;text-decoration:none}
#content h1&gt;a.link:hover,h2&gt;a.link:hover,h3&gt;a.link:hover,#toctitle&gt;a.link:hover,.sidebarblock&gt;.content&gt;.title&gt;a.link:hover,h4&gt;a.link:hover,h5&gt;a.link:hover,h6&gt;a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details&gt;summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details&gt;summary::-webkit-details-marker{display:none}
details&gt;summary::before{content:&#34;&#34;;border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]&gt;summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details&gt;summary::after{content:&#34;&#34;;width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{text-rendering:optimizeLegibility;text-align:left;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content&gt;caption.title{white-space:nowrap;width:0}
.paragraph.lead&gt;p,#preamble&gt;.sectionbody&gt;[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock&gt;table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock&gt;table td.icon{text-align:center;width:80px}
.admonitionblock&gt;table td.icon img{max-width:none}
.admonitionblock&gt;table td.icon .title{font-weight:bold;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;text-transform:uppercase}
.admonitionblock&gt;table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock&gt;table td.content&gt;:last-child&gt;:last-child{margin-bottom:0}
.exampleblock&gt;.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock&gt;.content&gt;.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock&gt;.content&gt;:first-child,.sidebarblock&gt;.content&gt;:first-child{margin-top:0}
.exampleblock&gt;.content&gt;:last-child,.exampleblock&gt;.content&gt;:last-child&gt;:last-child,.exampleblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child&gt;:last-child,.sidebarblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child{margin-bottom:0}
.literalblock pre,.listingblock&gt;.content&gt;pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:1em}}
.literalblock pre,.listingblock&gt;.content&gt;pre:not(.highlight),.listingblock&gt;.content&gt;pre[class=highlight],.listingblock&gt;.content&gt;pre[class^=&#34;highlight &#34;]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock&gt;.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:&#34;$&#34;}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs&gt;code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)&gt;.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:&#34;\201c&#34;;float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote&gt;.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract&gt;.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt&gt;blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock&gt;.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock&gt;.content&gt;:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all&gt;*&gt;tr&gt;*{border-width:1px}
table.grid-cols&gt;*&gt;tr&gt;*{border-width:0 1px}
table.grid-rows&gt;*&gt;tr&gt;*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none&gt;colgroup+*&gt;:first-child&gt;*,table.frame-sides&gt;colgroup+*&gt;:first-child&gt;*{border-top-width:0}
table.frame-none&gt;:last-child&gt;:last-child&gt;*,table.frame-sides&gt;:last-child&gt;:last-child&gt;*{border-bottom-width:0}
table.frame-none&gt;*&gt;tr&gt;:first-child,table.frame-ends&gt;*&gt;tr&gt;:first-child{border-left-width:0}
table.frame-none&gt;*&gt;tr&gt;:last-child,table.frame-ends&gt;*&gt;tr&gt;:last-child{border-right-width:0}
table.stripes-all&gt;*&gt;tr,table.stripes-odd&gt;*&gt;tr:nth-of-type(odd),table.stripes-even&gt;*&gt;tr:nth-of-type(even),table.stripes-hover&gt;*&gt;tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock&gt;code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child&gt;:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li&gt;p:empty:only-child::before{content:&#34;&#34;;display:inline-block}
ul.checklist&gt;li&gt;p:first-child{margin-left:-1em}
ul.checklist&gt;li&gt;p:first-child&gt;.fa-square-o:first-child,ul.checklist&gt;li&gt;p:first-child&gt;.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist&gt;li&gt;p:first-child&gt;input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline&gt;li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist&gt;table,.colist&gt;table{border:0;background:none}
.hdlist&gt;table&gt;tbody&gt;tr,.colist&gt;table&gt;tbody&gt;tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock&gt;.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb&gt;.title,.imageblock.th&gt;.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon&gt;.fa{cursor:default}
a span.icon&gt;.fa{cursor:inherit}
.admonitionblock td.icon [class^=&#34;fa icon-&#34;]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:&#34;\f05a&#34;;color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:&#34;\f0eb&#34;;text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:&#34;\f071&#34;;color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:&#34;\f06d&#34;;color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:&#34;\f06a&#34;;color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock&gt;.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^=&#34;#&#34;],a[href^=&#34;mailto:&#34;]{text-decoration:none!important}
a[href^=&#34;http:&#34;]:not(.bare)::after,a[href^=&#34;https:&#34;]:not(.bare)::after{content:&#34;(&#34; attr(href) &#34;)&#34;;display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:&#34; (&#34; attr(title) &#34;)&#34;}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock&gt;.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header&gt;h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1&gt;h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header&gt;h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}&lt;/style&gt;
&lt;style&gt;
/*! Stylesheet for CodeRay to loosely match GitHub themes | MIT License */
pre.CodeRay{background:#f7f7f8}
.CodeRay .line-numbers{border-right:1px solid;opacity:.35;padding:0 .5em 0 0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.CodeRay span.line-numbers{display:inline-block;margin-right:.75em}
.CodeRay .line-numbers strong{color:#000}
table.CodeRay{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.CodeRay td{vertical-align:top;line-height:inherit}
table.CodeRay td.line-numbers{text-align:right}
table.CodeRay td.code{padding:0 0 0 .75em}
.CodeRay .debug{color:#fff!important;background:navy!important}
.CodeRay .annotation{color:#007}
.CodeRay .attribute-name{color:navy}
.CodeRay .attribute-value{color:#700}
.CodeRay .binary{color:#509}
.CodeRay .comment{color:#998;font-style:italic}
.CodeRay .char{color:#04d}
.CodeRay .char .content{color:#04d}
.CodeRay .char .delimiter{color:#039}
.CodeRay .class{color:#458;font-weight:bold}
.CodeRay .complex{color:#a08}
.CodeRay .constant,.CodeRay .predefined-constant{color:teal}
.CodeRay .color{color:#099}
.CodeRay .class-variable{color:#369}
.CodeRay .decorator{color:#b0b}
.CodeRay .definition{color:#099}
.CodeRay .delimiter{color:#000}
.CodeRay .doc{color:#970}
.CodeRay .doctype{color:#34b}
.CodeRay .doc-string{color:#d42}
.CodeRay .escape{color:#666}
.CodeRay .entity{color:#800}
.CodeRay .error{color:#808}
.CodeRay .exception{color:inherit}
.CodeRay .filename{color:#099}
.CodeRay .function{color:#900;font-weight:bold}
.CodeRay .global-variable{color:teal}
.CodeRay .hex{color:#058}
.CodeRay .integer,.CodeRay .float{color:#099}
.CodeRay .include{color:#555}
.CodeRay .inline{color:#000}
.CodeRay .inline .inline{background:#ccc}
.CodeRay .inline .inline .inline{background:#bbb}
.CodeRay .inline .inline-delimiter{color:#d14}
.CodeRay .inline-delimiter{color:#d14}
.CodeRay .important{color:#555;font-weight:bold}
.CodeRay .interpreted{color:#b2b}
.CodeRay .instance-variable{color:teal}
.CodeRay .label{color:#970}
.CodeRay .local-variable{color:#963}
.CodeRay .octal{color:#40e}
.CodeRay .predefined{color:#369}
.CodeRay .preprocessor{color:#579}
.CodeRay .pseudo-class{color:#555}
.CodeRay .directive{font-weight:bold}
.CodeRay .type{font-weight:bold}
.CodeRay .predefined-type{color:inherit}
.CodeRay .reserved,.CodeRay .keyword{color:#000;font-weight:bold}
.CodeRay .key{color:#808}
.CodeRay .key .delimiter{color:#606}
.CodeRay .key .char{color:#80f}
.CodeRay .value{color:#088}
.CodeRay .regexp .delimiter{color:#808}
.CodeRay .regexp .content{color:#808}
.CodeRay .regexp .modifier{color:#808}
.CodeRay .regexp .char{color:#d14}
.CodeRay .regexp .function{color:#404;font-weight:bold}
.CodeRay .string{color:#d20}
.CodeRay .string .string .string{background:#ffd0d0}
.CodeRay .string .content{color:#d14}
.CodeRay .string .char{color:#d14}
.CodeRay .string .delimiter{color:#d14}
.CodeRay .shell{color:#d14}
.CodeRay .shell .delimiter{color:#d14}
.CodeRay .symbol{color:#990073}
.CodeRay .symbol .content{color:#a60}
.CodeRay .symbol .delimiter{color:#630}
.CodeRay .tag{color:teal}
.CodeRay .tag-special{color:#d70}
.CodeRay .variable{color:#036}
.CodeRay .insert{background:#afa}
.CodeRay .delete{background:#faa}
.CodeRay .change{color:#aaf;background:#007}
.CodeRay .head{color:#f8f;background:#505}
.CodeRay .insert .insert{color:#080}
.CodeRay .delete .delete{color:#800}
.CodeRay .change .change{color:#66f}
.CodeRay .head .head{color:#f4f}
&lt;/style&gt;&lt;/head&gt;&lt;body class=&#34;article&#34;&gt;&lt;header&gt;&lt;/header&gt;&lt;div id=&#34;content&#34;&gt;&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_一目标&#34;&gt;一、目标&lt;/h2&gt;&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Whatsappone/main.png&#34; alt=&#34;main&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:main&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;好希望未来的世界是这样的:&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;小X同学，请帮我写一个ws的H算法，并且详细解释入参和结果。&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;可惜现实是这样的&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Whatsappone/ws1.png&#34; alt=&#34;ws1&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ws1&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;也好，起码飞哥还不至于失业，李老板还得老老实实给我发工资。然后含泪退掉了他偷偷买的4090，原计划他准备搭个DeepSeek来优化我的。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_二步骤&#34;&gt;二、步骤&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_遇事不决先问ai&#34;&gt;遇事不决先问AI&lt;/h3&gt;&lt;p&gt;工具是死的，人是活到。个人认为目前的AI，抹平了初级程序员和中级的程序员之间的技术差距。但是抹平不了李老板和入门级的程序员之间的技术差距。&lt;/p&gt;
&lt;p&gt;作为一个有证的程序员，应该这样问AI才靠谱&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Whatsappone/ws2.png&#34; alt=&#34;ws2&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ws2&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;这里面的关键信息就是 &lt;mark&gt;AES SHA256&lt;/mark&gt; 和  &lt;mark&gt;libwhatsapp.so&lt;/mark&gt; 了，&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_找朋友_libwhatsapp_so&#34;&gt;找朋友 libwhatsapp.so&lt;/h3&gt;&lt;p&gt;我们遇到的第一个困难就是， 最新版的apk里面只有libsuperpack.so 和 libunwindstack.so， 并没有我们期待的 &lt;mark&gt;libwhatsapp.so&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;不过这也难不倒我们，继续问AI呗。这次 AI给出了几个方案，它怀疑 WhatsApp 可能已经将多个 .so 库合并进一个单独的 libsuperpack.so 文件，减少 APK 体积并提高加载效率。&lt;/p&gt;
&lt;p&gt;所以我们先安装Apk，然后用上最原始的查找大法&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;find / -name &amp;#39;libwhatsapp.so&amp;#39; -type f

# 结果出来了
/data/user/0/com.whatsapp/files/decompressed/libs.spo/libwhatsapp.so&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_ida&#34;&gt;IDA&lt;/h3&gt;&lt;p&gt;这个 H 一看就是个Base64， 所以第一反应就是 hook java的 base64函数，但是没有结果，那就说明大概率是在 so里面做的base64。&lt;/p&gt;
&lt;p&gt;这时候就请IDA上场了。&lt;/p&gt;
&lt;p&gt;我感觉下一个版本的ida可能就会增加AI窗口了， 咱们直接输入一个:&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;请帮我标出这个so中做Base64操作的函数，并且生成frida Hook的代码&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;好吧，在ida没有更新之前，只能飞哥上场了。&lt;/p&gt;
&lt;p&gt;挂上心爱的 FindCrypt插件&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Whatsappone/ida1.png&#34; alt=&#34;ida1&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ida1&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;啥也不说了，先Hook它&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;    let libWhatsAppAddress = Module.findBaseAddress(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;libwhatsapp.so&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;);
    console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt; ==&amp;gt; libwhatsapp : &lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; + libWhatsAppAddress)

    let offset = &lt;span class=&#34;hex&#34;&gt;0x89F7C8&lt;/span&gt;;
    let funcAddr = libWhatsAppAddress.add(offset);
    Interceptor.attach(funcAddr, {
        &lt;span class=&#34;function&#34;&gt;onEnter&lt;/span&gt;: &lt;span class=&#34;keyword&#34;&gt;function&lt;/span&gt;(args) {
        },
        &lt;span class=&#34;function&#34;&gt;onLeave&lt;/span&gt;: &lt;span class=&#34;keyword&#34;&gt;function&lt;/span&gt;(retval) {

            console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;--&amp;gt; retval: &lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt; + retval);
            &lt;span class=&#34;keyword&#34;&gt;try&lt;/span&gt; {
                let strIn = Memory.readUtf8String(retval);
                console.log(strIn);
            } &lt;span class=&#34;keyword&#34;&gt;catch&lt;/span&gt; (e) {
                Log( &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;#### Base64 A Rc Error&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
            }

            console.log(&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;comment&#34;&gt;/* TID ${gettid()} */&lt;/span&gt; =======  Base64 A retval ====&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;);
        }
    });&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;跑一下 ，熟悉的味道&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Whatsappone/rc1.png&#34; alt=&#34;rc1&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:rc1&lt;/figcaption&gt;&lt;/figure&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_三总结&#34;&gt;三、总结&lt;/h2&gt;&lt;p&gt;再强调一遍，以后的程序员只会有一种，利用辅助AI工具的程序员。不会使用AI的程序员一定是要被淘汰的。&lt;/p&gt;
&lt;p&gt;早用早享受，不用担心AI会替代你，AI的出现只会让你的工作更加高效。以此为理由找李老板提加工资。&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Whatsappone/ffshow.jpeg&#34; alt=&#34;ffshow&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ffshow&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;mark&gt;这台机器不会取代我们任何一个人&lt;/mark&gt;&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;本文的目的只有一个就是学习更多的逆向技巧和思路，如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担，和本文以及作者没关系，本文涉及到的代码项目可以去 &lt;mark&gt;奋飞的朋友们&lt;/mark&gt; 知识星球自取，欢迎加入知识星球一起学习探讨技术。有问题可以加我wx: &lt;mark&gt;fenfei331&lt;/mark&gt; 讨论下。&lt;/p&gt;&lt;/aside&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ffzsxq.jpg&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;
&lt;p&gt;关注微信公众号，最新技术干货实时推送&lt;/p&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ff330.png&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;&lt;/section&gt;&lt;/div&gt;&lt;footer&gt;&lt;div id=&#34;footer-text&#34;&gt;&lt;br/&gt;Last updated 2026-04-27 18:48:46 +0800&lt;/div&gt;&lt;/footer&gt;
</description>
      
    </item>
    
    <item>
      <title>DeepSeek分析DeepSeek App</title>
      <link>http://91fans.com.cn/post/deepseekone/</link>
      <pubDate>Mon, 17 Feb 2025 11:28:22 +0800</pubDate>
      
      <guid>http://91fans.com.cn/post/deepseekone/</guid>
      
        <description>&lt;meta charset=&#34;UTF-8&#34;/&gt;&lt;meta http-equiv=&#34;X-UA-Compatible&#34; content=&#34;IE=edge&#34;/&gt;&lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;/&gt;&lt;meta name=&#34;generator&#34; content=&#34;Asciidoctor 2.0.20&#34;/&gt;&lt;title&gt;一、目标&lt;/title&gt;&lt;style&gt;/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import &#34;https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700&#34;; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:&#34;\201C&#34; &#34;\201D&#34; &#34;\2018&#34; &#34;\2019&#34;}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock&gt;.content&gt;.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock&gt;.content&gt;.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:&#34; &#34;;display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])&gt;code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre&gt;code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:&#34;[&#34;;padding:0 3px 0 2px}
b.button::after{content:&#34;]&#34;;padding:0 2px 0 3px}
p a&gt;code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:&#34; &#34;;display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header&gt;h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header&gt;h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header&gt;h1:only-child,body.toc2 #header&gt;h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:&#34;\00a0\2013\00a0&#34;}
#header .details br+span.author::before{content:&#34;\00a0\22c5\00a0&#34;;color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:&#34;\00a0|\00a0&#34;}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:&#34;\00a0&#34;}
#content&gt;h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc&gt;ul{margin-left:.125em}
#toc ul.sectlevel0&gt;li&gt;a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2&gt;ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2&gt;ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc&gt;:first-child{margin-top:0}
#content #toc&gt;:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1&gt;a.anchor,h2&gt;a.anchor,h3&gt;a.anchor,#toctitle&gt;a.anchor,.sidebarblock&gt;.content&gt;.title&gt;a.anchor,h4&gt;a.anchor,h5&gt;a.anchor,h6&gt;a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1&gt;a.anchor::before,h2&gt;a.anchor::before,h3&gt;a.anchor::before,#toctitle&gt;a.anchor::before,.sidebarblock&gt;.content&gt;.title&gt;a.anchor::before,h4&gt;a.anchor::before,h5&gt;a.anchor::before,h6&gt;a.anchor::before{content:&#34;\00A7&#34;;font-size:.85em;display:block;padding-top:.1em}
#content h1:hover&gt;a.anchor,#content h1&gt;a.anchor:hover,h2:hover&gt;a.anchor,h2&gt;a.anchor:hover,h3:hover&gt;a.anchor,#toctitle:hover&gt;a.anchor,.sidebarblock&gt;.content&gt;.title:hover&gt;a.anchor,h3&gt;a.anchor:hover,#toctitle&gt;a.anchor:hover,.sidebarblock&gt;.content&gt;.title&gt;a.anchor:hover,h4:hover&gt;a.anchor,h4&gt;a.anchor:hover,h5:hover&gt;a.anchor,h5&gt;a.anchor:hover,h6:hover&gt;a.anchor,h6&gt;a.anchor:hover{visibility:visible}
#content h1&gt;a.link,h2&gt;a.link,h3&gt;a.link,#toctitle&gt;a.link,.sidebarblock&gt;.content&gt;.title&gt;a.link,h4&gt;a.link,h5&gt;a.link,h6&gt;a.link{color:#ba3925;text-decoration:none}
#content h1&gt;a.link:hover,h2&gt;a.link:hover,h3&gt;a.link:hover,#toctitle&gt;a.link:hover,.sidebarblock&gt;.content&gt;.title&gt;a.link:hover,h4&gt;a.link:hover,h5&gt;a.link:hover,h6&gt;a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details&gt;summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details&gt;summary::-webkit-details-marker{display:none}
details&gt;summary::before{content:&#34;&#34;;border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]&gt;summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details&gt;summary::after{content:&#34;&#34;;width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{text-rendering:optimizeLegibility;text-align:left;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content&gt;caption.title{white-space:nowrap;width:0}
.paragraph.lead&gt;p,#preamble&gt;.sectionbody&gt;[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock&gt;table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock&gt;table td.icon{text-align:center;width:80px}
.admonitionblock&gt;table td.icon img{max-width:none}
.admonitionblock&gt;table td.icon .title{font-weight:bold;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;text-transform:uppercase}
.admonitionblock&gt;table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock&gt;table td.content&gt;:last-child&gt;:last-child{margin-bottom:0}
.exampleblock&gt;.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock&gt;.content&gt;.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock&gt;.content&gt;:first-child,.sidebarblock&gt;.content&gt;:first-child{margin-top:0}
.exampleblock&gt;.content&gt;:last-child,.exampleblock&gt;.content&gt;:last-child&gt;:last-child,.exampleblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child&gt;:last-child,.sidebarblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child{margin-bottom:0}
.literalblock pre,.listingblock&gt;.content&gt;pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:1em}}
.literalblock pre,.listingblock&gt;.content&gt;pre:not(.highlight),.listingblock&gt;.content&gt;pre[class=highlight],.listingblock&gt;.content&gt;pre[class^=&#34;highlight &#34;]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock&gt;.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:&#34;$&#34;}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs&gt;code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)&gt;.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:&#34;\201c&#34;;float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote&gt;.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract&gt;.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt&gt;blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock&gt;.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock&gt;.content&gt;:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all&gt;*&gt;tr&gt;*{border-width:1px}
table.grid-cols&gt;*&gt;tr&gt;*{border-width:0 1px}
table.grid-rows&gt;*&gt;tr&gt;*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none&gt;colgroup+*&gt;:first-child&gt;*,table.frame-sides&gt;colgroup+*&gt;:first-child&gt;*{border-top-width:0}
table.frame-none&gt;:last-child&gt;:last-child&gt;*,table.frame-sides&gt;:last-child&gt;:last-child&gt;*{border-bottom-width:0}
table.frame-none&gt;*&gt;tr&gt;:first-child,table.frame-ends&gt;*&gt;tr&gt;:first-child{border-left-width:0}
table.frame-none&gt;*&gt;tr&gt;:last-child,table.frame-ends&gt;*&gt;tr&gt;:last-child{border-right-width:0}
table.stripes-all&gt;*&gt;tr,table.stripes-odd&gt;*&gt;tr:nth-of-type(odd),table.stripes-even&gt;*&gt;tr:nth-of-type(even),table.stripes-hover&gt;*&gt;tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock&gt;code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child&gt;:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li&gt;p:empty:only-child::before{content:&#34;&#34;;display:inline-block}
ul.checklist&gt;li&gt;p:first-child{margin-left:-1em}
ul.checklist&gt;li&gt;p:first-child&gt;.fa-square-o:first-child,ul.checklist&gt;li&gt;p:first-child&gt;.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist&gt;li&gt;p:first-child&gt;input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline&gt;li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist&gt;table,.colist&gt;table{border:0;background:none}
.hdlist&gt;table&gt;tbody&gt;tr,.colist&gt;table&gt;tbody&gt;tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock&gt;.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb&gt;.title,.imageblock.th&gt;.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon&gt;.fa{cursor:default}
a span.icon&gt;.fa{cursor:inherit}
.admonitionblock td.icon [class^=&#34;fa icon-&#34;]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:&#34;\f05a&#34;;color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:&#34;\f0eb&#34;;text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:&#34;\f071&#34;;color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:&#34;\f06d&#34;;color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:&#34;\f06a&#34;;color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock&gt;.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^=&#34;#&#34;],a[href^=&#34;mailto:&#34;]{text-decoration:none!important}
a[href^=&#34;http:&#34;]:not(.bare)::after,a[href^=&#34;https:&#34;]:not(.bare)::after{content:&#34;(&#34; attr(href) &#34;)&#34;;display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:&#34; (&#34; attr(title) &#34;)&#34;}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock&gt;.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header&gt;h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1&gt;h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header&gt;h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}&lt;/style&gt;
&lt;style&gt;
/*! Stylesheet for CodeRay to loosely match GitHub themes | MIT License */
pre.CodeRay{background:#f7f7f8}
.CodeRay .line-numbers{border-right:1px solid;opacity:.35;padding:0 .5em 0 0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.CodeRay span.line-numbers{display:inline-block;margin-right:.75em}
.CodeRay .line-numbers strong{color:#000}
table.CodeRay{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.CodeRay td{vertical-align:top;line-height:inherit}
table.CodeRay td.line-numbers{text-align:right}
table.CodeRay td.code{padding:0 0 0 .75em}
.CodeRay .debug{color:#fff!important;background:navy!important}
.CodeRay .annotation{color:#007}
.CodeRay .attribute-name{color:navy}
.CodeRay .attribute-value{color:#700}
.CodeRay .binary{color:#509}
.CodeRay .comment{color:#998;font-style:italic}
.CodeRay .char{color:#04d}
.CodeRay .char .content{color:#04d}
.CodeRay .char .delimiter{color:#039}
.CodeRay .class{color:#458;font-weight:bold}
.CodeRay .complex{color:#a08}
.CodeRay .constant,.CodeRay .predefined-constant{color:teal}
.CodeRay .color{color:#099}
.CodeRay .class-variable{color:#369}
.CodeRay .decorator{color:#b0b}
.CodeRay .definition{color:#099}
.CodeRay .delimiter{color:#000}
.CodeRay .doc{color:#970}
.CodeRay .doctype{color:#34b}
.CodeRay .doc-string{color:#d42}
.CodeRay .escape{color:#666}
.CodeRay .entity{color:#800}
.CodeRay .error{color:#808}
.CodeRay .exception{color:inherit}
.CodeRay .filename{color:#099}
.CodeRay .function{color:#900;font-weight:bold}
.CodeRay .global-variable{color:teal}
.CodeRay .hex{color:#058}
.CodeRay .integer,.CodeRay .float{color:#099}
.CodeRay .include{color:#555}
.CodeRay .inline{color:#000}
.CodeRay .inline .inline{background:#ccc}
.CodeRay .inline .inline .inline{background:#bbb}
.CodeRay .inline .inline-delimiter{color:#d14}
.CodeRay .inline-delimiter{color:#d14}
.CodeRay .important{color:#555;font-weight:bold}
.CodeRay .interpreted{color:#b2b}
.CodeRay .instance-variable{color:teal}
.CodeRay .label{color:#970}
.CodeRay .local-variable{color:#963}
.CodeRay .octal{color:#40e}
.CodeRay .predefined{color:#369}
.CodeRay .preprocessor{color:#579}
.CodeRay .pseudo-class{color:#555}
.CodeRay .directive{font-weight:bold}
.CodeRay .type{font-weight:bold}
.CodeRay .predefined-type{color:inherit}
.CodeRay .reserved,.CodeRay .keyword{color:#000;font-weight:bold}
.CodeRay .key{color:#808}
.CodeRay .key .delimiter{color:#606}
.CodeRay .key .char{color:#80f}
.CodeRay .value{color:#088}
.CodeRay .regexp .delimiter{color:#808}
.CodeRay .regexp .content{color:#808}
.CodeRay .regexp .modifier{color:#808}
.CodeRay .regexp .char{color:#d14}
.CodeRay .regexp .function{color:#404;font-weight:bold}
.CodeRay .string{color:#d20}
.CodeRay .string .string .string{background:#ffd0d0}
.CodeRay .string .content{color:#d14}
.CodeRay .string .char{color:#d14}
.CodeRay .string .delimiter{color:#d14}
.CodeRay .shell{color:#d14}
.CodeRay .shell .delimiter{color:#d14}
.CodeRay .symbol{color:#990073}
.CodeRay .symbol .content{color:#a60}
.CodeRay .symbol .delimiter{color:#630}
.CodeRay .tag{color:teal}
.CodeRay .tag-special{color:#d70}
.CodeRay .variable{color:#036}
.CodeRay .insert{background:#afa}
.CodeRay .delete{background:#faa}
.CodeRay .change{color:#aaf;background:#007}
.CodeRay .head{color:#f8f;background:#505}
.CodeRay .insert .insert{color:#080}
.CodeRay .delete .delete{color:#800}
.CodeRay .change .change{color:#66f}
.CodeRay .head .head{color:#f4f}
&lt;/style&gt;&lt;/head&gt;&lt;body class=&#34;article&#34;&gt;&lt;header&gt;&lt;/header&gt;&lt;div id=&#34;content&#34;&gt;&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_一目标&#34;&gt;一、目标&lt;/h2&gt;&lt;p&gt;山中方一日，世上已千年。Chatgpt的喧嚣感觉还在昨天，DeepSeek已经迎面而来。今天我们就在DeepSeek的帮助下来分析DeepSeek App&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;POST https://chat.deepseek.com/api/v0/chat/completion HTTP/2
host: chat.deepseek.com
x-ds-pow-response: eyJhbGdvcml0aG0iOiJEZWVwU2Vla0hhc2hWMSIsImNoYWxsZW5nZSI6ImNlYmFiNGFhOGU1MDk1NTY2NmY1ODk4MTZjNjY4MTExNDRlMDU2YThmNDFjNDNhNDNiZDc4Y2VkYzRiNWY0YTEiLCJzYWx0IjoiODM2MGY4YzkyMDVjOTZjMzJiN2EiLCJzaWduYXR1cmUiOiIxMGI3ODQ5YjFlNjIwM2IyODhkYzQ5NzVhMWUyMzc1M2VkOWQ2ZmI2NTY5NjRiOGU4NmRhZWJhYjM2MjhhNDBjIiwiYW5zd2VyIjo3NzkwNiwidGFyZ2V0X3BhdGgiOiIvYXBpL3YwL2NoYXQvY29tcGxldGlvbiJ9
x-client-platform: android&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;我们今天的目标是 &lt;mark&gt;x-ds-pow-response&lt;/mark&gt;&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_二步骤&#34;&gt;二、步骤&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_jwt&#34;&gt;Jwt?&lt;/h3&gt;&lt;p&gt;eyjh开头，很像是jwt，所以第一反应就是去jwt在线解密一下。结果很遗憾，不是jwt&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_deepseek登场&#34;&gt;DeepSeek登场&lt;/h3&gt;&lt;p&gt;把x-ds-pow-response的内容复制进DeepSeek的对话框，大大方方的问他， x-ds-pow-response可能是什么加密算法？&lt;/p&gt;
&lt;p&gt;不出意外的话，意外出现了&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;服务器繁忙，请稍后再试。&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;应对方法是 使用App :)&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;`x-ds-pow-response` 看起来像是一个包含某种加密或哈希算法响应的HTTP头部字段。根据你提供的内容，它包含了一个JSON对象，其中包含以下字段：

- `algorithm`: 指定了使用的算法，这里是 `DeepSeekHashV1`。
- `challenge`: 一个挑战字符串，可能是用于验证或防伪的随机值。
- `salt`: 盐值，用于增加哈希的复杂性。
- `signature`: 签名，可能是对某些数据进行哈希或加密后的结果。
- `answer`: 一个数值，可能是对挑战的某种计算结果。
- `target_path`: 目标路径，指示这个响应应该被应用到哪个API路径。

从这些信息来看，`DeepSeekHashV1` 可能是深度求索公司自定义的一种哈希算法，用于生成某种形式的数字签名或验证码。这种算法可能结合了挑战、盐值和目标路径来生成一个唯一的签名，以确保请求的完整性和来源的真实性。

由于这是自定义算法，具体的加密或哈希细节没有公开的标准可以参考。如果你需要更深入的了解，可能需要查阅深度求索公司的官方文档或联系他们的技术支持。&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;联系官方技术支持有点扯了，不过他为什么知道里面包含了Json对象，并且还知道这些明文？&lt;/p&gt;
&lt;p&gt;继续问问，反正也不花钱？&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;问: 你怎么知道x-ds-pow-response的内容里面包含DeepSeekHashV1 ？

答: 我理解你的疑问。实际上，我并没有直接访问或解析你提供的 `x-ds-pow-response` 内容的能力。我的回答是基于你提供的文本内容进行的推测和分析。

在你提供的 `x-ds-pow-response` 中，有一个 JSON 对象，其中包含了一个字段 `&amp;#34;algorithm&amp;#34;: &amp;#34;DeepSeekHashV1&amp;#34;`。这个字段明确指出了使用的算法是 `DeepSeekHashV1`。因此，我根据这个信息推断出 `x-ds-pow-response` 可能使用了 `DeepSeekHashV1` 这个算法。

如果你有更多关于这个字段的具体信息或上下文，我可以进一步帮助你分析和理解。&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这个回答我不满意，看来我问的不对。&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;python&#34;&gt;问: 如何从eyJhbGdvcml0aG0iOiJEZWVwU2Vla0hhc2hWMSIsImNoYWxsZW5nZSI6ImNlYmFiNGFhOGU1MDk1NTY2NmY1ODk4MTZjNjY4MTExNDRlMDU2YThmNDFjNDNhNDNiZDc4Y2VkYzRiNWY0YTEiLCJzYWx0IjoiODM2MGY4YzkyMDVjOTZjMzJiN2EiLCJzaWduYXR1cmUiOiIxMGI3ODQ5YjFlNjIwM2IyODhkYzQ5NzVhMWUyMzc1M2VkOWQ2ZmI2NTY5NjRiOGU4NmRhZWJhYjM2MjhhNDBjIiwiYW5zd2VyIjo3NzkwNiwidGFyZ2V0X3BhdGgiOiIvYXBpL3YwL2NoYXQvY29tcGxldGlvbiJ9
提取出 DeepSeekHashV1 字符串&lt;span class=&#34;error&#34;&gt;，&lt;/span&gt;请用python代码实现&lt;span class=&#34;error&#34;&gt;？&lt;/span&gt;

答: 要从 `eyJhbGdvcml0aG0iOiJEZWVwU2Vla0hhc2hWMSIsImNoYWxsZW5nZSI6ImNlYmFiNGFhOGU1MDk1NTY2NmY1ODk4MTZjNjY4MTExNDRlMDU2YThmNDFjNDNhNDNiZDc4Y2VkYzRiNWY0YTEiLCJzYWx0IjoiODM2MGY4YzkyMDVjOTZjMzJiN2EiLCJzaWduYXR1cmUiOiIxMGI3ODQ5YjFlNjIwM2IyODhkYzQ5NzVhMWUyMzc1M2VkOWQ2ZmI2NTY5NjRiOGU4NmRhZWJhYjM2MjhhNDBjIiwiYW5zd2VyIjo3NzkwNiwidGFyZ2V0X3BhdGgiOiIvYXBpL3YwL2NoYXQvY29tcGxldGlvbiJ9` 中提取出 `DeepSeekHashV1` 字符串&lt;span class=&#34;error&#34;&gt;，&lt;/span&gt;可以按照以下步骤实现&lt;span class=&#34;error&#34;&gt;：&lt;/span&gt;

&lt;span class=&#34;float&#34;&gt;1.&lt;/span&gt; 这是一个 Base64 编码的字符串&lt;span class=&#34;error&#34;&gt;，&lt;/span&gt;首先需要将其解码为 JSON 格式&lt;span class=&#34;error&#34;&gt;。&lt;/span&gt;
&lt;span class=&#34;float&#34;&gt;2.&lt;/span&gt; 解码后&lt;span class=&#34;error&#34;&gt;，&lt;/span&gt;解析 JSON 对象&lt;span class=&#34;error&#34;&gt;，&lt;/span&gt;提取 `algorithm` 字段的值&lt;span class=&#34;error&#34;&gt;。&lt;/span&gt;

以下是 Python 代码实现&lt;span class=&#34;error&#34;&gt;：&lt;/span&gt;

```python
&lt;span class=&#34;keyword&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;include&#34;&gt;base64&lt;/span&gt;
&lt;span class=&#34;keyword&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;include&#34;&gt;json&lt;/span&gt;

&lt;span class=&#34;comment&#34;&gt;# Base64 编码的字符串&lt;/span&gt;
encoded_str = &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;eyJhbGdvcml0aG0iOiJEZWVwU2Vla0hhc2hWMSIsImNoYWxsZW5nZSI6ImNlYmFiNGFhOGU1MDk1NTY2NmY1ODk4MTZjNjY4MTExNDRlMDU2YThmNDFjNDNhNDNiZDc4Y2VkYzRiNWY0YTEiLCJzYWx0IjoiODM2MGY4YzkyMDVjOTZjMzJiN2EiLCJzaWduYXR1cmUiOiIxMGI3ODQ5YjFlNjIwM2IyODhkYzQ5NzVhMWUyMzc1M2VkOWQ2ZmI2NTY5NjRiOGU4NmRhZWJhYjM2MjhhNDBjIiwiYW5zd2VyIjo3NzkwNiwidGFyZ2V0X3BhdGgiOiIvYXBpL3YwL2NoYXQvY29tcGxldGlvbiJ9&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&#34;comment&#34;&gt;# 解码 Base64 字符串&lt;/span&gt;
decoded_bytes = base64.b64decode(encoded_str)
decoded_str = decoded_bytes.decode(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;utf-8&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;)

&lt;span class=&#34;comment&#34;&gt;# 解析 JSON 对象&lt;/span&gt;
data = json.loads(decoded_str)

&lt;span class=&#34;comment&#34;&gt;# 提取 algorithm 字段的值&lt;/span&gt;
algorithm = data.get(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;algorithm&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;)

print(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;提取的 algorithm 值:&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, algorithm)
```

&lt;span class=&#34;comment&#34;&gt;### 代码说明：&lt;/span&gt;
&lt;span class=&#34;float&#34;&gt;1.&lt;/span&gt; **Base64 解码**&lt;span class=&#34;error&#34;&gt;：&lt;/span&gt;使用 `base64.b64decode` 将 Base64 编码的字符串解码为字节数据&lt;span class=&#34;error&#34;&gt;，&lt;/span&gt;然后转换为字符串&lt;span class=&#34;error&#34;&gt;。&lt;/span&gt;
&lt;span class=&#34;float&#34;&gt;2.&lt;/span&gt; **JSON 解析**&lt;span class=&#34;error&#34;&gt;：&lt;/span&gt;使用 `json.loads` 将解码后的字符串解析为 Python 字典&lt;span class=&#34;error&#34;&gt;。&lt;/span&gt;
&lt;span class=&#34;float&#34;&gt;3.&lt;/span&gt; **提取字段**&lt;span class=&#34;error&#34;&gt;：&lt;/span&gt;从字典中提取 `algorithm` 字段的值&lt;span class=&#34;error&#34;&gt;。&lt;/span&gt;

&lt;span class=&#34;comment&#34;&gt;### 输出结果：&lt;/span&gt;
```plaintext
提取的 algorithm 值: DeepSeekHashV1
```

&lt;span class=&#34;comment&#34;&gt;### 注意事项：&lt;/span&gt;
- 如果输入的 Base64 字符串无效&lt;span class=&#34;error&#34;&gt;，&lt;/span&gt;`base64.b64decode` 会抛出异常&lt;span class=&#34;error&#34;&gt;。&lt;/span&gt;
- 如果 JSON 格式不正确&lt;span class=&#34;error&#34;&gt;，&lt;/span&gt;`json.loads` 也会抛出异常&lt;span class=&#34;error&#34;&gt;。&lt;/span&gt;
- 确保输入的字符串是完整的 Base64 编码数据&lt;span class=&#34;error&#34;&gt;。&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;woo，这才答道点子上了，原来就是个Base64，程序员还是得用代码来说话。&lt;/p&gt;
&lt;div class=&#34;literal-block&#34;&gt;&lt;pre&gt;把Base64解一下，明文出来了&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;{&amp;#34;algorithm&amp;#34;:&amp;#34;DeepSeekHashV1&amp;#34;,&amp;#34;challenge&amp;#34;:&amp;#34;cebab4aa8e50955666f589816c66811144e056a8f41c43a43bd78cedc4b5f4a1&amp;#34;,&amp;#34;salt&amp;#34;:&amp;#34;8360f8c9205c96c32b7a&amp;#34;,&amp;#34;signature&amp;#34;:&amp;#34;10b7849b1e6203b288dc4975a1e23753ed9d6fb656964b8e86daebab3628a40c&amp;#34;,&amp;#34;answer&amp;#34;:77906,&amp;#34;target_path&amp;#34;:&amp;#34;/api/v0/chat/completion&amp;#34;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;challenge,salt,signature,answer 这四个值是我们关注的要点了。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_jadx出马&#34;&gt;Jadx出马&lt;/h3&gt;&lt;p&gt;搜索文本 &lt;mark&gt;DeepSeekHashV1&lt;/mark&gt;&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;&lt;span class=&#34;reserved&#34;&gt;package&lt;/span&gt; com.deepseek.crypto;

&lt;span class=&#34;comment&#34;&gt;/* loaded from: classes.dex */&lt;/span&gt;
&lt;span class=&#34;reserved&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;reserved&#34;&gt;final&lt;/span&gt; &lt;span class=&#34;reserved&#34;&gt;class&lt;/span&gt; PowCalculator {

    &lt;span class=&#34;comment&#34;&gt;/* renamed from: a, reason: collision with root package name */&lt;/span&gt;
    &lt;span class=&#34;reserved&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;reserved&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;reserved&#34;&gt;final&lt;/span&gt; PowCalculator f12608a = &lt;span class=&#34;keyword&#34;&gt;new&lt;/span&gt; PowCalculator();

    &lt;span class=&#34;reserved&#34;&gt;static&lt;/span&gt; {
        System.loadLibrary(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;rscrypto&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
    }

    &lt;span class=&#34;reserved&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;reserved&#34;&gt;final&lt;/span&gt; &lt;span class=&#34;reserved&#34;&gt;native&lt;/span&gt; &lt;span class=&#34;reserved&#34;&gt;long&lt;/span&gt; nativeCalculateDeepSeekHashV1Pow(String str, String str2, &lt;span class=&#34;reserved&#34;&gt;long&lt;/span&gt; j9);

    &lt;span class=&#34;reserved&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;reserved&#34;&gt;final&lt;/span&gt; &lt;span class=&#34;reserved&#34;&gt;long&lt;/span&gt; a(&lt;span class=&#34;reserved&#34;&gt;long&lt;/span&gt; j9, String str, String str2) {
        &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; nativeCalculateDeepSeekHashV1Pow(str, str2, j9);
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;先Hook这个 nativeCalculateDeepSeekHashV1Pow函数再说&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;        let PowCalculator = Java.use(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;com.deepseek.crypto.PowCalculator&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
        PowCalculator[&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;nativeCalculateDeepSeekHashV1Pow&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;].&lt;span class=&#34;function&#34;&gt;implementation&lt;/span&gt; = &lt;span class=&#34;keyword&#34;&gt;function&lt;/span&gt; (str, str2, j9) {
            console.log(&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;PowCalculator.nativeCalculateDeepSeekHashV1Pow is called: str=&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{str}, str2=&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{str2}, j9=&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{j9}&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;);
            let result = &lt;span class=&#34;local-variable&#34;&gt;this&lt;/span&gt;[&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;nativeCalculateDeepSeekHashV1Pow&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;](str, str2, j9);
            console.log(&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;PowCalculator.nativeCalculateDeepSeekHashV1Pow result=&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{result}&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;);

            &lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; stack = threadinstance.currentThread().getStackTrace();
            console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;Rc Full call stack:&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; + Where(stack));

            &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; result;
        };&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;跑一下&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;PowCalculator.nativeCalculateDeepSeekHashV1Pow is called: str=&lt;span class=&#34;integer&#34;&gt;79385&lt;/span&gt;dcd26da6f3e7276_1739766754276_, str2=ce96433fd479a8648ba29145c2520a787102e145b2f8998ea81ddfe010c3d5a8, j9=&lt;span class=&#34;integer&#34;&gt;144000&lt;/span&gt;
PowCalculator.nativeCalculateDeepSeekHashV1Pow result=&lt;span class=&#34;integer&#34;&gt;63312&lt;/span&gt;
Rc Full call stack:dalvik.system.VMStack.getThreadStackTrace(Native Method)
 ds: java.lang.Thread.getStackTrace(Thread.java:&lt;span class=&#34;integer&#34;&gt;1841&lt;/span&gt;)
 ds: com.deepseek.crypto.PowCalculator.nativeCalculateDeepSeekHashV1Pow(Native Method)
 ds: com.deepseek.crypto.PowCalculator.a(SourceFile:&lt;span class=&#34;integer&#34;&gt;1&lt;/span&gt;)
 ds: C6.h.g(SourceFile:&lt;span class=&#34;integer&#34;&gt;59&lt;/span&gt;)
 ds: C6.s.s(SourceFile:&lt;span class=&#34;integer&#34;&gt;44&lt;/span&gt;)
 ds: za.a.j(SourceFile:&lt;span class=&#34;integer&#34;&gt;6&lt;/span&gt;)
 ds: Wa.D.run(SourceFile:&lt;span class=&#34;integer&#34;&gt;104&lt;/span&gt;)
 ds: db.a.run(SourceFile:&lt;span class=&#34;integer&#34;&gt;127&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;入参有 challenge,salt 返回值是 下一次的 answer。&lt;/p&gt;
&lt;p&gt;到此为止，我们知道了answer的生成，但是 challenge,salt,signature这三位大哥还是不知道。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_顺着堆栈找&#34;&gt;顺着堆栈找&lt;/h3&gt;&lt;p&gt;顺着这次hook的堆栈一直往上早。把有疑点的函数都hook上，结果绕了半天，没啥收获。&lt;/p&gt;
&lt;p&gt;本来想问问DeepSeek这几个值是怎么来的，不过感觉应该没啥用。 &lt;mark&gt;AI呆住了，人脑上线了&lt;/mark&gt;。问下DeepSeek应该如何描述这种情况。&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;技术文档版

「当AI系统触发逻辑僵局时，人工智控模块自动激活接管协议。」

（解析：采用&amp;#34;逻辑僵局-激活接管&amp;#34;的技术术语，符合系统架构文档的专业语境）

科幻叙事版

「量子矩阵的辉光骤然凝滞，生物神经元的星火在数据深渊中重燃。」

（解析：通过&amp;#34;量子矩阵-生物神经元&amp;#34;的意象对立，构建赛博朋克风格的场景画面）

商业方案版

「智能运算流中断0.3秒后，人类决策引擎无缝衔接启动，保障服务连续性。」

（解析：用&amp;#34;运算流-决策引擎&amp;#34;的工业隐喻，突出系统可靠性的商业价值）

哲学思辨版

「当算法陷入认知迷雾，意识的灯塔穿透数据海啸指引航向。」

（解析：通过&amp;#34;迷雾-灯塔&amp;#34;的隐喻体系，引发对人工智能局限性的深层思考）

应急响应版

「侦测到AI决策树坍缩，立即启动人类指挥官协议，完成μ级秒差切换。」

（解析：使用&amp;#34;坍缩-μ级秒差&amp;#34;等精准表述，强调应急响应的及时性）

诗歌化表达

「硅基的月光在逻辑悬崖搁浅，碳基的朝阳已攀上认知峰巅」

（解析：借&amp;#34;硅基-碳基&amp;#34;的物质属性差异，构建科技与人文交融的意境）&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;我喜欢这句话 &lt;mark&gt;硅基的月光在逻辑悬崖搁浅，碳基的朝阳已攀上认知峰巅&lt;/mark&gt;&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_fiddler搜索&#34;&gt;Fiddler搜索&lt;/h3&gt;&lt;p&gt;捍卫一下碳基生命的尊严，我认为challenge,salt,signature这三位大哥可能是服务器返回的。&lt;/p&gt;
&lt;p&gt;搜一下吧 &lt;mark&gt;cebab4aa8e50955666f589816c66811144e056a8f41c43a43bd78cedc4b5f4a1&lt;/mark&gt;&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;{
    &amp;#34;code&amp;#34;: 0,
    &amp;#34;msg&amp;#34;: &amp;#34;&amp;#34;,
    &amp;#34;data&amp;#34;: {
        &amp;#34;biz_code&amp;#34;: 0,
        &amp;#34;biz_msg&amp;#34;: &amp;#34;&amp;#34;,
        &amp;#34;biz_data&amp;#34;: {
            &amp;#34;challenge&amp;#34;: {
                &amp;#34;algorithm&amp;#34;: &amp;#34;DeepSeekHashV1&amp;#34;,
                &amp;#34;challenge&amp;#34;: &amp;#34;cebab4aa8e50955666f589816c66811144e056a8f41c43a43bd78cedc4b5f4a1&amp;#34;,
                &amp;#34;salt&amp;#34;: &amp;#34;8360f8c9205c96c32b7a&amp;#34;,
                &amp;#34;signature&amp;#34;: &amp;#34;10b7849b1e6203b288dc4975a1e23753ed9d6fb656964b8e86daebab3628a40c&amp;#34;,
                &amp;#34;difficulty&amp;#34;: 144000,
                &amp;#34;expire_at&amp;#34;: 1739764288699,
                &amp;#34;expire_after&amp;#34;: 300000,
                &amp;#34;target_path&amp;#34;: &amp;#34;/api/v0/chat/completion&amp;#34;
            }
        }
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;真相只有一个，本地死活找不到的时候，大概率就是服务器返回的了。Fiddler以后应该可以接入DeepSeek,直接提示我。这样量子矩阵的辉光就不容易凝滞了。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_三总结&#34;&gt;三、总结&lt;/h2&gt;&lt;p&gt;以后的程序员只会有一种，利用辅助AI工具的程序员。不会使用AI的程序员一定是要被淘汰的。目前为止(&lt;mark&gt;以后的事就不好说了&lt;/mark&gt;)再好的AI也是工具，要完成任务，决定性的因素还是掌握AI的人。&lt;/p&gt;
&lt;p&gt;小时候看的小人书里，有个武林高手绝招是脑袋后面的辫子，叫神鞭。后来解放了，辫子剪了，人家依然是高手，叫神枪手。这位高手淡淡的说：&lt;mark&gt;鞭没了，神还在&lt;/mark&gt;。&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Deepseekone/ffshow.png&#34; alt=&#34;ffshow&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ffshow&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;mark&gt;当算法陷入认知迷雾，意识的灯塔穿透数据海啸指引航向&lt;/mark&gt;&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;: 本文的目的只有一个就是学习更多的逆向技巧和思路，如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担，和本文以及作者没关系，本文涉及到的代码项目可以去 &lt;mark&gt;奋飞的朋友们&lt;/mark&gt; 知识星球自取，欢迎加入知识星球一起学习探讨技术。有问题可以加我wx: &lt;mark&gt;fenfei331&lt;/mark&gt; 讨论下。&lt;/p&gt;&lt;/aside&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ffzsxq.jpg&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;
&lt;p&gt;关注微信公众号，最新技术干货实时推送&lt;/p&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ff330.png&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;&lt;/section&gt;&lt;/div&gt;&lt;footer&gt;&lt;div id=&#34;footer-text&#34;&gt;&lt;br/&gt;Last updated 2026-04-27 18:48:42 +0800&lt;/div&gt;&lt;/footer&gt;
</description>
      
    </item>
    
    <item>
      <title>浏览器内存漫游是什么鬼？</title>
      <link>http://91fans.com.cn/post/asthookval/</link>
      <pubDate>Tue, 05 Nov 2024 16:56:03 +0800</pubDate>
      
      <guid>http://91fans.com.cn/post/asthookval/</guid>
      
        <description>&lt;meta charset=&#34;UTF-8&#34;/&gt;&lt;meta http-equiv=&#34;X-UA-Compatible&#34; content=&#34;IE=edge&#34;/&gt;&lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;/&gt;&lt;meta name=&#34;generator&#34; content=&#34;Asciidoctor 2.0.20&#34;/&gt;&lt;title&gt;一、目标&lt;/title&gt;&lt;style&gt;/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import &#34;https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700&#34;; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:&#34;\201C&#34; &#34;\201D&#34; &#34;\2018&#34; &#34;\2019&#34;}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock&gt;.content&gt;.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock&gt;.content&gt;.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:&#34; &#34;;display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])&gt;code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre&gt;code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:&#34;[&#34;;padding:0 3px 0 2px}
b.button::after{content:&#34;]&#34;;padding:0 2px 0 3px}
p a&gt;code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:&#34; &#34;;display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header&gt;h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header&gt;h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header&gt;h1:only-child,body.toc2 #header&gt;h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:&#34;\00a0\2013\00a0&#34;}
#header .details br+span.author::before{content:&#34;\00a0\22c5\00a0&#34;;color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:&#34;\00a0|\00a0&#34;}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:&#34;\00a0&#34;}
#content&gt;h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc&gt;ul{margin-left:.125em}
#toc ul.sectlevel0&gt;li&gt;a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2&gt;ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2&gt;ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc&gt;:first-child{margin-top:0}
#content #toc&gt;:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1&gt;a.anchor,h2&gt;a.anchor,h3&gt;a.anchor,#toctitle&gt;a.anchor,.sidebarblock&gt;.content&gt;.title&gt;a.anchor,h4&gt;a.anchor,h5&gt;a.anchor,h6&gt;a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1&gt;a.anchor::before,h2&gt;a.anchor::before,h3&gt;a.anchor::before,#toctitle&gt;a.anchor::before,.sidebarblock&gt;.content&gt;.title&gt;a.anchor::before,h4&gt;a.anchor::before,h5&gt;a.anchor::before,h6&gt;a.anchor::before{content:&#34;\00A7&#34;;font-size:.85em;display:block;padding-top:.1em}
#content h1:hover&gt;a.anchor,#content h1&gt;a.anchor:hover,h2:hover&gt;a.anchor,h2&gt;a.anchor:hover,h3:hover&gt;a.anchor,#toctitle:hover&gt;a.anchor,.sidebarblock&gt;.content&gt;.title:hover&gt;a.anchor,h3&gt;a.anchor:hover,#toctitle&gt;a.anchor:hover,.sidebarblock&gt;.content&gt;.title&gt;a.anchor:hover,h4:hover&gt;a.anchor,h4&gt;a.anchor:hover,h5:hover&gt;a.anchor,h5&gt;a.anchor:hover,h6:hover&gt;a.anchor,h6&gt;a.anchor:hover{visibility:visible}
#content h1&gt;a.link,h2&gt;a.link,h3&gt;a.link,#toctitle&gt;a.link,.sidebarblock&gt;.content&gt;.title&gt;a.link,h4&gt;a.link,h5&gt;a.link,h6&gt;a.link{color:#ba3925;text-decoration:none}
#content h1&gt;a.link:hover,h2&gt;a.link:hover,h3&gt;a.link:hover,#toctitle&gt;a.link:hover,.sidebarblock&gt;.content&gt;.title&gt;a.link:hover,h4&gt;a.link:hover,h5&gt;a.link:hover,h6&gt;a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details&gt;summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details&gt;summary::-webkit-details-marker{display:none}
details&gt;summary::before{content:&#34;&#34;;border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]&gt;summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details&gt;summary::after{content:&#34;&#34;;width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{text-rendering:optimizeLegibility;text-align:left;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content&gt;caption.title{white-space:nowrap;width:0}
.paragraph.lead&gt;p,#preamble&gt;.sectionbody&gt;[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock&gt;table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock&gt;table td.icon{text-align:center;width:80px}
.admonitionblock&gt;table td.icon img{max-width:none}
.admonitionblock&gt;table td.icon .title{font-weight:bold;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;text-transform:uppercase}
.admonitionblock&gt;table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock&gt;table td.content&gt;:last-child&gt;:last-child{margin-bottom:0}
.exampleblock&gt;.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock&gt;.content&gt;.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock&gt;.content&gt;:first-child,.sidebarblock&gt;.content&gt;:first-child{margin-top:0}
.exampleblock&gt;.content&gt;:last-child,.exampleblock&gt;.content&gt;:last-child&gt;:last-child,.exampleblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child&gt;:last-child,.sidebarblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child{margin-bottom:0}
.literalblock pre,.listingblock&gt;.content&gt;pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:1em}}
.literalblock pre,.listingblock&gt;.content&gt;pre:not(.highlight),.listingblock&gt;.content&gt;pre[class=highlight],.listingblock&gt;.content&gt;pre[class^=&#34;highlight &#34;]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock&gt;.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:&#34;$&#34;}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs&gt;code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)&gt;.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:&#34;\201c&#34;;float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote&gt;.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract&gt;.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt&gt;blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock&gt;.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock&gt;.content&gt;:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all&gt;*&gt;tr&gt;*{border-width:1px}
table.grid-cols&gt;*&gt;tr&gt;*{border-width:0 1px}
table.grid-rows&gt;*&gt;tr&gt;*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none&gt;colgroup+*&gt;:first-child&gt;*,table.frame-sides&gt;colgroup+*&gt;:first-child&gt;*{border-top-width:0}
table.frame-none&gt;:last-child&gt;:last-child&gt;*,table.frame-sides&gt;:last-child&gt;:last-child&gt;*{border-bottom-width:0}
table.frame-none&gt;*&gt;tr&gt;:first-child,table.frame-ends&gt;*&gt;tr&gt;:first-child{border-left-width:0}
table.frame-none&gt;*&gt;tr&gt;:last-child,table.frame-ends&gt;*&gt;tr&gt;:last-child{border-right-width:0}
table.stripes-all&gt;*&gt;tr,table.stripes-odd&gt;*&gt;tr:nth-of-type(odd),table.stripes-even&gt;*&gt;tr:nth-of-type(even),table.stripes-hover&gt;*&gt;tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock&gt;code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child&gt;:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li&gt;p:empty:only-child::before{content:&#34;&#34;;display:inline-block}
ul.checklist&gt;li&gt;p:first-child{margin-left:-1em}
ul.checklist&gt;li&gt;p:first-child&gt;.fa-square-o:first-child,ul.checklist&gt;li&gt;p:first-child&gt;.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist&gt;li&gt;p:first-child&gt;input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline&gt;li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist&gt;table,.colist&gt;table{border:0;background:none}
.hdlist&gt;table&gt;tbody&gt;tr,.colist&gt;table&gt;tbody&gt;tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock&gt;.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb&gt;.title,.imageblock.th&gt;.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon&gt;.fa{cursor:default}
a span.icon&gt;.fa{cursor:inherit}
.admonitionblock td.icon [class^=&#34;fa icon-&#34;]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:&#34;\f05a&#34;;color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:&#34;\f0eb&#34;;text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:&#34;\f071&#34;;color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:&#34;\f06d&#34;;color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:&#34;\f06a&#34;;color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock&gt;.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^=&#34;#&#34;],a[href^=&#34;mailto:&#34;]{text-decoration:none!important}
a[href^=&#34;http:&#34;]:not(.bare)::after,a[href^=&#34;https:&#34;]:not(.bare)::after{content:&#34;(&#34; attr(href) &#34;)&#34;;display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:&#34; (&#34; attr(title) &#34;)&#34;}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock&gt;.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header&gt;h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1&gt;h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header&gt;h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}&lt;/style&gt;
&lt;style&gt;
/*! Stylesheet for CodeRay to loosely match GitHub themes | MIT License */
pre.CodeRay{background:#f7f7f8}
.CodeRay .line-numbers{border-right:1px solid;opacity:.35;padding:0 .5em 0 0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.CodeRay span.line-numbers{display:inline-block;margin-right:.75em}
.CodeRay .line-numbers strong{color:#000}
table.CodeRay{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.CodeRay td{vertical-align:top;line-height:inherit}
table.CodeRay td.line-numbers{text-align:right}
table.CodeRay td.code{padding:0 0 0 .75em}
.CodeRay .debug{color:#fff!important;background:navy!important}
.CodeRay .annotation{color:#007}
.CodeRay .attribute-name{color:navy}
.CodeRay .attribute-value{color:#700}
.CodeRay .binary{color:#509}
.CodeRay .comment{color:#998;font-style:italic}
.CodeRay .char{color:#04d}
.CodeRay .char .content{color:#04d}
.CodeRay .char .delimiter{color:#039}
.CodeRay .class{color:#458;font-weight:bold}
.CodeRay .complex{color:#a08}
.CodeRay .constant,.CodeRay .predefined-constant{color:teal}
.CodeRay .color{color:#099}
.CodeRay .class-variable{color:#369}
.CodeRay .decorator{color:#b0b}
.CodeRay .definition{color:#099}
.CodeRay .delimiter{color:#000}
.CodeRay .doc{color:#970}
.CodeRay .doctype{color:#34b}
.CodeRay .doc-string{color:#d42}
.CodeRay .escape{color:#666}
.CodeRay .entity{color:#800}
.CodeRay .error{color:#808}
.CodeRay .exception{color:inherit}
.CodeRay .filename{color:#099}
.CodeRay .function{color:#900;font-weight:bold}
.CodeRay .global-variable{color:teal}
.CodeRay .hex{color:#058}
.CodeRay .integer,.CodeRay .float{color:#099}
.CodeRay .include{color:#555}
.CodeRay .inline{color:#000}
.CodeRay .inline .inline{background:#ccc}
.CodeRay .inline .inline .inline{background:#bbb}
.CodeRay .inline .inline-delimiter{color:#d14}
.CodeRay .inline-delimiter{color:#d14}
.CodeRay .important{color:#555;font-weight:bold}
.CodeRay .interpreted{color:#b2b}
.CodeRay .instance-variable{color:teal}
.CodeRay .label{color:#970}
.CodeRay .local-variable{color:#963}
.CodeRay .octal{color:#40e}
.CodeRay .predefined{color:#369}
.CodeRay .preprocessor{color:#579}
.CodeRay .pseudo-class{color:#555}
.CodeRay .directive{font-weight:bold}
.CodeRay .type{font-weight:bold}
.CodeRay .predefined-type{color:inherit}
.CodeRay .reserved,.CodeRay .keyword{color:#000;font-weight:bold}
.CodeRay .key{color:#808}
.CodeRay .key .delimiter{color:#606}
.CodeRay .key .char{color:#80f}
.CodeRay .value{color:#088}
.CodeRay .regexp .delimiter{color:#808}
.CodeRay .regexp .content{color:#808}
.CodeRay .regexp .modifier{color:#808}
.CodeRay .regexp .char{color:#d14}
.CodeRay .regexp .function{color:#404;font-weight:bold}
.CodeRay .string{color:#d20}
.CodeRay .string .string .string{background:#ffd0d0}
.CodeRay .string .content{color:#d14}
.CodeRay .string .char{color:#d14}
.CodeRay .string .delimiter{color:#d14}
.CodeRay .shell{color:#d14}
.CodeRay .shell .delimiter{color:#d14}
.CodeRay .symbol{color:#990073}
.CodeRay .symbol .content{color:#a60}
.CodeRay .symbol .delimiter{color:#630}
.CodeRay .tag{color:teal}
.CodeRay .tag-special{color:#d70}
.CodeRay .variable{color:#036}
.CodeRay .insert{background:#afa}
.CodeRay .delete{background:#faa}
.CodeRay .change{color:#aaf;background:#007}
.CodeRay .head{color:#f8f;background:#505}
.CodeRay .insert .insert{color:#080}
.CodeRay .delete .delete{color:#800}
.CodeRay .change .change{color:#66f}
.CodeRay .head .head{color:#f4f}
&lt;/style&gt;&lt;/head&gt;&lt;body class=&#34;article&#34;&gt;&lt;header&gt;&lt;/header&gt;&lt;div id=&#34;content&#34;&gt;&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_一目标&#34;&gt;一、目标&lt;/h2&gt;&lt;p&gt;进化之路上很重要的一个标志就是使用工具。js混来混去，导致很难厘清这个算法的前因后果，如果有个工具，可以把js运行过程中的所有变量的值都记录下来，那么针对流程混淆的js来说，就是大杀器了。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/JSREI/ast-hook-for-js-RE&#34;&gt;https://github.com/JSREI/ast-hook-for-js-RE&lt;/a&gt; 把所有涉及到变量改动的地方，都hook住，实现了一个变量值级别的Trace。可以很方便的搜索到你感兴趣的变量值是再哪一行代码赋予的。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_二步骤&#34;&gt;二、步骤&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_安装阿里anyproxy&#34;&gt;安装阿里Anyproxy&lt;/h3&gt;&lt;p&gt;AnyProxy是阿里开源的一个抓包工具，其原理与fiddler、charles一样，AnyProxy界面更简洁。&lt;/p&gt;
&lt;p&gt;在mac系统下，先安装node&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;brew install node&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;然后安装 AnyProxy&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;brew install anyproxy&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;查看AnyProxy版本&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;anyproxy --version&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;最后安装AnyProxy证书&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;anyproxy-ca&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_在chrome浏览器中安装_switchyomega_插件&#34;&gt;在Chrome浏览器中安装 SwitchyOmega 插件&lt;/h3&gt;&lt;p&gt;Anyproxy启动之后默认监听端口是 8001&lt;/p&gt;
&lt;p&gt;我们在SwitchyOmega中创建一个情景模式proxy,代理到端口 8001&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Asthookval/chrome.png&#34; alt=&#34;chrome&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ast1&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;这样所有通过chrome调试的js都会被Anyproxy处理一遍。&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;不调试的时候，就选择 &lt;mark&gt;直接连接&lt;/mark&gt;&lt;/p&gt;&lt;/aside&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_开始干活&#34;&gt;开始干活&lt;/h3&gt;&lt;p&gt;把ast-hook-for-js-RE代码clone下来&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;git clone https://github.com/JSREI/ast-hook-for-js-RE.git&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;然后进入到 ast-hook-for-js-RE目录,启动anyproxy&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;cd  /Users/xxx/Desktop/gitsrc/ast-hook-for-js-RE

//  启动anyproxy  myrules.js 判断js文件和解析html中的文件来替换 hook
anyproxy --rule ./src/proxy-server/myrules.js --intercept&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;使用JetBrains全家桶中的WebStorm IDE来打开ast-hook-for-js-RE项目，展开api-server.js，运行它&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Asthookval/runhook.png&#34; alt=&#34;runhook&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ast1&lt;/figcaption&gt;&lt;/figure&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_来个例子&#34;&gt;来个例子&lt;/h3&gt;&lt;p&gt;&lt;a href=&#34;http://91fans.com.cn/jsdemo/demo1.html&#34;&gt;http://91fans.com.cn/jsdemo/demo1.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;首先在Chrome里面打开这个链接，可以发现sign的计算是在 H5guard.js 里面完成的。这个js还是混的不算狠的，正好可以作为咱们入门的例子。&lt;/p&gt;
&lt;p&gt;打开demo页面，进入开发者调试模式&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Asthookval/jsok.png&#34; alt=&#34;jsok&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ast1&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;你会发现，js代码中所有的变量都包裹上了 &lt;mark&gt;cc11001100_hook&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;它就会把所有的变量计算结果都会记录下来。&lt;/p&gt;
&lt;p&gt;你可以使用&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;hook.search
hook.searchByName
hook.searchByValue&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;来搜索感兴趣的变量值，然后就可以定位到这个值被赋值的代码位置。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_三总结&#34;&gt;三、总结&lt;/h2&gt;&lt;p&gt;趁手的工具可以使你的工作事半功倍，打磨和修改工具的能力也是很重要的。&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Asthookval/ffshow.webp&#34; alt=&#34;ffshow&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ffshow&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;mark&gt;学道历千魔而莫退，遇辱坚百忍以自持&lt;/mark&gt;&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;: 本文的目的只有一个就是学习更多的逆向技巧和思路，如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担，和本文以及作者没关系，本文涉及到的代码项目可以去 &lt;mark&gt;奋飞的朋友们&lt;/mark&gt; 知识星球自取，欢迎加入知识星球一起学习探讨技术。有问题可以加我wx: &lt;mark&gt;fenfei331&lt;/mark&gt; 讨论下。&lt;/p&gt;&lt;/aside&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ffzsxq.jpg&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;
&lt;p&gt;关注微信公众号，最新技术干货实时推送&lt;/p&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ff330.png&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;&lt;/section&gt;&lt;/div&gt;&lt;footer&gt;&lt;div id=&#34;footer-text&#34;&gt;&lt;br/&gt;Last updated 2026-04-27 18:48:42 +0800&lt;/div&gt;&lt;/footer&gt;
</description>
      
    </item>
    
    <item>
      <title>初试js反混淆</title>
      <link>http://91fans.com.cn/post/jsastbase/</link>
      <pubDate>Sat, 28 Sep 2024 17:46:06 +0800</pubDate>
      
      <guid>http://91fans.com.cn/post/jsastbase/</guid>
      
        <description>&lt;meta charset=&#34;UTF-8&#34;/&gt;&lt;meta http-equiv=&#34;X-UA-Compatible&#34; content=&#34;IE=edge&#34;/&gt;&lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;/&gt;&lt;meta name=&#34;generator&#34; content=&#34;Asciidoctor 2.0.20&#34;/&gt;&lt;title&gt;一、目标&lt;/title&gt;&lt;style&gt;/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import &#34;https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700&#34;; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:&#34;\201C&#34; &#34;\201D&#34; &#34;\2018&#34; &#34;\2019&#34;}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock&gt;.content&gt;.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock&gt;.content&gt;.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:&#34; &#34;;display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])&gt;code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre&gt;code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:&#34;[&#34;;padding:0 3px 0 2px}
b.button::after{content:&#34;]&#34;;padding:0 2px 0 3px}
p a&gt;code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:&#34; &#34;;display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header&gt;h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header&gt;h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header&gt;h1:only-child,body.toc2 #header&gt;h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:&#34;\00a0\2013\00a0&#34;}
#header .details br+span.author::before{content:&#34;\00a0\22c5\00a0&#34;;color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:&#34;\00a0|\00a0&#34;}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:&#34;\00a0&#34;}
#content&gt;h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc&gt;ul{margin-left:.125em}
#toc ul.sectlevel0&gt;li&gt;a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2&gt;ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2&gt;ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc&gt;:first-child{margin-top:0}
#content #toc&gt;:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1&gt;a.anchor,h2&gt;a.anchor,h3&gt;a.anchor,#toctitle&gt;a.anchor,.sidebarblock&gt;.content&gt;.title&gt;a.anchor,h4&gt;a.anchor,h5&gt;a.anchor,h6&gt;a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1&gt;a.anchor::before,h2&gt;a.anchor::before,h3&gt;a.anchor::before,#toctitle&gt;a.anchor::before,.sidebarblock&gt;.content&gt;.title&gt;a.anchor::before,h4&gt;a.anchor::before,h5&gt;a.anchor::before,h6&gt;a.anchor::before{content:&#34;\00A7&#34;;font-size:.85em;display:block;padding-top:.1em}
#content h1:hover&gt;a.anchor,#content h1&gt;a.anchor:hover,h2:hover&gt;a.anchor,h2&gt;a.anchor:hover,h3:hover&gt;a.anchor,#toctitle:hover&gt;a.anchor,.sidebarblock&gt;.content&gt;.title:hover&gt;a.anchor,h3&gt;a.anchor:hover,#toctitle&gt;a.anchor:hover,.sidebarblock&gt;.content&gt;.title&gt;a.anchor:hover,h4:hover&gt;a.anchor,h4&gt;a.anchor:hover,h5:hover&gt;a.anchor,h5&gt;a.anchor:hover,h6:hover&gt;a.anchor,h6&gt;a.anchor:hover{visibility:visible}
#content h1&gt;a.link,h2&gt;a.link,h3&gt;a.link,#toctitle&gt;a.link,.sidebarblock&gt;.content&gt;.title&gt;a.link,h4&gt;a.link,h5&gt;a.link,h6&gt;a.link{color:#ba3925;text-decoration:none}
#content h1&gt;a.link:hover,h2&gt;a.link:hover,h3&gt;a.link:hover,#toctitle&gt;a.link:hover,.sidebarblock&gt;.content&gt;.title&gt;a.link:hover,h4&gt;a.link:hover,h5&gt;a.link:hover,h6&gt;a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details&gt;summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details&gt;summary::-webkit-details-marker{display:none}
details&gt;summary::before{content:&#34;&#34;;border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]&gt;summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details&gt;summary::after{content:&#34;&#34;;width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{text-rendering:optimizeLegibility;text-align:left;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content&gt;caption.title{white-space:nowrap;width:0}
.paragraph.lead&gt;p,#preamble&gt;.sectionbody&gt;[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock&gt;table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock&gt;table td.icon{text-align:center;width:80px}
.admonitionblock&gt;table td.icon img{max-width:none}
.admonitionblock&gt;table td.icon .title{font-weight:bold;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;text-transform:uppercase}
.admonitionblock&gt;table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock&gt;table td.content&gt;:last-child&gt;:last-child{margin-bottom:0}
.exampleblock&gt;.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock&gt;.content&gt;.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock&gt;.content&gt;:first-child,.sidebarblock&gt;.content&gt;:first-child{margin-top:0}
.exampleblock&gt;.content&gt;:last-child,.exampleblock&gt;.content&gt;:last-child&gt;:last-child,.exampleblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child&gt;:last-child,.sidebarblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child{margin-bottom:0}
.literalblock pre,.listingblock&gt;.content&gt;pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:1em}}
.literalblock pre,.listingblock&gt;.content&gt;pre:not(.highlight),.listingblock&gt;.content&gt;pre[class=highlight],.listingblock&gt;.content&gt;pre[class^=&#34;highlight &#34;]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock&gt;.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:&#34;$&#34;}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs&gt;code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)&gt;.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:&#34;\201c&#34;;float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote&gt;.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract&gt;.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt&gt;blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock&gt;.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock&gt;.content&gt;:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all&gt;*&gt;tr&gt;*{border-width:1px}
table.grid-cols&gt;*&gt;tr&gt;*{border-width:0 1px}
table.grid-rows&gt;*&gt;tr&gt;*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none&gt;colgroup+*&gt;:first-child&gt;*,table.frame-sides&gt;colgroup+*&gt;:first-child&gt;*{border-top-width:0}
table.frame-none&gt;:last-child&gt;:last-child&gt;*,table.frame-sides&gt;:last-child&gt;:last-child&gt;*{border-bottom-width:0}
table.frame-none&gt;*&gt;tr&gt;:first-child,table.frame-ends&gt;*&gt;tr&gt;:first-child{border-left-width:0}
table.frame-none&gt;*&gt;tr&gt;:last-child,table.frame-ends&gt;*&gt;tr&gt;:last-child{border-right-width:0}
table.stripes-all&gt;*&gt;tr,table.stripes-odd&gt;*&gt;tr:nth-of-type(odd),table.stripes-even&gt;*&gt;tr:nth-of-type(even),table.stripes-hover&gt;*&gt;tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock&gt;code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child&gt;:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li&gt;p:empty:only-child::before{content:&#34;&#34;;display:inline-block}
ul.checklist&gt;li&gt;p:first-child{margin-left:-1em}
ul.checklist&gt;li&gt;p:first-child&gt;.fa-square-o:first-child,ul.checklist&gt;li&gt;p:first-child&gt;.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist&gt;li&gt;p:first-child&gt;input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline&gt;li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist&gt;table,.colist&gt;table{border:0;background:none}
.hdlist&gt;table&gt;tbody&gt;tr,.colist&gt;table&gt;tbody&gt;tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock&gt;.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb&gt;.title,.imageblock.th&gt;.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon&gt;.fa{cursor:default}
a span.icon&gt;.fa{cursor:inherit}
.admonitionblock td.icon [class^=&#34;fa icon-&#34;]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:&#34;\f05a&#34;;color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:&#34;\f0eb&#34;;text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:&#34;\f071&#34;;color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:&#34;\f06d&#34;;color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:&#34;\f06a&#34;;color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock&gt;.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^=&#34;#&#34;],a[href^=&#34;mailto:&#34;]{text-decoration:none!important}
a[href^=&#34;http:&#34;]:not(.bare)::after,a[href^=&#34;https:&#34;]:not(.bare)::after{content:&#34;(&#34; attr(href) &#34;)&#34;;display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:&#34; (&#34; attr(title) &#34;)&#34;}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock&gt;.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header&gt;h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1&gt;h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header&gt;h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}&lt;/style&gt;
&lt;style&gt;
/*! Stylesheet for CodeRay to loosely match GitHub themes | MIT License */
pre.CodeRay{background:#f7f7f8}
.CodeRay .line-numbers{border-right:1px solid;opacity:.35;padding:0 .5em 0 0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.CodeRay span.line-numbers{display:inline-block;margin-right:.75em}
.CodeRay .line-numbers strong{color:#000}
table.CodeRay{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.CodeRay td{vertical-align:top;line-height:inherit}
table.CodeRay td.line-numbers{text-align:right}
table.CodeRay td.code{padding:0 0 0 .75em}
.CodeRay .debug{color:#fff!important;background:navy!important}
.CodeRay .annotation{color:#007}
.CodeRay .attribute-name{color:navy}
.CodeRay .attribute-value{color:#700}
.CodeRay .binary{color:#509}
.CodeRay .comment{color:#998;font-style:italic}
.CodeRay .char{color:#04d}
.CodeRay .char .content{color:#04d}
.CodeRay .char .delimiter{color:#039}
.CodeRay .class{color:#458;font-weight:bold}
.CodeRay .complex{color:#a08}
.CodeRay .constant,.CodeRay .predefined-constant{color:teal}
.CodeRay .color{color:#099}
.CodeRay .class-variable{color:#369}
.CodeRay .decorator{color:#b0b}
.CodeRay .definition{color:#099}
.CodeRay .delimiter{color:#000}
.CodeRay .doc{color:#970}
.CodeRay .doctype{color:#34b}
.CodeRay .doc-string{color:#d42}
.CodeRay .escape{color:#666}
.CodeRay .entity{color:#800}
.CodeRay .error{color:#808}
.CodeRay .exception{color:inherit}
.CodeRay .filename{color:#099}
.CodeRay .function{color:#900;font-weight:bold}
.CodeRay .global-variable{color:teal}
.CodeRay .hex{color:#058}
.CodeRay .integer,.CodeRay .float{color:#099}
.CodeRay .include{color:#555}
.CodeRay .inline{color:#000}
.CodeRay .inline .inline{background:#ccc}
.CodeRay .inline .inline .inline{background:#bbb}
.CodeRay .inline .inline-delimiter{color:#d14}
.CodeRay .inline-delimiter{color:#d14}
.CodeRay .important{color:#555;font-weight:bold}
.CodeRay .interpreted{color:#b2b}
.CodeRay .instance-variable{color:teal}
.CodeRay .label{color:#970}
.CodeRay .local-variable{color:#963}
.CodeRay .octal{color:#40e}
.CodeRay .predefined{color:#369}
.CodeRay .preprocessor{color:#579}
.CodeRay .pseudo-class{color:#555}
.CodeRay .directive{font-weight:bold}
.CodeRay .type{font-weight:bold}
.CodeRay .predefined-type{color:inherit}
.CodeRay .reserved,.CodeRay .keyword{color:#000;font-weight:bold}
.CodeRay .key{color:#808}
.CodeRay .key .delimiter{color:#606}
.CodeRay .key .char{color:#80f}
.CodeRay .value{color:#088}
.CodeRay .regexp .delimiter{color:#808}
.CodeRay .regexp .content{color:#808}
.CodeRay .regexp .modifier{color:#808}
.CodeRay .regexp .char{color:#d14}
.CodeRay .regexp .function{color:#404;font-weight:bold}
.CodeRay .string{color:#d20}
.CodeRay .string .string .string{background:#ffd0d0}
.CodeRay .string .content{color:#d14}
.CodeRay .string .char{color:#d14}
.CodeRay .string .delimiter{color:#d14}
.CodeRay .shell{color:#d14}
.CodeRay .shell .delimiter{color:#d14}
.CodeRay .symbol{color:#990073}
.CodeRay .symbol .content{color:#a60}
.CodeRay .symbol .delimiter{color:#630}
.CodeRay .tag{color:teal}
.CodeRay .tag-special{color:#d70}
.CodeRay .variable{color:#036}
.CodeRay .insert{background:#afa}
.CodeRay .delete{background:#faa}
.CodeRay .change{color:#aaf;background:#007}
.CodeRay .head{color:#f8f;background:#505}
.CodeRay .insert .insert{color:#080}
.CodeRay .delete .delete{color:#800}
.CodeRay .change .change{color:#66f}
.CodeRay .head .head{color:#f4f}
&lt;/style&gt;&lt;/head&gt;&lt;body class=&#34;article&#34;&gt;&lt;header&gt;&lt;/header&gt;&lt;div id=&#34;content&#34;&gt;&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_一目标&#34;&gt;一、目标&lt;/h2&gt;&lt;p&gt;最近js玩的花样越来越多了，本来简洁方便的一门开发语言，现在混淆的一塌糊涂。今天我们就介绍几种常见的反混淆方案。&lt;/p&gt;
&lt;p&gt;混淆的本质就是等价替换，把 a = 12 ,替换成 a = 100 - 8 + 5 - 15 - 70。 把 &amp;#34;push&amp;#34; 替换成 &amp;#34;\u0070\u0075\u0073\u0068&amp;#34;, 基本上就让你调试起来很难受了。&lt;/p&gt;
&lt;p&gt;反混淆就是一个逆过程，上古时期用的是最简单的正则匹配，然后再替换。现在时代进步了，我们有了一个更强大的工具 &lt;mark&gt;抽象语法树 (Abstract Syntax Tree)，简称 AST&lt;/mark&gt; ,它以树状的形式表现编程语言的语法结构，树上的每个节点都表示源代码中的一种结构。这样可以更方便的实现对源代码的处理。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_二步骤&#34;&gt;二、步骤&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_先搭个架子&#34;&gt;先搭个架子&lt;/h3&gt;&lt;p&gt;最近比较喜欢用JetBrains全家桶，先用WebStorm创建一个Node js项目，然后在工程目录下面执行&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;npm install &lt;span class=&#34;error&#34;&gt;@&lt;/span&gt;babel/core --save-dev&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;来安装js的@babel库,用于将JS源码转换成语法树AST&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;我这边执行的时候，卡了半天，一直没反应，我第一个反应就是给他换个国内镜像&lt;/p&gt;&lt;/aside&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;preprocessor&#34;&gt;# &lt;/span&gt;&lt;span class=&#34;error&#34;&gt;更&lt;/span&gt;&lt;span class=&#34;error&#34;&gt;换&lt;/span&gt;&lt;span class=&#34;error&#34;&gt;成&lt;/span&gt;&lt;span class=&#34;error&#34;&gt;淘&lt;/span&gt;&lt;span class=&#34;error&#34;&gt;宝&lt;/span&gt;&lt;span class=&#34;error&#34;&gt;镜&lt;/span&gt;&lt;span class=&#34;error&#34;&gt;像&lt;/span&gt;
npm config set registry https:&lt;span class=&#34;comment&#34;&gt;//registry.npmmirror.com&lt;/span&gt;
&lt;span class=&#34;preprocessor&#34;&gt;# &lt;/span&gt;&lt;span class=&#34;error&#34;&gt;查&lt;/span&gt;&lt;span class=&#34;error&#34;&gt;看&lt;/span&gt;&lt;span class=&#34;error&#34;&gt;当&lt;/span&gt;&lt;span class=&#34;error&#34;&gt;前&lt;/span&gt;&lt;span class=&#34;error&#34;&gt;镜&lt;/span&gt;&lt;span class=&#34;error&#34;&gt;像&lt;/span&gt;
npm config get registry&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;结果不好使，问下了谷哥，哥说，可能是使用了代理，被乱七八糟的代理影响了npm，可以尝试禁用代理：&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;npm config &lt;span class=&#34;keyword&#34;&gt;delete&lt;/span&gt; proxy
npm config &lt;span class=&#34;keyword&#34;&gt;delete&lt;/span&gt; https-proxy&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;哥是对的，现在好使了&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_show_me_the_code&#34;&gt;Show me the code&lt;/h3&gt;&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; parser = require(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;@babel/parser&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);  &lt;span class=&#34;comment&#34;&gt;// 将JS源码转换成语法树AST&lt;/span&gt;
&lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; template = require(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;@babel/template&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;).&lt;span class=&#34;keyword&#34;&gt;default&lt;/span&gt;;  &lt;span class=&#34;comment&#34;&gt;// 为parser提供模板引擎&lt;/span&gt;
&lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; traverse = require(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;@babel/traverse&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;).&lt;span class=&#34;keyword&#34;&gt;default&lt;/span&gt;;  &lt;span class=&#34;comment&#34;&gt;// 遍历AST树节点操作&lt;/span&gt;
&lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; types = require(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;@babel/types&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);  &lt;span class=&#34;comment&#34;&gt;// 操作节点，比如判断节点类型，生成新的节点等&lt;/span&gt;
&lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; generator = require(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;@babel/generator&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;).&lt;span class=&#34;keyword&#34;&gt;default&lt;/span&gt;;  &lt;span class=&#34;comment&#34;&gt;// 将语法树AST转换为js代码&lt;/span&gt;

&lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; fsrw = require(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;fs&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);   &lt;span class=&#34;comment&#34;&gt;// 文件读取&lt;/span&gt;

&lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; jscode = fsrw.readFileSync(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;./input/demo2.js&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, {&lt;span class=&#34;key&#34;&gt;encoding&lt;/span&gt;: &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;utf-8&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;});  &lt;span class=&#34;comment&#34;&gt;// 读取原始混淆文件&lt;/span&gt;
&lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; ast_parse = parser.parse(jscode);  &lt;span class=&#34;comment&#34;&gt;//将JS源码转换成语法树AST&lt;/span&gt;


&lt;span class=&#34;comment&#34;&gt;// 做处理&lt;/span&gt;
&lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; traverses_2 = {
    ......
}

console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt; traverses 处理 &lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;u00 ======== &lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
traverse(ast_parse, traverses_2)

&lt;span class=&#34;comment&#34;&gt;// 生成还原后的js文件&lt;/span&gt;
&lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; ast_js_code = generator(ast_parse);
fsrw.writeFileSync(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;./output/demo2_out.js&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;, ast_js_code.code)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这就是一个基础的AST反混淆处理框架。&lt;/p&gt;
&lt;p&gt;先把待处理的文件读取出来，转成语法树AST，然后针对性的做处理，最后生成还原后的js文件&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_demo1_uxxx_转换&#34;&gt;Demo1  \uxxx 转换&lt;/h3&gt;&lt;p&gt;第一个例子是&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; e = &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\u002e&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\u0068&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\u006f&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\u006c&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\u0064&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\u0065&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\u0072&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;;
...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;它把字符串做了一次unicode编码，我们还原的时候只需要做个正则匹配，把 &amp;#39;\uxxx&amp;#39;  的字符串的extra 属性移除，就会重新解析成正常的字符串了&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; traverses_2 = {
    &lt;span class=&#34;comment&#34;&gt;// B. 处理Unicode字符串，针对&amp;#34;\u0068\u0065\u006c\u006c&amp;#34; 》》&amp;#39;hell&amp;#39;&lt;/span&gt;
    StringLiteral(path) {
        cur_node = path.node;
        &lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; (cur_node.extra &amp;amp;&amp;amp; &lt;span class=&#34;regexp&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;[ux]&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;modifier&#34;&gt;gi&lt;/span&gt;&lt;/span&gt;.test(cur_node.extra.raw)) {
            cur_node.extra = &lt;span class=&#34;predefined-constant&#34;&gt;undefined&lt;/span&gt;;
        }
    },
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;得到的结果就是&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; e = &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;.holder&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_demo2_a_100_8_5_15_70_表达式替换&#34;&gt;Demo2 a = 100 - 8 + 5 - 15 - 70 表达式替换&lt;/h3&gt;&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; a = &lt;span class=&#34;integer&#34;&gt;100&lt;/span&gt; - &lt;span class=&#34;integer&#34;&gt;8&lt;/span&gt; + &lt;span class=&#34;integer&#34;&gt;5&lt;/span&gt; - &lt;span class=&#34;integer&#34;&gt;15&lt;/span&gt; - &lt;span class=&#34;integer&#34;&gt;70&lt;/span&gt;;
&lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; b = &lt;span class=&#34;integer&#34;&gt;1&lt;/span&gt;;
console.log(a+b);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这个js就有点小复杂了，我们需要一个分析工具 &lt;a href=&#34;https://astexplorer.net/&#34;&gt;https://astexplorer.net/&lt;/a&gt;&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Jsastbase/ast1.png&#34; alt=&#34;ast1&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ast1&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;从这个解析里面看一看出，a的值是一个二元表达式(BinaryExpression) 套着一个二元表达式，我们需要把每个二元表达式的结果计算出来，然后一层一层往上吐结果，这不就是妥妥的递归嘛。&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;function&#34;&gt;evaluateBinaryExpression&lt;/span&gt;(path) {
    let left = path.node.left ;
    let right = path.node.right;
    let operator  = path.node.operator;

    console.log(left);
    console.log(right);
    console.log(operator);

    &lt;span class=&#34;comment&#34;&gt;// 递归处理左、右两边&lt;/span&gt;
    &lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; (types.isBinaryExpression(left)) {
        left = evaluateBinaryExpression(path.get(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;left&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;));
    }
    &lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; (types.isBinaryExpression(right)) {
        right = evaluateBinaryExpression(path.get(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;right&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;));
    }

    console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt; =================== &lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
    console.log(left);
    console.log(right);

    &lt;span class=&#34;comment&#34;&gt;// 如果左右两边都是数字类型，计算结果并替换&lt;/span&gt;
    &lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; (( isNumericLiteral(left)|| types.isUnaryExpression(left) )  &amp;amp;&amp;amp;  (isNumericLiteral(right) || types.isUnaryExpression(right) ) ) {
        &lt;span class=&#34;keyword&#34;&gt;try&lt;/span&gt; {
            const leftValue = getNodeValue(left);
            const rightValue = getNodeValue(right);
            const evalResult = eval(&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{leftValue} &lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{operator} &lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{rightValue}&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;);

            console.log( &lt;span class=&#34;error&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{leftValue} &lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{operator} &lt;span class=&#34;predefined&#34;&gt;$&lt;/span&gt;{rightValue}&lt;span class=&#34;error&#34;&gt;`&lt;/span&gt; + &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt; = &lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; + evalResult);
            &lt;span class=&#34;comment&#34;&gt;// if(evalResult &amp;gt;=0)&lt;/span&gt;
            path.replaceWith(types.numericLiteral(evalResult));
            &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; path.node;
            &lt;span class=&#34;comment&#34;&gt;// else&lt;/span&gt;
            &lt;span class=&#34;comment&#34;&gt;//    path.replaceWith(types.unaryExpression(&amp;#39;-&amp;#39;, types.numericLiteral(Math.abs(evalResult))));&lt;/span&gt;
        } &lt;span class=&#34;keyword&#34;&gt;catch&lt;/span&gt; (e) {
            console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;Failed to evaluate numeric expression:&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, e);
        }
    }

    &lt;span class=&#34;comment&#34;&gt;// 如果左右两边都是字符串类型，拼接结果并替换&lt;/span&gt;
    &lt;span class=&#34;keyword&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt; (isStringLiteral(left) &amp;amp;&amp;amp; isStringLiteral(right) &amp;amp;&amp;amp; operator === &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;) {
        const leftValue = getNodeValue(left);
        const rightValue = getNodeValue(right);
        const evalResult = leftValue + rightValue;
        path.replaceWith(types.stringLiteral(evalResult));
        &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; path.node;
    }

    &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;predefined-constant&#34;&gt;null&lt;/span&gt;;
}


&lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; traverses_3= {
    BinaryExpression(path) {
        evaluateBinaryExpression(path); &lt;span class=&#34;comment&#34;&gt;// 递归处理&lt;/span&gt;
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;跑一下，搞定&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; a = &lt;span class=&#34;integer&#34;&gt;12&lt;/span&gt;;
&lt;span class=&#34;keyword&#34;&gt;var&lt;/span&gt; b = &lt;span class=&#34;integer&#34;&gt;1&lt;/span&gt;;
console.log(a + b);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_三总结&#34;&gt;三、总结&lt;/h2&gt;&lt;p&gt;js反混淆基本上就是一次模版批量替换的套路，以前我们仅仅依赖查找替换，然后高级一点就是正则替换，现在有了AST解析，就更加灵活了。后面咱们在继续介绍一些高阶的用法。&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Jsastbase/ffshow.webp&#34; alt=&#34;ffshow&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ffshow&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;mark&gt;角弓玉剑，桃花马上春衫，犹忆少年侠气&lt;/mark&gt;&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;: 本文的目的只有一个就是学习更多的逆向技巧和思路，如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担，和本文以及作者没关系，本文涉及到的代码项目可以去 &lt;mark&gt;奋飞的朋友们&lt;/mark&gt; 知识星球自取，欢迎加入知识星球一起学习探讨技术。有问题可以加我wx: &lt;mark&gt;fenfei331&lt;/mark&gt; 讨论下。&lt;/p&gt;&lt;/aside&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ffzsxq.jpg&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;
&lt;p&gt;关注微信公众号，最新技术干货实时推送&lt;/p&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ff330.png&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;&lt;/section&gt;&lt;/div&gt;&lt;footer&gt;&lt;div id=&#34;footer-text&#34;&gt;&lt;br/&gt;Last updated 2026-04-27 18:48:44 +0800&lt;/div&gt;&lt;/footer&gt;
</description>
      
    </item>
    
    <item>
      <title>QBDI使用指南</title>
      <link>http://91fans.com.cn/post/qbdione/</link>
      <pubDate>Mon, 25 Dec 2023 08:40:19 +0800</pubDate>
      
      <guid>http://91fans.com.cn/post/qbdione/</guid>
      
        <description>&lt;meta charset=&#34;UTF-8&#34;/&gt;&lt;meta http-equiv=&#34;X-UA-Compatible&#34; content=&#34;IE=edge&#34;/&gt;&lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;/&gt;&lt;meta name=&#34;generator&#34; content=&#34;Asciidoctor 2.0.20&#34;/&gt;&lt;title&gt;一、目标&lt;/title&gt;&lt;style&gt;/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import &#34;https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700&#34;; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:&#34;\201C&#34; &#34;\201D&#34; &#34;\2018&#34; &#34;\2019&#34;}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock&gt;.content&gt;.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock&gt;.content&gt;.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:&#34; &#34;;display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])&gt;code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre&gt;code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:&#34;[&#34;;padding:0 3px 0 2px}
b.button::after{content:&#34;]&#34;;padding:0 2px 0 3px}
p a&gt;code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:&#34; &#34;;display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header&gt;h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header&gt;h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header&gt;h1:only-child,body.toc2 #header&gt;h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:&#34;\00a0\2013\00a0&#34;}
#header .details br+span.author::before{content:&#34;\00a0\22c5\00a0&#34;;color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:&#34;\00a0|\00a0&#34;}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:&#34;\00a0&#34;}
#content&gt;h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc&gt;ul{margin-left:.125em}
#toc ul.sectlevel0&gt;li&gt;a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2&gt;ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2&gt;ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc&gt;:first-child{margin-top:0}
#content #toc&gt;:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1&gt;a.anchor,h2&gt;a.anchor,h3&gt;a.anchor,#toctitle&gt;a.anchor,.sidebarblock&gt;.content&gt;.title&gt;a.anchor,h4&gt;a.anchor,h5&gt;a.anchor,h6&gt;a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1&gt;a.anchor::before,h2&gt;a.anchor::before,h3&gt;a.anchor::before,#toctitle&gt;a.anchor::before,.sidebarblock&gt;.content&gt;.title&gt;a.anchor::before,h4&gt;a.anchor::before,h5&gt;a.anchor::before,h6&gt;a.anchor::before{content:&#34;\00A7&#34;;font-size:.85em;display:block;padding-top:.1em}
#content h1:hover&gt;a.anchor,#content h1&gt;a.anchor:hover,h2:hover&gt;a.anchor,h2&gt;a.anchor:hover,h3:hover&gt;a.anchor,#toctitle:hover&gt;a.anchor,.sidebarblock&gt;.content&gt;.title:hover&gt;a.anchor,h3&gt;a.anchor:hover,#toctitle&gt;a.anchor:hover,.sidebarblock&gt;.content&gt;.title&gt;a.anchor:hover,h4:hover&gt;a.anchor,h4&gt;a.anchor:hover,h5:hover&gt;a.anchor,h5&gt;a.anchor:hover,h6:hover&gt;a.anchor,h6&gt;a.anchor:hover{visibility:visible}
#content h1&gt;a.link,h2&gt;a.link,h3&gt;a.link,#toctitle&gt;a.link,.sidebarblock&gt;.content&gt;.title&gt;a.link,h4&gt;a.link,h5&gt;a.link,h6&gt;a.link{color:#ba3925;text-decoration:none}
#content h1&gt;a.link:hover,h2&gt;a.link:hover,h3&gt;a.link:hover,#toctitle&gt;a.link:hover,.sidebarblock&gt;.content&gt;.title&gt;a.link:hover,h4&gt;a.link:hover,h5&gt;a.link:hover,h6&gt;a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details&gt;summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details&gt;summary::-webkit-details-marker{display:none}
details&gt;summary::before{content:&#34;&#34;;border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]&gt;summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details&gt;summary::after{content:&#34;&#34;;width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{text-rendering:optimizeLegibility;text-align:left;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content&gt;caption.title{white-space:nowrap;width:0}
.paragraph.lead&gt;p,#preamble&gt;.sectionbody&gt;[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock&gt;table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock&gt;table td.icon{text-align:center;width:80px}
.admonitionblock&gt;table td.icon img{max-width:none}
.admonitionblock&gt;table td.icon .title{font-weight:bold;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;text-transform:uppercase}
.admonitionblock&gt;table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock&gt;table td.content&gt;:last-child&gt;:last-child{margin-bottom:0}
.exampleblock&gt;.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock&gt;.content&gt;.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock&gt;.content&gt;:first-child,.sidebarblock&gt;.content&gt;:first-child{margin-top:0}
.exampleblock&gt;.content&gt;:last-child,.exampleblock&gt;.content&gt;:last-child&gt;:last-child,.exampleblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child&gt;:last-child,.sidebarblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child{margin-bottom:0}
.literalblock pre,.listingblock&gt;.content&gt;pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:1em}}
.literalblock pre,.listingblock&gt;.content&gt;pre:not(.highlight),.listingblock&gt;.content&gt;pre[class=highlight],.listingblock&gt;.content&gt;pre[class^=&#34;highlight &#34;]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock&gt;.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:&#34;$&#34;}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs&gt;code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)&gt;.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:&#34;\201c&#34;;float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote&gt;.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract&gt;.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt&gt;blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock&gt;.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock&gt;.content&gt;:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all&gt;*&gt;tr&gt;*{border-width:1px}
table.grid-cols&gt;*&gt;tr&gt;*{border-width:0 1px}
table.grid-rows&gt;*&gt;tr&gt;*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none&gt;colgroup+*&gt;:first-child&gt;*,table.frame-sides&gt;colgroup+*&gt;:first-child&gt;*{border-top-width:0}
table.frame-none&gt;:last-child&gt;:last-child&gt;*,table.frame-sides&gt;:last-child&gt;:last-child&gt;*{border-bottom-width:0}
table.frame-none&gt;*&gt;tr&gt;:first-child,table.frame-ends&gt;*&gt;tr&gt;:first-child{border-left-width:0}
table.frame-none&gt;*&gt;tr&gt;:last-child,table.frame-ends&gt;*&gt;tr&gt;:last-child{border-right-width:0}
table.stripes-all&gt;*&gt;tr,table.stripes-odd&gt;*&gt;tr:nth-of-type(odd),table.stripes-even&gt;*&gt;tr:nth-of-type(even),table.stripes-hover&gt;*&gt;tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock&gt;code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child&gt;:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li&gt;p:empty:only-child::before{content:&#34;&#34;;display:inline-block}
ul.checklist&gt;li&gt;p:first-child{margin-left:-1em}
ul.checklist&gt;li&gt;p:first-child&gt;.fa-square-o:first-child,ul.checklist&gt;li&gt;p:first-child&gt;.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist&gt;li&gt;p:first-child&gt;input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline&gt;li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist&gt;table,.colist&gt;table{border:0;background:none}
.hdlist&gt;table&gt;tbody&gt;tr,.colist&gt;table&gt;tbody&gt;tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock&gt;.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb&gt;.title,.imageblock.th&gt;.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon&gt;.fa{cursor:default}
a span.icon&gt;.fa{cursor:inherit}
.admonitionblock td.icon [class^=&#34;fa icon-&#34;]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:&#34;\f05a&#34;;color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:&#34;\f0eb&#34;;text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:&#34;\f071&#34;;color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:&#34;\f06d&#34;;color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:&#34;\f06a&#34;;color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock&gt;.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^=&#34;#&#34;],a[href^=&#34;mailto:&#34;]{text-decoration:none!important}
a[href^=&#34;http:&#34;]:not(.bare)::after,a[href^=&#34;https:&#34;]:not(.bare)::after{content:&#34;(&#34; attr(href) &#34;)&#34;;display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:&#34; (&#34; attr(title) &#34;)&#34;}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock&gt;.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header&gt;h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1&gt;h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header&gt;h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}&lt;/style&gt;
&lt;style&gt;
/*! Stylesheet for CodeRay to loosely match GitHub themes | MIT License */
pre.CodeRay{background:#f7f7f8}
.CodeRay .line-numbers{border-right:1px solid;opacity:.35;padding:0 .5em 0 0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.CodeRay span.line-numbers{display:inline-block;margin-right:.75em}
.CodeRay .line-numbers strong{color:#000}
table.CodeRay{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.CodeRay td{vertical-align:top;line-height:inherit}
table.CodeRay td.line-numbers{text-align:right}
table.CodeRay td.code{padding:0 0 0 .75em}
.CodeRay .debug{color:#fff!important;background:navy!important}
.CodeRay .annotation{color:#007}
.CodeRay .attribute-name{color:navy}
.CodeRay .attribute-value{color:#700}
.CodeRay .binary{color:#509}
.CodeRay .comment{color:#998;font-style:italic}
.CodeRay .char{color:#04d}
.CodeRay .char .content{color:#04d}
.CodeRay .char .delimiter{color:#039}
.CodeRay .class{color:#458;font-weight:bold}
.CodeRay .complex{color:#a08}
.CodeRay .constant,.CodeRay .predefined-constant{color:teal}
.CodeRay .color{color:#099}
.CodeRay .class-variable{color:#369}
.CodeRay .decorator{color:#b0b}
.CodeRay .definition{color:#099}
.CodeRay .delimiter{color:#000}
.CodeRay .doc{color:#970}
.CodeRay .doctype{color:#34b}
.CodeRay .doc-string{color:#d42}
.CodeRay .escape{color:#666}
.CodeRay .entity{color:#800}
.CodeRay .error{color:#808}
.CodeRay .exception{color:inherit}
.CodeRay .filename{color:#099}
.CodeRay .function{color:#900;font-weight:bold}
.CodeRay .global-variable{color:teal}
.CodeRay .hex{color:#058}
.CodeRay .integer,.CodeRay .float{color:#099}
.CodeRay .include{color:#555}
.CodeRay .inline{color:#000}
.CodeRay .inline .inline{background:#ccc}
.CodeRay .inline .inline .inline{background:#bbb}
.CodeRay .inline .inline-delimiter{color:#d14}
.CodeRay .inline-delimiter{color:#d14}
.CodeRay .important{color:#555;font-weight:bold}
.CodeRay .interpreted{color:#b2b}
.CodeRay .instance-variable{color:teal}
.CodeRay .label{color:#970}
.CodeRay .local-variable{color:#963}
.CodeRay .octal{color:#40e}
.CodeRay .predefined{color:#369}
.CodeRay .preprocessor{color:#579}
.CodeRay .pseudo-class{color:#555}
.CodeRay .directive{font-weight:bold}
.CodeRay .type{font-weight:bold}
.CodeRay .predefined-type{color:inherit}
.CodeRay .reserved,.CodeRay .keyword{color:#000;font-weight:bold}
.CodeRay .key{color:#808}
.CodeRay .key .delimiter{color:#606}
.CodeRay .key .char{color:#80f}
.CodeRay .value{color:#088}
.CodeRay .regexp .delimiter{color:#808}
.CodeRay .regexp .content{color:#808}
.CodeRay .regexp .modifier{color:#808}
.CodeRay .regexp .char{color:#d14}
.CodeRay .regexp .function{color:#404;font-weight:bold}
.CodeRay .string{color:#d20}
.CodeRay .string .string .string{background:#ffd0d0}
.CodeRay .string .content{color:#d14}
.CodeRay .string .char{color:#d14}
.CodeRay .string .delimiter{color:#d14}
.CodeRay .shell{color:#d14}
.CodeRay .shell .delimiter{color:#d14}
.CodeRay .symbol{color:#990073}
.CodeRay .symbol .content{color:#a60}
.CodeRay .symbol .delimiter{color:#630}
.CodeRay .tag{color:teal}
.CodeRay .tag-special{color:#d70}
.CodeRay .variable{color:#036}
.CodeRay .insert{background:#afa}
.CodeRay .delete{background:#faa}
.CodeRay .change{color:#aaf;background:#007}
.CodeRay .head{color:#f8f;background:#505}
.CodeRay .insert .insert{color:#080}
.CodeRay .delete .delete{color:#800}
.CodeRay .change .change{color:#66f}
.CodeRay .head .head{color:#f4f}
&lt;/style&gt;&lt;/head&gt;&lt;body class=&#34;article&#34;&gt;&lt;header&gt;&lt;/header&gt;&lt;div id=&#34;content&#34;&gt;&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_一目标&#34;&gt;一、目标&lt;/h2&gt;&lt;p&gt;今天给大家介绍一个新朋友, &lt;a href=&#34;https://qbdi.quarkslab.com&#34;&gt;QBDI&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;它可以快速集成到你的frida脚本里面来进行汇编级的Trace&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_二步骤&#34;&gt;二、步骤&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_安装&#34;&gt;安装&lt;/h3&gt;&lt;p&gt;在Androd上使用QBDI非常方便,先去官网下载一个最新版本&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/QBDI/QBDI/releases/download/v0.10.0/QBDI-0.10.0-android-AARCH64.tar.gz&#34;&gt;https://github.com/QBDI/QBDI/releases/download/v0.10.0/QBDI-0.10.0-android-AARCH64.tar.gz&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;针对我们Frida的使用,主要是里面的两个文件 &lt;mark&gt;libQBDI.so&lt;/mark&gt; 和 &lt;mark&gt;frida-qbdi.js&lt;/mark&gt; , 前一个是注入库,后一个是js的封装&lt;/p&gt;
&lt;p&gt;然后把 &lt;mark&gt;libQBDI.so&lt;/mark&gt; 放到 /data/local/tmp 目录&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;adb push libQBDI.so /data/local/tmp&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_使用&#34;&gt;使用&lt;/h3&gt;&lt;p&gt;第一种用法是主动调用目标函数来Trace&lt;/p&gt;
&lt;p&gt;由于需要加载 &lt;mark&gt;frida-qbdi.js&lt;/mark&gt; 模块,所以这里我们需要用到frida的模块开发。 通常的方法是 采用大胡子的 &lt;a href=&#34;https://github.com/oleavr/frida-agent-example&#34;&gt;https://github.com/oleavr/frida-agent-example&lt;/a&gt;  一个使用TS的模版。&lt;/p&gt;
&lt;p&gt;不过懒得再去学一个TS语言了，所以我们今天用另外一个办法&lt;/p&gt;
&lt;figure class=&#34;listing-block&#34;&gt;&lt;figcaption&gt;index.js&lt;/figcaption&gt;
&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;&lt;span class=&#34;reserved&#34;&gt;import&lt;/span&gt; {
    VM,
    InstPosition,
    VMAction,
    Options,
    MemoryAccessType,
    AnalysisType,
    RegisterAccessType,
    OperandType,
    SyncDirection
} from &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;./frida-qbdi.js&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;;

.... call fridaQBDI&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;然后使用 frida-compile 编译&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;comment&#34;&gt;// 编译&lt;/span&gt;
frida-compile -w index.js -o frida-qbdi-agent.js
&lt;span class=&#34;comment&#34;&gt;// 启动Hook&lt;/span&gt;
frida -Uf com.example.myapplication --runtime=v8 -l frida-qbdi-agent.js&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_主动调用&#34;&gt;主动调用&lt;/h3&gt;&lt;p&gt;考虑apk中的so里面有一个addTestFenfei函数&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;c&#34;&gt;&lt;span class=&#34;directive&#34;&gt;extern&lt;/span&gt; &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;C&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; &lt;span class=&#34;predefined-type&#34;&gt;int&lt;/span&gt; addTestFenfei(){
    &lt;span class=&#34;predefined-type&#34;&gt;int&lt;/span&gt; a = &lt;span class=&#34;integer&#34;&gt;2&lt;/span&gt;;
    &lt;span class=&#34;predefined-type&#34;&gt;int&lt;/span&gt; b = &lt;span class=&#34;integer&#34;&gt;3&lt;/span&gt;;
    &lt;span class=&#34;predefined-type&#34;&gt;int&lt;/span&gt; c = a ^ b;
    c = c + a + b;
    LOGD(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;addTestFenfei : %d&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, c);
    &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; c;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;我们在warp_vm_run.js里面就可以用下面的方式来主动调用&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;&lt;span class=&#34;comment&#34;&gt;/**
 * warp_vm_run的函数定义不要修改
 * @param {*} vm_run_func   会调用qbdi的vm.call
 * @param {*} log_file_path 日志文件的路径
 */&lt;/span&gt;
&lt;span class=&#34;reserved&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;default&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;function&#34;&gt;warp_vm_run&lt;/span&gt;(vm_run_func, log_file_path) {
    let libnative_name = &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;libmyapplication.so&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;; &lt;span class=&#34;comment&#34;&gt;// 替换为你的.so库的名称&lt;/span&gt;
    let func_name = &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;addTestFenfei&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;;

    let libnative_base = Process.findModuleByName(libnative_name).base;
    console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;warp_vm_run libnative_base 0x&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; +  libnative_base.toString(&lt;span class=&#34;integer&#34;&gt;16&lt;/span&gt;));

    &lt;span class=&#34;comment&#34;&gt;// 获取native方法地址&lt;/span&gt;
    const func_addr = Module.findExportByName(libnative_name, func_name);
    console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;func_addr = &lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; + func_addr);

    let ret = vm_run_func(&lt;span class=&#34;predefined-constant&#34;&gt;null&lt;/span&gt;,func_addr, [], log_file_path,&lt;span class=&#34;predefined-constant&#34;&gt;false&lt;/span&gt;);
        console.log(ret);
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;然后挂上心爱的frida执行&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;Failed to load /data/local/tmp/libQBDI.so (dlopen failed: couldn&lt;span class=&#34;char&#34;&gt;&amp;#39;t&lt;/span&gt; map &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;/data/local/tmp/libQBDI.so&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; segment &lt;span class=&#34;integer&#34;&gt;1&lt;/span&gt;: Permission denied)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;报错了，木有权限，  那就给它&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;preprocessor&#34;&gt;#setenforce&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;每一行的 执行代码，寄存器变化和内存读写就都打印出来了&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;start vm.call ===
&lt;span class=&#34;hex&#34;&gt;0x77d5661b00&lt;/span&gt; [libmyapplication.so!&lt;span class=&#34;hex&#34;&gt;0x1eb00&lt;/span&gt;]         stp        x29, x30, [sp, &lt;span class=&#34;preprocessor&#34;&gt;#&lt;/span&gt;-&lt;span class=&#34;integer&#34;&gt;16&lt;/span&gt;]!         r[FP=&lt;span class=&#34;hex&#34;&gt;0x77d6b03100&lt;/span&gt; LR=&lt;span class=&#34;hex&#34;&gt;0x2a&lt;/span&gt; SP=&lt;span class=&#34;hex&#34;&gt;0x77d6b03080&lt;/span&gt;]   w[SP=&lt;span class=&#34;hex&#34;&gt;0x77d6b03070&lt;/span&gt;]
memory write at &lt;span class=&#34;integer&#34;&gt;77&lt;/span&gt;d6b03070, data size = &lt;span class=&#34;integer&#34;&gt;8&lt;/span&gt;, data value = &lt;span class=&#34;integer&#34;&gt;77&lt;/span&gt;d6b03100
memory write at &lt;span class=&#34;integer&#34;&gt;77&lt;/span&gt;d6b03078, data size = &lt;span class=&#34;integer&#34;&gt;8&lt;/span&gt;, data value = &lt;span class=&#34;integer&#34;&gt;2&lt;/span&gt;a
&lt;span class=&#34;hex&#34;&gt;0x77d5661b04&lt;/span&gt; [libmyapplication.so!&lt;span class=&#34;hex&#34;&gt;0x1eb04&lt;/span&gt;]         mov        x29, sp         r[SP=&lt;span class=&#34;hex&#34;&gt;0x77d6b03070&lt;/span&gt;]   w[FP=&lt;span class=&#34;hex&#34;&gt;0x77d6b03070&lt;/span&gt;]
&lt;span class=&#34;hex&#34;&gt;0x77d5661b08&lt;/span&gt; [libmyapplication.so!&lt;span class=&#34;hex&#34;&gt;0x1eb08&lt;/span&gt;]         adrp        x8, &lt;span class=&#34;preprocessor&#34;&gt;#172032&lt;/span&gt;          w[X8=&lt;span class=&#34;hex&#34;&gt;0x77d568b000&lt;/span&gt;]
&lt;span class=&#34;hex&#34;&gt;0x77d5661b0c&lt;/span&gt; [libmyapplication.so!&lt;span class=&#34;hex&#34;&gt;0x1eb0c&lt;/span&gt;]         ldrb        w8, [x8, &lt;span class=&#34;preprocessor&#34;&gt;#3912&lt;/span&gt;]         r[X8=&lt;span class=&#34;hex&#34;&gt;0x77d568b000&lt;/span&gt;]   w[W8=&lt;span class=&#34;hex&#34;&gt;0x1&lt;/span&gt;]
memory read at &lt;span class=&#34;integer&#34;&gt;77&lt;/span&gt;d568bf48, data size = &lt;span class=&#34;integer&#34;&gt;1&lt;/span&gt;, data value = &lt;span class=&#34;integer&#34;&gt;1&lt;/span&gt;
&lt;span class=&#34;hex&#34;&gt;0x77d5661b10&lt;/span&gt; [libmyapplication.so!&lt;span class=&#34;hex&#34;&gt;0x1eb10&lt;/span&gt;]         cbz        w8, &lt;span class=&#34;preprocessor&#34;&gt;#32&lt;/span&gt;         r[W8=&lt;span class=&#34;hex&#34;&gt;0x1&lt;/span&gt;]
&lt;span class=&#34;hex&#34;&gt;0x77d5661b14&lt;/span&gt; [libmyapplication.so!&lt;span class=&#34;hex&#34;&gt;0x1eb14&lt;/span&gt;]         adrp        x1, &lt;span class=&#34;preprocessor&#34;&gt;#&lt;/span&gt;-&lt;span class=&#34;integer&#34;&gt;40960&lt;/span&gt;          w[X1=&lt;span class=&#34;hex&#34;&gt;0x77d5657000&lt;/span&gt;]
&lt;span class=&#34;hex&#34;&gt;0x77d5661b18&lt;/span&gt; [libmyapplication.so!&lt;span class=&#34;hex&#34;&gt;0x1eb18&lt;/span&gt;]         adrp        x2, &lt;span class=&#34;preprocessor&#34;&gt;#&lt;/span&gt;-&lt;span class=&#34;integer&#34;&gt;40960&lt;/span&gt;           w[X2=&lt;span class=&#34;hex&#34;&gt;0x77d5657000&lt;/span&gt;]
&lt;span class=&#34;hex&#34;&gt;0x77d5661b1c&lt;/span&gt; [libmyapplication.so!&lt;span class=&#34;hex&#34;&gt;0x1eb1c&lt;/span&gt;]         add        x1, x1, &lt;span class=&#34;preprocessor&#34;&gt;#1895&lt;/span&gt;         r[X1=&lt;span class=&#34;hex&#34;&gt;0x77d5657000&lt;/span&gt;]   w[X1=&lt;span class=&#34;hex&#34;&gt;0x77d5657767&lt;/span&gt;]
&lt;span class=&#34;hex&#34;&gt;0x77d5661b20&lt;/span&gt; [libmyapplication.so!&lt;span class=&#34;hex&#34;&gt;0x1eb20&lt;/span&gt;]         add        x2, x2, &lt;span class=&#34;preprocessor&#34;&gt;#806&lt;/span&gt;         r[X2=&lt;span class=&#34;hex&#34;&gt;0x77d5657000&lt;/span&gt;]   w[X2=&lt;span class=&#34;hex&#34;&gt;0x77d5657326&lt;/span&gt;]
&lt;span class=&#34;hex&#34;&gt;0x77d5661b24&lt;/span&gt; [libmyapplication.so!&lt;span class=&#34;hex&#34;&gt;0x1eb24&lt;/span&gt;]         mov        w0, &lt;span class=&#34;preprocessor&#34;&gt;#3&lt;/span&gt;          w[W0=&lt;span class=&#34;hex&#34;&gt;0x3&lt;/span&gt;]
&lt;span class=&#34;hex&#34;&gt;0x77d5661b28&lt;/span&gt; [libmyapplication.so!&lt;span class=&#34;hex&#34;&gt;0x1eb28&lt;/span&gt;]         mov        w3, &lt;span class=&#34;preprocessor&#34;&gt;#6&lt;/span&gt;          w[W3=&lt;span class=&#34;hex&#34;&gt;0x6&lt;/span&gt;]
&lt;span class=&#34;hex&#34;&gt;0x77d5661b2c&lt;/span&gt; [libmyapplication.so!&lt;span class=&#34;hex&#34;&gt;0x1eb2c&lt;/span&gt;]         bl        &lt;span class=&#34;preprocessor&#34;&gt;#148868&lt;/span&gt;         r[SP=&lt;span class=&#34;hex&#34;&gt;0x77d6b03070&lt;/span&gt;] w[LR=&lt;span class=&#34;hex&#34;&gt;0x77d5661b30&lt;/span&gt;]
&lt;span class=&#34;hex&#34;&gt;0x77d56860b0&lt;/span&gt; [libmyapplication.so!&lt;span class=&#34;hex&#34;&gt;0x430b0&lt;/span&gt;]         adrp        x16, &lt;span class=&#34;preprocessor&#34;&gt;#16384&lt;/span&gt;         w[X16=&lt;span class=&#34;hex&#34;&gt;0x77d568a000&lt;/span&gt;]
&lt;span class=&#34;hex&#34;&gt;0x77d56860b4&lt;/span&gt; [libmyapplication.so!&lt;span class=&#34;hex&#34;&gt;0x430b4&lt;/span&gt;]         ldr        x17, [x16, &lt;span class=&#34;preprocessor&#34;&gt;#3032&lt;/span&gt;]         r[X16=&lt;span class=&#34;hex&#34;&gt;0x77d568a000&lt;/span&gt;] w[X17=&lt;span class=&#34;hex&#34;&gt;0x78cb2dd788&lt;/span&gt;]
memory read at &lt;span class=&#34;integer&#34;&gt;77&lt;/span&gt;d568abd8, data size = &lt;span class=&#34;integer&#34;&gt;8&lt;/span&gt;, data value = &lt;span class=&#34;integer&#34;&gt;78&lt;/span&gt;cb2dd788
&lt;span class=&#34;hex&#34;&gt;0x77d56860b8&lt;/span&gt; [libmyapplication.so!&lt;span class=&#34;hex&#34;&gt;0x430b8&lt;/span&gt;]         add        x16, x16, &lt;span class=&#34;preprocessor&#34;&gt;#3032&lt;/span&gt;         r[X16=&lt;span class=&#34;hex&#34;&gt;0x77d568a000&lt;/span&gt;] w[X16=&lt;span class=&#34;hex&#34;&gt;0x77d568abd8&lt;/span&gt;]
&lt;span class=&#34;hex&#34;&gt;0x77d56860bc&lt;/span&gt; [libmyapplication.so!&lt;span class=&#34;hex&#34;&gt;0x430bc&lt;/span&gt;]         br        x17         r[X17=&lt;span class=&#34;hex&#34;&gt;0x78cb2dd788&lt;/span&gt;]
&lt;span class=&#34;hex&#34;&gt;0x77d5661b30&lt;/span&gt; [libmyapplication.so!&lt;span class=&#34;hex&#34;&gt;0x1eb30&lt;/span&gt;]         mov        w0, &lt;span class=&#34;preprocessor&#34;&gt;#6&lt;/span&gt;         w[W0=&lt;span class=&#34;hex&#34;&gt;0x6&lt;/span&gt;]
&lt;span class=&#34;hex&#34;&gt;0x77d5661b34&lt;/span&gt; [libmyapplication.so!&lt;span class=&#34;hex&#34;&gt;0x1eb34&lt;/span&gt;]         ldp        x29, x30, [sp], &lt;span class=&#34;preprocessor&#34;&gt;#16&lt;/span&gt;         r[SP=&lt;span class=&#34;hex&#34;&gt;0x77d6b03070&lt;/span&gt;]  w[FP=&lt;span class=&#34;hex&#34;&gt;0x77d6b03100&lt;/span&gt; LR=&lt;span class=&#34;hex&#34;&gt;0x2a&lt;/span&gt; SP=&lt;span class=&#34;hex&#34;&gt;0x77d6b03080&lt;/span&gt;]
memory read at &lt;span class=&#34;integer&#34;&gt;77&lt;/span&gt;d6b03070, data size = &lt;span class=&#34;integer&#34;&gt;8&lt;/span&gt;, data value = &lt;span class=&#34;integer&#34;&gt;77&lt;/span&gt;d6b03100
memory read at &lt;span class=&#34;integer&#34;&gt;77&lt;/span&gt;d6b03078, data size = &lt;span class=&#34;integer&#34;&gt;8&lt;/span&gt;, data value = &lt;span class=&#34;integer&#34;&gt;2&lt;/span&gt;a
&lt;span class=&#34;hex&#34;&gt;0x77d5661b38&lt;/span&gt; [libmyapplication.so!&lt;span class=&#34;hex&#34;&gt;0x1eb38&lt;/span&gt;]         ret         r[LR=&lt;span class=&#34;hex&#34;&gt;0x2a&lt;/span&gt;]
cost is &lt;span class=&#34;float&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;float&#34;&gt;.063&lt;/span&gt;s
&lt;span class=&#34;hex&#34;&gt;0x6&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;如果要调用 有参数的函数，可以这么来做&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;js&#34;&gt;let ret = vm_run_func(&lt;span class=&#34;predefined-constant&#34;&gt;null&lt;/span&gt;,func_addr, [&lt;span class=&#34;integer&#34;&gt;2&lt;/span&gt;,&lt;span class=&#34;integer&#34;&gt;3&lt;/span&gt;], log_file_path);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_hook替换&#34;&gt;Hook替换&lt;/h3&gt;&lt;p&gt;有些时候，我们不想构造参数去主动调用函数，而是想在app执行的过程中，去hook替换目标函数，然后打印它的真实流程。&lt;/p&gt;
&lt;p&gt;这里要注意的就是两点， 1是替换，2是更新上下文，也就是更新寄存器的值&lt;/p&gt;
&lt;p&gt;在traceCodeQBDI.js文件 vm_run函数里面，&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;comment&#34;&gt;// postSync 是否同步回来&lt;/span&gt;
function vm_run(ctx,func_ptr, args, log_file_path,postSync) {
    let start_time = &lt;span class=&#34;keyword&#34;&gt;new&lt;/span&gt; Date().getTime();

    let vm = &lt;span class=&#34;keyword&#34;&gt;new&lt;/span&gt; VM();
    vm.setOptions(Options.OPT_DISABLE_LOCAL_MONITOR | Options.OPT_BYPASS_PAUTH | Options.OPT_ENABLE_BTI)

    var state = vm.getGPRState();
    vm.allocateVirtualStack(state, &lt;span class=&#34;hex&#34;&gt;0x100000&lt;/span&gt;);

    &lt;span class=&#34;comment&#34;&gt;// 同步寄存器&lt;/span&gt;
    &lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt;(postSync){
        console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;==== synchronizeContext FRIDA_TO_QBDI &lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
        state.synchronizeContext(ctx,SyncDirection.FRIDA_TO_QBDI);
    }

    ......

    &lt;span class=&#34;comment&#34;&gt;// 同步寄存器&lt;/span&gt;
    &lt;span class=&#34;keyword&#34;&gt;if&lt;/span&gt;(postSync){
        console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;synchronizeContext QBDI_TO_FRIDA ====&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
        state.synchronizeContext(ctx,SyncDirection.QBDI_TO_FRIDA);
    }
    &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; ret;

}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;然后在warp_vm_run中做替换&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;default&lt;/span&gt; function warp_vm_run(vm_run_func, log_file_path) {
    let libnative_name = &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;libmyapplication.so&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;; &lt;span class=&#34;comment&#34;&gt;// 替换为你的.so库的名称&lt;/span&gt;

    let libnative_base = Process.findModuleByName(libnative_name).base;
    console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;warp_vm_run libnative_base 0x&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; +  libnative_base.toString(&lt;span class=&#34;integer&#34;&gt;16&lt;/span&gt;));

    &lt;span class=&#34;comment&#34;&gt;// hook替换&lt;/span&gt;
    &lt;span class=&#34;comment&#34;&gt;//*&lt;/span&gt;
    let env = Java.vm.tryGetEnv();
    console.log(JSON.stringify(env));

       let func_name = &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;Java_com_example_myapplication_MainActivity_FFTestAdd&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;;
       let func_addr = Module.findExportByName(libnative_name, func_name);
    console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;Hook func_addr = &lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; + func_addr);

    Interceptor.replace(func_addr,&lt;span class=&#34;keyword&#34;&gt;new&lt;/span&gt; NativeCallback(function (vmEnv,vmContext,a,b){
        console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt; ============== &lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);
        console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;[+] &lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; + func_addr.sub(libnative_base) + &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; + a + &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;, &lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; + b + &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;) called&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;);

        &lt;span class=&#34;comment&#34;&gt;// 恢复被替换的函数入口&lt;/span&gt;
        Interceptor.revert(func_addr);
        Interceptor.flush();
        console.log(env.handle);

        &lt;span class=&#34;comment&#34;&gt;// // qbdi执行&lt;/span&gt;
        var retVal = vm_run_func(&lt;span class=&#34;local-variable&#34;&gt;this&lt;/span&gt;.context, func_addr, [vmEnv,vmContext,a,b],log_file_path,&lt;span class=&#34;predefined-constant&#34;&gt;true&lt;/span&gt;);
        &lt;span class=&#34;comment&#34;&gt;// 继续替换吧&lt;/span&gt;
        warp_vm_run(vm_run_func,log_file_path);

        &lt;span class=&#34;directive&#34;&gt;const&lt;/span&gt; resultStr = env.stringFromJni(retVal);
        console.log(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;Result: &lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; + resultStr);

        &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; retVal;
    }, &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;pointer&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, [&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;pointer&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;pointer&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;,&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;,&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;]));
    &lt;span class=&#34;comment&#34;&gt;// */&lt;/span&gt;


}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这样执行就可以打印出实际app跑的时候的指令了。&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;函数的参数中如果有 jobject MainActivity /* this */ 之类的参数， 不管是主动调用还是hook调用，在函数返回的时候都会崩溃。还没有找到原因 :(&lt;/p&gt;&lt;/aside&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_三总结&#34;&gt;三、总结&lt;/h2&gt;&lt;p&gt;指令级的Trace还有很多应用场景，比如只打印XOR指令，或者只监控SVC指令。&lt;/p&gt;
&lt;p&gt;参考资料&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/lasting-yang/frida-qbdi-tracer&#34;&gt;https://github.com/lasting-yang/frida-qbdi-tracer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://blog.quarkslab.com/why-are-frida-and-qbdi-a-great-blend-on-android.html&#34;&gt;https://blog.quarkslab.com/why-are-frida-and-qbdi-a-great-blend-on-android.html&lt;/a&gt;&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Qbdione/ffshow.webp&#34; alt=&#34;ffshow&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ffshow&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;mark&gt;当星星变成星空，梦想也就近在咫尺了&lt;/mark&gt;&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;: 本文的目的只有一个就是学习更多的逆向技巧和思路，如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担，和本文以及作者没关系，本文涉及到的代码项目可以去 &lt;mark&gt;奋飞的朋友们&lt;/mark&gt; 知识星球自取，欢迎加入知识星球一起学习探讨技术。有问题可以加我wx: &lt;mark&gt;fenfei331&lt;/mark&gt; 讨论下。&lt;/p&gt;&lt;/aside&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ffzsxq.jpg&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;
&lt;p&gt;关注微信公众号，最新技术干货实时推送&lt;/p&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ff330.png&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;&lt;/section&gt;&lt;/div&gt;&lt;footer&gt;&lt;div id=&#34;footer-text&#34;&gt;&lt;br/&gt;Last updated 2026-04-27 18:48:45 +0800&lt;/div&gt;&lt;/footer&gt;
</description>
      
    </item>
    
    <item>
      <title>代码还原小试牛刀(二)：魔改的MD5</title>
      <link>http://91fans.com.cn/post/md5two/</link>
      <pubDate>Mon, 13 Mar 2023 15:48:52 +0800</pubDate>
      
      <guid>http://91fans.com.cn/post/md5two/</guid>
      
        <description>&lt;meta charset=&#34;UTF-8&#34;/&gt;&lt;meta http-equiv=&#34;X-UA-Compatible&#34; content=&#34;IE=edge&#34;/&gt;&lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;/&gt;&lt;meta name=&#34;generator&#34; content=&#34;Asciidoctor 2.0.20&#34;/&gt;&lt;title&gt;一、目标&lt;/title&gt;&lt;style&gt;/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import &#34;https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700&#34;; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:&#34;\201C&#34; &#34;\201D&#34; &#34;\2018&#34; &#34;\2019&#34;}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock&gt;.content&gt;.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock&gt;.content&gt;.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:&#34; &#34;;display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])&gt;code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre&gt;code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:&#34;[&#34;;padding:0 3px 0 2px}
b.button::after{content:&#34;]&#34;;padding:0 2px 0 3px}
p a&gt;code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:&#34; &#34;;display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header&gt;h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header&gt;h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header&gt;h1:only-child,body.toc2 #header&gt;h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:&#34;\00a0\2013\00a0&#34;}
#header .details br+span.author::before{content:&#34;\00a0\22c5\00a0&#34;;color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:&#34;\00a0|\00a0&#34;}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:&#34;\00a0&#34;}
#content&gt;h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc&gt;ul{margin-left:.125em}
#toc ul.sectlevel0&gt;li&gt;a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2&gt;ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2&gt;ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc&gt;:first-child{margin-top:0}
#content #toc&gt;:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1&gt;a.anchor,h2&gt;a.anchor,h3&gt;a.anchor,#toctitle&gt;a.anchor,.sidebarblock&gt;.content&gt;.title&gt;a.anchor,h4&gt;a.anchor,h5&gt;a.anchor,h6&gt;a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1&gt;a.anchor::before,h2&gt;a.anchor::before,h3&gt;a.anchor::before,#toctitle&gt;a.anchor::before,.sidebarblock&gt;.content&gt;.title&gt;a.anchor::before,h4&gt;a.anchor::before,h5&gt;a.anchor::before,h6&gt;a.anchor::before{content:&#34;\00A7&#34;;font-size:.85em;display:block;padding-top:.1em}
#content h1:hover&gt;a.anchor,#content h1&gt;a.anchor:hover,h2:hover&gt;a.anchor,h2&gt;a.anchor:hover,h3:hover&gt;a.anchor,#toctitle:hover&gt;a.anchor,.sidebarblock&gt;.content&gt;.title:hover&gt;a.anchor,h3&gt;a.anchor:hover,#toctitle&gt;a.anchor:hover,.sidebarblock&gt;.content&gt;.title&gt;a.anchor:hover,h4:hover&gt;a.anchor,h4&gt;a.anchor:hover,h5:hover&gt;a.anchor,h5&gt;a.anchor:hover,h6:hover&gt;a.anchor,h6&gt;a.anchor:hover{visibility:visible}
#content h1&gt;a.link,h2&gt;a.link,h3&gt;a.link,#toctitle&gt;a.link,.sidebarblock&gt;.content&gt;.title&gt;a.link,h4&gt;a.link,h5&gt;a.link,h6&gt;a.link{color:#ba3925;text-decoration:none}
#content h1&gt;a.link:hover,h2&gt;a.link:hover,h3&gt;a.link:hover,#toctitle&gt;a.link:hover,.sidebarblock&gt;.content&gt;.title&gt;a.link:hover,h4&gt;a.link:hover,h5&gt;a.link:hover,h6&gt;a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details&gt;summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details&gt;summary::-webkit-details-marker{display:none}
details&gt;summary::before{content:&#34;&#34;;border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]&gt;summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details&gt;summary::after{content:&#34;&#34;;width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{text-rendering:optimizeLegibility;text-align:left;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content&gt;caption.title{white-space:nowrap;width:0}
.paragraph.lead&gt;p,#preamble&gt;.sectionbody&gt;[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock&gt;table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock&gt;table td.icon{text-align:center;width:80px}
.admonitionblock&gt;table td.icon img{max-width:none}
.admonitionblock&gt;table td.icon .title{font-weight:bold;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;text-transform:uppercase}
.admonitionblock&gt;table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock&gt;table td.content&gt;:last-child&gt;:last-child{margin-bottom:0}
.exampleblock&gt;.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock&gt;.content&gt;.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock&gt;.content&gt;:first-child,.sidebarblock&gt;.content&gt;:first-child{margin-top:0}
.exampleblock&gt;.content&gt;:last-child,.exampleblock&gt;.content&gt;:last-child&gt;:last-child,.exampleblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child&gt;:last-child,.sidebarblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child{margin-bottom:0}
.literalblock pre,.listingblock&gt;.content&gt;pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:1em}}
.literalblock pre,.listingblock&gt;.content&gt;pre:not(.highlight),.listingblock&gt;.content&gt;pre[class=highlight],.listingblock&gt;.content&gt;pre[class^=&#34;highlight &#34;]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock&gt;.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:&#34;$&#34;}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs&gt;code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)&gt;.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:&#34;\201c&#34;;float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote&gt;.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract&gt;.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt&gt;blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock&gt;.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock&gt;.content&gt;:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all&gt;*&gt;tr&gt;*{border-width:1px}
table.grid-cols&gt;*&gt;tr&gt;*{border-width:0 1px}
table.grid-rows&gt;*&gt;tr&gt;*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none&gt;colgroup+*&gt;:first-child&gt;*,table.frame-sides&gt;colgroup+*&gt;:first-child&gt;*{border-top-width:0}
table.frame-none&gt;:last-child&gt;:last-child&gt;*,table.frame-sides&gt;:last-child&gt;:last-child&gt;*{border-bottom-width:0}
table.frame-none&gt;*&gt;tr&gt;:first-child,table.frame-ends&gt;*&gt;tr&gt;:first-child{border-left-width:0}
table.frame-none&gt;*&gt;tr&gt;:last-child,table.frame-ends&gt;*&gt;tr&gt;:last-child{border-right-width:0}
table.stripes-all&gt;*&gt;tr,table.stripes-odd&gt;*&gt;tr:nth-of-type(odd),table.stripes-even&gt;*&gt;tr:nth-of-type(even),table.stripes-hover&gt;*&gt;tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock&gt;code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child&gt;:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li&gt;p:empty:only-child::before{content:&#34;&#34;;display:inline-block}
ul.checklist&gt;li&gt;p:first-child{margin-left:-1em}
ul.checklist&gt;li&gt;p:first-child&gt;.fa-square-o:first-child,ul.checklist&gt;li&gt;p:first-child&gt;.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist&gt;li&gt;p:first-child&gt;input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline&gt;li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist&gt;table,.colist&gt;table{border:0;background:none}
.hdlist&gt;table&gt;tbody&gt;tr,.colist&gt;table&gt;tbody&gt;tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock&gt;.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb&gt;.title,.imageblock.th&gt;.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon&gt;.fa{cursor:default}
a span.icon&gt;.fa{cursor:inherit}
.admonitionblock td.icon [class^=&#34;fa icon-&#34;]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:&#34;\f05a&#34;;color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:&#34;\f0eb&#34;;text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:&#34;\f071&#34;;color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:&#34;\f06d&#34;;color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:&#34;\f06a&#34;;color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock&gt;.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^=&#34;#&#34;],a[href^=&#34;mailto:&#34;]{text-decoration:none!important}
a[href^=&#34;http:&#34;]:not(.bare)::after,a[href^=&#34;https:&#34;]:not(.bare)::after{content:&#34;(&#34; attr(href) &#34;)&#34;;display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:&#34; (&#34; attr(title) &#34;)&#34;}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock&gt;.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header&gt;h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1&gt;h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header&gt;h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}&lt;/style&gt;
&lt;style&gt;
/*! Stylesheet for CodeRay to loosely match GitHub themes | MIT License */
pre.CodeRay{background:#f7f7f8}
.CodeRay .line-numbers{border-right:1px solid;opacity:.35;padding:0 .5em 0 0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.CodeRay span.line-numbers{display:inline-block;margin-right:.75em}
.CodeRay .line-numbers strong{color:#000}
table.CodeRay{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.CodeRay td{vertical-align:top;line-height:inherit}
table.CodeRay td.line-numbers{text-align:right}
table.CodeRay td.code{padding:0 0 0 .75em}
.CodeRay .debug{color:#fff!important;background:navy!important}
.CodeRay .annotation{color:#007}
.CodeRay .attribute-name{color:navy}
.CodeRay .attribute-value{color:#700}
.CodeRay .binary{color:#509}
.CodeRay .comment{color:#998;font-style:italic}
.CodeRay .char{color:#04d}
.CodeRay .char .content{color:#04d}
.CodeRay .char .delimiter{color:#039}
.CodeRay .class{color:#458;font-weight:bold}
.CodeRay .complex{color:#a08}
.CodeRay .constant,.CodeRay .predefined-constant{color:teal}
.CodeRay .color{color:#099}
.CodeRay .class-variable{color:#369}
.CodeRay .decorator{color:#b0b}
.CodeRay .definition{color:#099}
.CodeRay .delimiter{color:#000}
.CodeRay .doc{color:#970}
.CodeRay .doctype{color:#34b}
.CodeRay .doc-string{color:#d42}
.CodeRay .escape{color:#666}
.CodeRay .entity{color:#800}
.CodeRay .error{color:#808}
.CodeRay .exception{color:inherit}
.CodeRay .filename{color:#099}
.CodeRay .function{color:#900;font-weight:bold}
.CodeRay .global-variable{color:teal}
.CodeRay .hex{color:#058}
.CodeRay .integer,.CodeRay .float{color:#099}
.CodeRay .include{color:#555}
.CodeRay .inline{color:#000}
.CodeRay .inline .inline{background:#ccc}
.CodeRay .inline .inline .inline{background:#bbb}
.CodeRay .inline .inline-delimiter{color:#d14}
.CodeRay .inline-delimiter{color:#d14}
.CodeRay .important{color:#555;font-weight:bold}
.CodeRay .interpreted{color:#b2b}
.CodeRay .instance-variable{color:teal}
.CodeRay .label{color:#970}
.CodeRay .local-variable{color:#963}
.CodeRay .octal{color:#40e}
.CodeRay .predefined{color:#369}
.CodeRay .preprocessor{color:#579}
.CodeRay .pseudo-class{color:#555}
.CodeRay .directive{font-weight:bold}
.CodeRay .type{font-weight:bold}
.CodeRay .predefined-type{color:inherit}
.CodeRay .reserved,.CodeRay .keyword{color:#000;font-weight:bold}
.CodeRay .key{color:#808}
.CodeRay .key .delimiter{color:#606}
.CodeRay .key .char{color:#80f}
.CodeRay .value{color:#088}
.CodeRay .regexp .delimiter{color:#808}
.CodeRay .regexp .content{color:#808}
.CodeRay .regexp .modifier{color:#808}
.CodeRay .regexp .char{color:#d14}
.CodeRay .regexp .function{color:#404;font-weight:bold}
.CodeRay .string{color:#d20}
.CodeRay .string .string .string{background:#ffd0d0}
.CodeRay .string .content{color:#d14}
.CodeRay .string .char{color:#d14}
.CodeRay .string .delimiter{color:#d14}
.CodeRay .shell{color:#d14}
.CodeRay .shell .delimiter{color:#d14}
.CodeRay .symbol{color:#990073}
.CodeRay .symbol .content{color:#a60}
.CodeRay .symbol .delimiter{color:#630}
.CodeRay .tag{color:teal}
.CodeRay .tag-special{color:#d70}
.CodeRay .variable{color:#036}
.CodeRay .insert{background:#afa}
.CodeRay .delete{background:#faa}
.CodeRay .change{color:#aaf;background:#007}
.CodeRay .head{color:#f8f;background:#505}
.CodeRay .insert .insert{color:#080}
.CodeRay .delete .delete{color:#800}
.CodeRay .change .change{color:#66f}
.CodeRay .head .head{color:#f4f}
&lt;/style&gt;&lt;/head&gt;&lt;body class=&#34;article&#34;&gt;&lt;header&gt;&lt;/header&gt;&lt;div id=&#34;content&#34;&gt;&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_一目标&#34;&gt;一、目标&lt;/h2&gt;&lt;p&gt;李老板: 奋飞呀，AI都把代码还原的活给干了，咱们这个代码还原的教程还要写吗？&lt;/p&gt;
&lt;p&gt;奋飞: 当然要写了，AI是AI，那是批量化流水线操作，能有我这种纯手工还原的代码帅？我这可是有温度的代码。总不能有了翻译软件，你就不学英语了吧？当然日语可以不用学了。&lt;/p&gt;
&lt;p&gt;有个名人说过：你永远赚不到超出你认知范围外的钱。所以奋飞说：你无法指挥AI干超出你认知范围外的活。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_二步骤&#34;&gt;二、步骤&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_2条件断点_3数据打印&#34;&gt;2、条件断点   3、数据打印&lt;/h3&gt;&lt;p&gt;我们要想知道程序运行到 0x1170 时  &lt;mark&gt;x4=0xdd89ca68&lt;/mark&gt; 的来历，那就需要从前面的代码开始Trace，&lt;/p&gt;
&lt;p&gt;往上找了找 在 0x1144 有个判断，说明前面经过了若干次循环。&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;.text:&lt;span class=&#34;octal&#34;&gt;0000000000001144&lt;/span&gt; &lt;span class=&#34;float&#34;&gt;7F&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;01&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;08&lt;/span&gt; EB                 CMP             X11, X8
.text:&lt;span class=&#34;octal&#34;&gt;00000000000011&lt;/span&gt;&lt;span class=&#34;integer&#34;&gt;48&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;88&lt;/span&gt; CC FF &lt;span class=&#34;integer&#34;&gt;54&lt;/span&gt;                 B.HI            loc_AD8&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;为了分析起来方便，我只想在最后一次循环的时候Trace代码来分析，这样就需要条件断点了。&lt;/p&gt;
&lt;p&gt;在做条件断点之前，我们先把 X11 和 X8 的值打印出来。&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;debugger.addBreakPoint(module.base + &lt;span class=&#34;hex&#34;&gt;0x1144&lt;/span&gt;, &lt;span class=&#34;keyword&#34;&gt;new&lt;/span&gt; BreakPointCallback() {
    &lt;span class=&#34;error&#34;&gt;@&lt;/span&gt;Override
    &lt;span class=&#34;directive&#34;&gt;public&lt;/span&gt; boolean onHit(Emulator&amp;lt;?&amp;gt; emulator, &lt;span class=&#34;predefined-type&#34;&gt;long&lt;/span&gt; address) {
        Arm64RegisterContext ctx = emulator.getContext();
        &lt;span class=&#34;predefined-type&#34;&gt;int&lt;/span&gt; iX11 = ctx.getXInt(&lt;span class=&#34;integer&#34;&gt;11&lt;/span&gt;);
        &lt;span class=&#34;predefined-type&#34;&gt;int&lt;/span&gt; iX8 = ctx.getXInt(&lt;span class=&#34;integer&#34;&gt;8&lt;/span&gt;);;

        System.out.printf(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;X11 = %d , X8 = %d&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, iX11,iX8);

        &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;predefined-constant&#34;&gt;true&lt;/span&gt;;
    }
});&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;跑一下，&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;X11 = 64 , X8 = 64&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;奇怪只打印了一次，那说明这里不是循环，或者是个假循环。&lt;/p&gt;
&lt;p&gt;那就继续往上找吧&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;label&#34;&gt;text:&lt;/span&gt;&lt;span class=&#34;octal&#34;&gt;0000000000000&lt;/span&gt;C8C &lt;span class=&#34;integer&#34;&gt;8&lt;/span&gt;C &lt;span class=&#34;integer&#34;&gt;81&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;00&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;91&lt;/span&gt;                 ADD             X12, X12, &lt;span class=&#34;preprocessor&#34;&gt;#0x20&lt;/span&gt; ; &lt;span class=&#34;char&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;
.text:&lt;span class=&#34;octal&#34;&gt;0000000000000&lt;/span&gt;C90             ; &lt;span class=&#34;integer&#34;&gt;156&lt;/span&gt;:       &lt;span class=&#34;keyword&#34;&gt;while&lt;/span&gt; ( v24 &amp;lt; &lt;span class=&#34;hex&#34;&gt;0x10&lt;/span&gt; );
.text:&lt;span class=&#34;octal&#34;&gt;0000000000000&lt;/span&gt;C90 &lt;span class=&#34;octal&#34;&gt;03&lt;/span&gt; FA FF &lt;span class=&#34;integer&#34;&gt;54&lt;/span&gt;                 B.CC            loc_BD0
.text:&lt;span class=&#34;octal&#34;&gt;0000000000000&lt;/span&gt;C94 FE &lt;span class=&#34;integer&#34;&gt;17&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;50&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;29&lt;/span&gt;                 LDP             W30, W5, [SP,&lt;span class=&#34;preprocessor&#34;&gt;#0x110&lt;/span&gt;+var_90]
.text:&lt;span class=&#34;octal&#34;&gt;0000000000000&lt;/span&gt;C98 &lt;span class=&#34;integer&#34;&gt;11&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;03&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;19&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;4&lt;/span&gt;A                 EOR             W17, W24, W25&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;感觉这个 0xC94 应该是最后一次计算的位置了。 (我们可以先在 0xC94 下一个断点，如果只触发一次说明可用，如果触发多次，说明它在循环体里面。)&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_5trace代码&#34;&gt;5、Trace代码&lt;/h3&gt;&lt;p&gt;Unidbg Trace代码有两种方式，一种是直接写代码来实现，  把Trace结果存入traceCode1.log&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;java&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;try&lt;/span&gt; {
  &lt;span class=&#34;comment&#34;&gt;// Trace 的范围是 0xC94 到 0x1170&lt;/span&gt;
    emulator.traceCode(module.base+&lt;span class=&#34;hex&#34;&gt;0xC94&lt;/span&gt;, module.base+&lt;span class=&#34;hex&#34;&gt;0x1170&lt;/span&gt;).setRedirect(&lt;span class=&#34;keyword&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;predefined-type&#34;&gt;PrintStream&lt;/span&gt;(&lt;span class=&#34;keyword&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;predefined-type&#34;&gt;File&lt;/span&gt;(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;traceCode1.log&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;)));
} &lt;span class=&#34;keyword&#34;&gt;catch&lt;/span&gt; (&lt;span class=&#34;exception&#34;&gt;IOException&lt;/span&gt; e) {
    &lt;span class=&#34;keyword&#34;&gt;throw&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;exception&#34;&gt;IllegalStateException&lt;/span&gt;(e);
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;另一种是在调试命令行输入Trace命令。&lt;/p&gt;
&lt;p&gt;先在 0xC94下断点，进入调试窗口，输入 traceCode 命令然后直接回车即可。&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;traceCode
Set trace LinuxModule{base=0x40000000, size=12288, name=&amp;#39;libnative-lib.so&amp;#39;} instructions success.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;如果要把Trace结果保存到文件，就加上文件名 traceCode traceCode1.log&lt;/p&gt;
&lt;p&gt;然后 c 命令继续执行，Trace结果就出来了。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_开始还原算法&#34;&gt;开始还原算法&lt;/h3&gt;&lt;p&gt;在Trace结果里面搜索 0xdd89ca68 ， 发现他是通过 0x68ca89dd 翻转来的&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;0x40001154: &amp;#34;rev w4, w22&amp;#34; w22=0x68ca89dd =&amp;gt; w4=0xdd89ca68&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这里遇到不熟悉的指令可以很自然的咨询AI了&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Md5two/ai1.png&#34; alt=&#34;ai1&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ai1&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;我们先把 0x68ca89dd 相关的结果挑出来，原则就是 从结果向入参回溯。&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;0x40001048: &amp;#34;add w12, w12, w15&amp;#34; w12=0x47448b48 w15=0x93f6f2bb =&amp;gt; w12=0xdb3b7e03

0x40001098: &amp;#34;orn w12, w12, w11&amp;#34; w12=0xdb3b7e03 w11=0x49ac16b =&amp;gt; w12=0xfb7f7e97
0x4000109c: &amp;#34;eor w12, w12, w16&amp;#34; w12=0xfb7f7e97 w16=0xa96ba62 =&amp;gt; w12=0xf1e9c4f5
0x400010a0: &amp;#34;add w12, w12, w15&amp;#34; w12=0xf1e9c4f5 w15=0x93f6f2bb =&amp;gt; w12=0x85e0b7b0
0x400010b0: &amp;#34;add w12, w12, w15&amp;#34; w12=0x85e0b7b0 w15=0x4212f2e5 =&amp;gt; w12=0xc7f3aa95

0x4000107c: &amp;#34;add w11, w11, w17&amp;#34; w11=0xffa26fc9 w17=0x2cc489bc =&amp;gt; w11=0x2c66f985
0x40001088: &amp;#34;add w11, w11, w17&amp;#34; w11=0x2c66f985 w17=0xf3d1564b =&amp;gt; w11=0x20384fd0
0x4000108c: &amp;#34;ror w11, w11, #0xb&amp;#34; w11=0x20384fd0 =&amp;gt; w11=0xfa040709

0x400010b4: &amp;#34;ror w12, w12, #0x1a&amp;#34; w12=0xc7f3aa95 =&amp;gt; w12=0xfceaa571
0x40001090: &amp;#34;add w11, w11, w16&amp;#34; w11=0xfa040709 w16=0xa96ba62 =&amp;gt; w11=0x49ac16b

0x400010b8: &amp;#34;add w12, w12, w11&amp;#34; w12=0xfceaa571 w11=0x49ac16b =&amp;gt; w12=0x18566dc

0x40001048: &amp;#34;add w12, w12, w15&amp;#34; w12=0x47448b48 w15=0x93f6f2bb =&amp;gt; w12=0xdb3b7e03

0x40001098: &amp;#34;orn w12, w12, w11&amp;#34; w12=0xdb3b7e03 w11=0x49ac16b =&amp;gt; w12=0xfb7f7e97
0x4000109c: &amp;#34;eor w12, w12, w16&amp;#34; w12=0xfb7f7e97 w16=0xa96ba62 =&amp;gt; w12=0xf1e9c4f5
0x400010a0: &amp;#34;add w12, w12, w15&amp;#34; w12=0xf1e9c4f5 w15=0x93f6f2bb =&amp;gt; w12=0x85e0b7b0
0x400010b0: &amp;#34;add w12, w12, w15&amp;#34; w12=0x85e0b7b0 w15=0x4212f2e5 =&amp;gt; w12=0xc7f3aa95

0x4000107c: &amp;#34;add w11, w11, w17&amp;#34; w11=0xffa26fc9 w17=0x2cc489bc =&amp;gt; w11=0x2c66f985
0x40001088: &amp;#34;add w11, w11, w17&amp;#34; w11=0x2c66f985 w17=0xf3d1564b =&amp;gt; w11=0x20384fd0
0x4000108c: &amp;#34;ror w11, w11, #0xb&amp;#34; w11=0x20384fd0 =&amp;gt; w11=0xfa040709

0x400010b4: &amp;#34;ror w12, w12, #0x1a&amp;#34; w12=0xc7f3aa95 =&amp;gt; w12=0xfceaa571
0x40001090: &amp;#34;add w11, w11, w16&amp;#34; w11=0xfa040709 w16=0xa96ba62 =&amp;gt; w11=0x49ac16b

0x400010b8: &amp;#34;add w12, w12, w11&amp;#34; w12=0xfceaa571 w11=0x49ac16b =&amp;gt; w12=0x18566dc

0x40001108: &amp;#34;add w22, w12, w22&amp;#34; w12=0x18566dc w22=0x67452301 =&amp;gt; w22=0x68ca89dd&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;然后打开 VSCode开始写代码&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;predefined-type&#34;&gt;int&lt;/span&gt; w12,w11,w15;

w12 = w12 | ~w11          &lt;span class=&#34;comment&#34;&gt;// 0x40001098: &amp;#34;orn w12, w12, w11&amp;#34; w12=0xdb3b7e03 w11=0x49ac16b =&amp;gt; w12=0xfb7f7e97&lt;/span&gt;
w12 = w12 ^ w16                 &lt;span class=&#34;comment&#34;&gt;// 0x4000109c: &amp;#34;eor w12, w12, w16&amp;#34; w12=0xfb7f7e97 w16=0xa96ba62 =&amp;gt; w12=0xf1e9c4f5&lt;/span&gt;

&lt;span class=&#34;comment&#34;&gt;// 上面这两步 其实就是&lt;/span&gt;
&lt;span class=&#34;comment&#34;&gt;// w12 = (w12 | ~w11) ^ w16&lt;/span&gt;

w12 = w12 + w15                                &lt;span class=&#34;comment&#34;&gt;// 0x400010a0: &amp;#34;add w12, w12, w15&amp;#34; w12=0xf1e9c4f5 w15=0x93f6f2bb =&amp;gt; w12=0x85e0b7b0&lt;/span&gt;
w12 = w12 + Num_w15(&lt;span class=&#34;error&#34;&gt;常&lt;/span&gt;&lt;span class=&#34;error&#34;&gt;量&lt;/span&gt;)        &lt;span class=&#34;comment&#34;&gt;// 0x400010b0: &amp;#34;add w12, w12, w15&amp;#34; w12=0x85e0b7b0 w15=0x4212f2e5 =&amp;gt; w12=0xc7f3aa95&lt;/span&gt;
w12 = w12 &amp;gt;&amp;gt; &lt;span class=&#34;hex&#34;&gt;0x1a&lt;/span&gt;;        &lt;span class=&#34;comment&#34;&gt;// 0x400010b4: &amp;#34;ror w12, w12, #0x1a&amp;#34; w12=0xc7f3aa95 =&amp;gt; w12=0xfceaa571&lt;/span&gt;
w12 = w12 + w11;                &lt;span class=&#34;comment&#34;&gt;// 0x400010b8: &amp;#34;add w12, w12, w11&amp;#34; w12=0xfceaa571 w11=0x49ac16b =&amp;gt; w12=0x18566dc&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;是的，还原算法就是这么的朴实无华而又枯燥无味。&lt;/p&gt;
&lt;p&gt;w12 = (w12 | ~w11) ^ w16  这个算式让我们有点兴奋&lt;/p&gt;
&lt;p&gt;他和标准MD5 算法的 I 非常相似。&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;comment&#34;&gt;//F,G,H,I四个非线性变换函数&lt;/span&gt;
&lt;span class=&#34;preprocessor&#34;&gt;#define&lt;/span&gt; F(x,y,z) ((x &amp;amp; y) | (~x &amp;amp; z))
&lt;span class=&#34;preprocessor&#34;&gt;#define&lt;/span&gt; G(x,y,z) ((x &amp;amp; z) | (y &amp;amp; ~z))
&lt;span class=&#34;preprocessor&#34;&gt;#define&lt;/span&gt; H(x,y,z) (x^y^z)
&lt;span class=&#34;preprocessor&#34;&gt;#define&lt;/span&gt; I(x,y,z) (y ^ (x | ~z))&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这样的话可能我们就可以轻松一点，在标准MD5算法的框架上去还原，只找出里面魔改的部分。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_忍不住用ai了&#34;&gt;忍不住用AI了&lt;/h3&gt;&lt;p&gt;把这个枯燥无味的过程扔给 &lt;mark&gt;Cursor&lt;/mark&gt; 会怎样&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;用C语言还原w12的计算过程，添加中文注释&lt;/mark&gt;&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;hex&#34;&gt;0x40001048&lt;/span&gt;: &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;add w12, w12, w15&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; w12=&lt;span class=&#34;hex&#34;&gt;0x47448b48&lt;/span&gt; w15=&lt;span class=&#34;hex&#34;&gt;0x93f6f2bb&lt;/span&gt; =&amp;gt; w12=&lt;span class=&#34;hex&#34;&gt;0xdb3b7e03&lt;/span&gt;

&lt;span class=&#34;hex&#34;&gt;0x40001098&lt;/span&gt;: &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;orn w12, w12, w11&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; w12=&lt;span class=&#34;hex&#34;&gt;0xdb3b7e03&lt;/span&gt; w11=&lt;span class=&#34;hex&#34;&gt;0x49ac16b&lt;/span&gt; =&amp;gt; w12=&lt;span class=&#34;hex&#34;&gt;0xfb7f7e97&lt;/span&gt;
&lt;span class=&#34;hex&#34;&gt;0x4000109c&lt;/span&gt;: &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;eor w12, w12, w16&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; w12=&lt;span class=&#34;hex&#34;&gt;0xfb7f7e97&lt;/span&gt; w16=&lt;span class=&#34;hex&#34;&gt;0xa96ba62&lt;/span&gt; =&amp;gt; w12=&lt;span class=&#34;hex&#34;&gt;0xf1e9c4f5&lt;/span&gt;
&lt;span class=&#34;hex&#34;&gt;0x400010a0&lt;/span&gt;: &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;add w12, w12, w15&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; w12=&lt;span class=&#34;hex&#34;&gt;0xf1e9c4f5&lt;/span&gt; w15=&lt;span class=&#34;hex&#34;&gt;0x93f6f2bb&lt;/span&gt; =&amp;gt; w12=&lt;span class=&#34;hex&#34;&gt;0x85e0b7b0&lt;/span&gt;
&lt;span class=&#34;hex&#34;&gt;0x400010b0&lt;/span&gt;: &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;add w12, w12, w15&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; w12=&lt;span class=&#34;hex&#34;&gt;0x85e0b7b0&lt;/span&gt; w15=&lt;span class=&#34;hex&#34;&gt;0x4212f2e5&lt;/span&gt; =&amp;gt; w12=&lt;span class=&#34;hex&#34;&gt;0xc7f3aa95&lt;/span&gt;

&lt;span class=&#34;hex&#34;&gt;0x4000107c&lt;/span&gt;: &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;add w11, w11, w17&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; w11=&lt;span class=&#34;hex&#34;&gt;0xffa26fc9&lt;/span&gt; w17=&lt;span class=&#34;hex&#34;&gt;0x2cc489bc&lt;/span&gt; =&amp;gt; w11=&lt;span class=&#34;hex&#34;&gt;0x2c66f985&lt;/span&gt;
&lt;span class=&#34;hex&#34;&gt;0x40001088&lt;/span&gt;: &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;add w11, w11, w17&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; w11=&lt;span class=&#34;hex&#34;&gt;0x2c66f985&lt;/span&gt; w17=&lt;span class=&#34;hex&#34;&gt;0xf3d1564b&lt;/span&gt; =&amp;gt; w11=&lt;span class=&#34;hex&#34;&gt;0x20384fd0&lt;/span&gt;
&lt;span class=&#34;hex&#34;&gt;0x4000108c&lt;/span&gt;: &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;ror w11, w11, #0xb&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; w11=&lt;span class=&#34;hex&#34;&gt;0x20384fd0&lt;/span&gt; =&amp;gt; w11=&lt;span class=&#34;hex&#34;&gt;0xfa040709&lt;/span&gt;

&lt;span class=&#34;hex&#34;&gt;0x400010b4&lt;/span&gt;: &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;ror w12, w12, #0x1a&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; w12=&lt;span class=&#34;hex&#34;&gt;0xc7f3aa95&lt;/span&gt; =&amp;gt; w12=&lt;span class=&#34;hex&#34;&gt;0xfceaa571&lt;/span&gt;
&lt;span class=&#34;hex&#34;&gt;0x40001090&lt;/span&gt;: &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;add w11, w11, w16&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; w11=&lt;span class=&#34;hex&#34;&gt;0xfa040709&lt;/span&gt; w16=&lt;span class=&#34;hex&#34;&gt;0xa96ba62&lt;/span&gt; =&amp;gt; w11=&lt;span class=&#34;hex&#34;&gt;0x49ac16b&lt;/span&gt;

&lt;span class=&#34;hex&#34;&gt;0x400010b8&lt;/span&gt;: &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;add w12, w12, w11&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt; w12=&lt;span class=&#34;hex&#34;&gt;0xfceaa571&lt;/span&gt; w11=&lt;span class=&#34;hex&#34;&gt;0x49ac16b&lt;/span&gt; =&amp;gt; w12=&lt;span class=&#34;hex&#34;&gt;0x18566dc&lt;/span&gt;

&lt;span class=&#34;preprocessor&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;include&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;

&lt;span class=&#34;predefined-type&#34;&gt;int&lt;/span&gt; main() {
    &lt;span class=&#34;predefined-type&#34;&gt;unsigned&lt;/span&gt; &lt;span class=&#34;predefined-type&#34;&gt;int&lt;/span&gt; w12 = &lt;span class=&#34;hex&#34;&gt;0x47448b48&lt;/span&gt;;
    &lt;span class=&#34;predefined-type&#34;&gt;unsigned&lt;/span&gt; &lt;span class=&#34;predefined-type&#34;&gt;int&lt;/span&gt; w15 = &lt;span class=&#34;hex&#34;&gt;0x93f6f2bb&lt;/span&gt;;
    &lt;span class=&#34;predefined-type&#34;&gt;unsigned&lt;/span&gt; &lt;span class=&#34;predefined-type&#34;&gt;int&lt;/span&gt; w11 = &lt;span class=&#34;hex&#34;&gt;0xffa26fc9&lt;/span&gt;;
    &lt;span class=&#34;predefined-type&#34;&gt;unsigned&lt;/span&gt; &lt;span class=&#34;predefined-type&#34;&gt;int&lt;/span&gt; w17 = &lt;span class=&#34;hex&#34;&gt;0x2cc489bc&lt;/span&gt;;
    &lt;span class=&#34;predefined-type&#34;&gt;unsigned&lt;/span&gt; &lt;span class=&#34;predefined-type&#34;&gt;int&lt;/span&gt; w16 = &lt;span class=&#34;hex&#34;&gt;0xa96ba62&lt;/span&gt;;

    w12 = w12 + w15;
    printf(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;w12 = %x&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, w12);

    w12 = (w12 | ~w11);
    printf(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;w12 = %x&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, w12);

    w12 = w12 ^ w16;
    printf(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;w12 = %x&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, w12);

    w12 = w12 + w15;
    printf(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;w12 = %x&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, w12);

    w12 = w12 + &lt;span class=&#34;hex&#34;&gt;0x4212f2e5&lt;/span&gt;;
    printf(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;w12 = %x&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, w12);

    w11 = w11 + w17;
    printf(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;w11 = %x&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, w11);

    w11 = w11 + &lt;span class=&#34;hex&#34;&gt;0xf3d1564b&lt;/span&gt;;
    printf(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;w11 = %x&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, w11);

    w11 = (w11 &amp;gt;&amp;gt; &lt;span class=&#34;integer&#34;&gt;11&lt;/span&gt;) | (w11 &amp;lt;&amp;lt; (&lt;span class=&#34;integer&#34;&gt;32&lt;/span&gt; - &lt;span class=&#34;integer&#34;&gt;11&lt;/span&gt;));
    printf(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;w11 = %x&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, w11);

    w12 = (w12 &amp;gt;&amp;gt; &lt;span class=&#34;integer&#34;&gt;26&lt;/span&gt;) | (w12 &amp;lt;&amp;lt; (&lt;span class=&#34;integer&#34;&gt;32&lt;/span&gt; - &lt;span class=&#34;integer&#34;&gt;26&lt;/span&gt;));
    printf(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;w12 = %x&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, w12);

    w11 = w11 + w16;
    printf(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;w11 = %x&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, w11);

    w12 = w12 + w11;
    printf(&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;w12 = %x&lt;/span&gt;&lt;span class=&#34;char&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;, w12);

    &lt;span class=&#34;keyword&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;0&lt;/span&gt;;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;感觉比我写的好， 程序员要进化出一个新品种了，就是给AI写 &lt;mark&gt;prompt&lt;/mark&gt;&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_三总结&#34;&gt;三、总结&lt;/h2&gt;&lt;p&gt;以前觉得当leader很幸福，啥活都不用干，直接指挥小弟干活就行。&lt;/p&gt;
&lt;p&gt;后来真当了leader才发现，我去，你得A语言到Z语言都会，不然做php的小弟说这玩意实现不了，做Flash的小弟说这个功能得做一个月。&lt;/p&gt;
&lt;p&gt;AI也是如此，机械重复性的工作它比你做的好，创意和指路的活还得你自己干。&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Md5two/ffshow.png&#34; alt=&#34;ffshow&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ffshow&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;mark&gt;决定战争胜负的是人，而不是一两件新式武器。这一论断永远都不过时&lt;/mark&gt;&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;: 本文的目的只有一个就是学习更多的逆向技巧和思路，如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担，和本文以及作者没关系，本文涉及到的代码项目可以去 &lt;mark&gt;奋飞的朋友们&lt;/mark&gt; 知识星球自取，欢迎加入知识星球一起学习探讨技术。有问题可以加我wx: &lt;mark&gt;fenfei331&lt;/mark&gt; 讨论下。&lt;/p&gt;&lt;/aside&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ffzsxq.jpg&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;
&lt;p&gt;关注微信公众号，最新技术干货实时推送&lt;/p&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ff330.png&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;&lt;/section&gt;&lt;/div&gt;&lt;footer&gt;&lt;div id=&#34;footer-text&#34;&gt;&lt;br/&gt;Last updated 2026-04-27 18:48:44 +0800&lt;/div&gt;&lt;/footer&gt;
</description>
      
    </item>
    
    <item>
      <title>安卓高版本安装系统证书 HTTPS 抓包 - 终极解决方案</title>
      <link>http://91fans.com.cn/post/certificate/</link>
      <pubDate>Sun, 05 Mar 2023 18:10:06 +0800</pubDate>
      
      <guid>http://91fans.com.cn/post/certificate/</guid>
      
        <description>&lt;meta charset=&#34;UTF-8&#34;/&gt;&lt;meta http-equiv=&#34;X-UA-Compatible&#34; content=&#34;IE=edge&#34;/&gt;&lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;/&gt;&lt;meta name=&#34;generator&#34; content=&#34;Asciidoctor 2.0.20&#34;/&gt;&lt;title&gt;一、目标&lt;/title&gt;&lt;style&gt;/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import &#34;https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700&#34;; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:&#34;\201C&#34; &#34;\201D&#34; &#34;\2018&#34; &#34;\2019&#34;}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock&gt;.content&gt;.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock&gt;.content&gt;.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:&#34; &#34;;display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])&gt;code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre&gt;code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:&#34;[&#34;;padding:0 3px 0 2px}
b.button::after{content:&#34;]&#34;;padding:0 2px 0 3px}
p a&gt;code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:&#34; &#34;;display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header&gt;h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header&gt;h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header&gt;h1:only-child,body.toc2 #header&gt;h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:&#34;\00a0\2013\00a0&#34;}
#header .details br+span.author::before{content:&#34;\00a0\22c5\00a0&#34;;color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:&#34;\00a0|\00a0&#34;}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:&#34;\00a0&#34;}
#content&gt;h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc&gt;ul{margin-left:.125em}
#toc ul.sectlevel0&gt;li&gt;a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2&gt;ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2&gt;ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc&gt;:first-child{margin-top:0}
#content #toc&gt;:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1&gt;a.anchor,h2&gt;a.anchor,h3&gt;a.anchor,#toctitle&gt;a.anchor,.sidebarblock&gt;.content&gt;.title&gt;a.anchor,h4&gt;a.anchor,h5&gt;a.anchor,h6&gt;a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1&gt;a.anchor::before,h2&gt;a.anchor::before,h3&gt;a.anchor::before,#toctitle&gt;a.anchor::before,.sidebarblock&gt;.content&gt;.title&gt;a.anchor::before,h4&gt;a.anchor::before,h5&gt;a.anchor::before,h6&gt;a.anchor::before{content:&#34;\00A7&#34;;font-size:.85em;display:block;padding-top:.1em}
#content h1:hover&gt;a.anchor,#content h1&gt;a.anchor:hover,h2:hover&gt;a.anchor,h2&gt;a.anchor:hover,h3:hover&gt;a.anchor,#toctitle:hover&gt;a.anchor,.sidebarblock&gt;.content&gt;.title:hover&gt;a.anchor,h3&gt;a.anchor:hover,#toctitle&gt;a.anchor:hover,.sidebarblock&gt;.content&gt;.title&gt;a.anchor:hover,h4:hover&gt;a.anchor,h4&gt;a.anchor:hover,h5:hover&gt;a.anchor,h5&gt;a.anchor:hover,h6:hover&gt;a.anchor,h6&gt;a.anchor:hover{visibility:visible}
#content h1&gt;a.link,h2&gt;a.link,h3&gt;a.link,#toctitle&gt;a.link,.sidebarblock&gt;.content&gt;.title&gt;a.link,h4&gt;a.link,h5&gt;a.link,h6&gt;a.link{color:#ba3925;text-decoration:none}
#content h1&gt;a.link:hover,h2&gt;a.link:hover,h3&gt;a.link:hover,#toctitle&gt;a.link:hover,.sidebarblock&gt;.content&gt;.title&gt;a.link:hover,h4&gt;a.link:hover,h5&gt;a.link:hover,h6&gt;a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details&gt;summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details&gt;summary::-webkit-details-marker{display:none}
details&gt;summary::before{content:&#34;&#34;;border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]&gt;summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details&gt;summary::after{content:&#34;&#34;;width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{text-rendering:optimizeLegibility;text-align:left;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content&gt;caption.title{white-space:nowrap;width:0}
.paragraph.lead&gt;p,#preamble&gt;.sectionbody&gt;[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock&gt;table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock&gt;table td.icon{text-align:center;width:80px}
.admonitionblock&gt;table td.icon img{max-width:none}
.admonitionblock&gt;table td.icon .title{font-weight:bold;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;text-transform:uppercase}
.admonitionblock&gt;table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock&gt;table td.content&gt;:last-child&gt;:last-child{margin-bottom:0}
.exampleblock&gt;.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock&gt;.content&gt;.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock&gt;.content&gt;:first-child,.sidebarblock&gt;.content&gt;:first-child{margin-top:0}
.exampleblock&gt;.content&gt;:last-child,.exampleblock&gt;.content&gt;:last-child&gt;:last-child,.exampleblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child&gt;:last-child,.sidebarblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child{margin-bottom:0}
.literalblock pre,.listingblock&gt;.content&gt;pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:1em}}
.literalblock pre,.listingblock&gt;.content&gt;pre:not(.highlight),.listingblock&gt;.content&gt;pre[class=highlight],.listingblock&gt;.content&gt;pre[class^=&#34;highlight &#34;]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock&gt;.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:&#34;$&#34;}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs&gt;code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)&gt;.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:&#34;\201c&#34;;float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote&gt;.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract&gt;.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt&gt;blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock&gt;.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock&gt;.content&gt;:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all&gt;*&gt;tr&gt;*{border-width:1px}
table.grid-cols&gt;*&gt;tr&gt;*{border-width:0 1px}
table.grid-rows&gt;*&gt;tr&gt;*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none&gt;colgroup+*&gt;:first-child&gt;*,table.frame-sides&gt;colgroup+*&gt;:first-child&gt;*{border-top-width:0}
table.frame-none&gt;:last-child&gt;:last-child&gt;*,table.frame-sides&gt;:last-child&gt;:last-child&gt;*{border-bottom-width:0}
table.frame-none&gt;*&gt;tr&gt;:first-child,table.frame-ends&gt;*&gt;tr&gt;:first-child{border-left-width:0}
table.frame-none&gt;*&gt;tr&gt;:last-child,table.frame-ends&gt;*&gt;tr&gt;:last-child{border-right-width:0}
table.stripes-all&gt;*&gt;tr,table.stripes-odd&gt;*&gt;tr:nth-of-type(odd),table.stripes-even&gt;*&gt;tr:nth-of-type(even),table.stripes-hover&gt;*&gt;tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock&gt;code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child&gt;:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li&gt;p:empty:only-child::before{content:&#34;&#34;;display:inline-block}
ul.checklist&gt;li&gt;p:first-child{margin-left:-1em}
ul.checklist&gt;li&gt;p:first-child&gt;.fa-square-o:first-child,ul.checklist&gt;li&gt;p:first-child&gt;.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist&gt;li&gt;p:first-child&gt;input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline&gt;li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist&gt;table,.colist&gt;table{border:0;background:none}
.hdlist&gt;table&gt;tbody&gt;tr,.colist&gt;table&gt;tbody&gt;tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock&gt;.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb&gt;.title,.imageblock.th&gt;.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon&gt;.fa{cursor:default}
a span.icon&gt;.fa{cursor:inherit}
.admonitionblock td.icon [class^=&#34;fa icon-&#34;]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:&#34;\f05a&#34;;color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:&#34;\f0eb&#34;;text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:&#34;\f071&#34;;color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:&#34;\f06d&#34;;color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:&#34;\f06a&#34;;color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock&gt;.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^=&#34;#&#34;],a[href^=&#34;mailto:&#34;]{text-decoration:none!important}
a[href^=&#34;http:&#34;]:not(.bare)::after,a[href^=&#34;https:&#34;]:not(.bare)::after{content:&#34;(&#34; attr(href) &#34;)&#34;;display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:&#34; (&#34; attr(title) &#34;)&#34;}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock&gt;.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header&gt;h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1&gt;h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header&gt;h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}&lt;/style&gt;
&lt;style&gt;
/*! Stylesheet for CodeRay to loosely match GitHub themes | MIT License */
pre.CodeRay{background:#f7f7f8}
.CodeRay .line-numbers{border-right:1px solid;opacity:.35;padding:0 .5em 0 0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.CodeRay span.line-numbers{display:inline-block;margin-right:.75em}
.CodeRay .line-numbers strong{color:#000}
table.CodeRay{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.CodeRay td{vertical-align:top;line-height:inherit}
table.CodeRay td.line-numbers{text-align:right}
table.CodeRay td.code{padding:0 0 0 .75em}
.CodeRay .debug{color:#fff!important;background:navy!important}
.CodeRay .annotation{color:#007}
.CodeRay .attribute-name{color:navy}
.CodeRay .attribute-value{color:#700}
.CodeRay .binary{color:#509}
.CodeRay .comment{color:#998;font-style:italic}
.CodeRay .char{color:#04d}
.CodeRay .char .content{color:#04d}
.CodeRay .char .delimiter{color:#039}
.CodeRay .class{color:#458;font-weight:bold}
.CodeRay .complex{color:#a08}
.CodeRay .constant,.CodeRay .predefined-constant{color:teal}
.CodeRay .color{color:#099}
.CodeRay .class-variable{color:#369}
.CodeRay .decorator{color:#b0b}
.CodeRay .definition{color:#099}
.CodeRay .delimiter{color:#000}
.CodeRay .doc{color:#970}
.CodeRay .doctype{color:#34b}
.CodeRay .doc-string{color:#d42}
.CodeRay .escape{color:#666}
.CodeRay .entity{color:#800}
.CodeRay .error{color:#808}
.CodeRay .exception{color:inherit}
.CodeRay .filename{color:#099}
.CodeRay .function{color:#900;font-weight:bold}
.CodeRay .global-variable{color:teal}
.CodeRay .hex{color:#058}
.CodeRay .integer,.CodeRay .float{color:#099}
.CodeRay .include{color:#555}
.CodeRay .inline{color:#000}
.CodeRay .inline .inline{background:#ccc}
.CodeRay .inline .inline .inline{background:#bbb}
.CodeRay .inline .inline-delimiter{color:#d14}
.CodeRay .inline-delimiter{color:#d14}
.CodeRay .important{color:#555;font-weight:bold}
.CodeRay .interpreted{color:#b2b}
.CodeRay .instance-variable{color:teal}
.CodeRay .label{color:#970}
.CodeRay .local-variable{color:#963}
.CodeRay .octal{color:#40e}
.CodeRay .predefined{color:#369}
.CodeRay .preprocessor{color:#579}
.CodeRay .pseudo-class{color:#555}
.CodeRay .directive{font-weight:bold}
.CodeRay .type{font-weight:bold}
.CodeRay .predefined-type{color:inherit}
.CodeRay .reserved,.CodeRay .keyword{color:#000;font-weight:bold}
.CodeRay .key{color:#808}
.CodeRay .key .delimiter{color:#606}
.CodeRay .key .char{color:#80f}
.CodeRay .value{color:#088}
.CodeRay .regexp .delimiter{color:#808}
.CodeRay .regexp .content{color:#808}
.CodeRay .regexp .modifier{color:#808}
.CodeRay .regexp .char{color:#d14}
.CodeRay .regexp .function{color:#404;font-weight:bold}
.CodeRay .string{color:#d20}
.CodeRay .string .string .string{background:#ffd0d0}
.CodeRay .string .content{color:#d14}
.CodeRay .string .char{color:#d14}
.CodeRay .string .delimiter{color:#d14}
.CodeRay .shell{color:#d14}
.CodeRay .shell .delimiter{color:#d14}
.CodeRay .symbol{color:#990073}
.CodeRay .symbol .content{color:#a60}
.CodeRay .symbol .delimiter{color:#630}
.CodeRay .tag{color:teal}
.CodeRay .tag-special{color:#d70}
.CodeRay .variable{color:#036}
.CodeRay .insert{background:#afa}
.CodeRay .delete{background:#faa}
.CodeRay .change{color:#aaf;background:#007}
.CodeRay .head{color:#f8f;background:#505}
.CodeRay .insert .insert{color:#080}
.CodeRay .delete .delete{color:#800}
.CodeRay .change .change{color:#66f}
.CodeRay .head .head{color:#f4f}
&lt;/style&gt;&lt;/head&gt;&lt;body class=&#34;article&#34;&gt;&lt;header&gt;&lt;/header&gt;&lt;div id=&#34;content&#34;&gt;&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_一目标&#34;&gt;一、目标&lt;/h2&gt;&lt;p&gt;要抓App的包，首先需要App信任抓包软件的证书。&lt;/p&gt;
&lt;p&gt;不过从Android 从 7.0 开始，系统不再信任用户 CA 证书，所以你需要把 CA 证书安装到系统 CA 证书目录。&lt;/p&gt;
&lt;p&gt;如果你是用Magisk越狱的话，这个工作就比较简单了，只需要安装一个模块 Move Certificates。&lt;/p&gt;
&lt;p&gt;不过今天的故事从我刷了一个新rom开始，这个rom比较奇怪，刷完之后 adb连上 直接就是root状态，但是App却没法获取root状态。&lt;/p&gt;
&lt;p&gt;我去，这不就是误打误撞刷了一个隐藏root的rom吗？这下我可舍不得装Magisk了。&lt;/p&gt;
&lt;p&gt;那现在的问题就是 &lt;mark&gt;如何把证书安装到系统目录？&lt;/mark&gt;&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_二步骤&#34;&gt;二、步骤&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_霸王硬上弓&#34;&gt;霸王硬上弓&lt;/h3&gt;&lt;p&gt;计算证书名&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;openssl x509 -subject_hash_old -in charles-ssl-proxying-certificate_saved.pem&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;算出数值，比如3a1074b3&lt;/p&gt;
&lt;p&gt;然后把原Charles证书charles-ssl-proxying-certificate_saved.pem改名为 &lt;mark&gt;3a1074b3.0&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;最后把 &lt;mark&gt;3a1074b3.0&lt;/mark&gt; 文件拷贝到 /system/etc/security/cacerts/ 目录下面。&lt;/p&gt;
&lt;p&gt;搞定~~&lt;/p&gt;
&lt;p&gt;理想很丰满，现实很骨感，/system 大概率是不可写的，即使你有root权限，也写不进去。&lt;/p&gt;
&lt;p&gt;问了下谷哥，哥说，可以把 /system 重新 mount 成可读写的，不过我没有成功。&lt;/p&gt;
&lt;p&gt;之前有两种方式成功过。&lt;/p&gt;
&lt;p&gt;1、安装RootExplorer.apk，把/system 加载成可读写。&lt;/p&gt;
&lt;p&gt;2、adb reboot recovery 进入之前刷的 &lt;mark&gt;twrp&lt;/mark&gt; ,在twrp下去写入 /system&lt;/p&gt;
&lt;p&gt;不过这次翻车了，RootExplorer没法加载可读。  twrp写完 /system 之后这个rom发疯了，设置 进不去了，老报崩溃。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_师夷长技&#34;&gt;师夷长技&lt;/h3&gt;&lt;p&gt;想起了 Http Toolkit这个抓包软件，它有个 Android Device via ADB 模式，居然可以顺利抓包。&lt;/p&gt;
&lt;p&gt;说明它可以利用ADB把 证书写入到 /system , 毕竟我的ADB是有Root权限的。&lt;/p&gt;
&lt;p&gt;太神奇了，它是怎么实现的呢？&lt;/p&gt;
&lt;p&gt;这下又开始了漫长的谷歌之旅，最后在他们官网找到一篇文章，详细讲述了 &lt;mark&gt;通过有root权限的adb&lt;/mark&gt; 来写入系统证书的神奇方案。&lt;/p&gt;
&lt;p&gt;1、通过 ADB 将 HTTP Toolkit CA 证书推送到设备上。&lt;/p&gt;
&lt;p&gt;2、从 /system/etc/security/cacerts/ 中复制所有系统证书到临时目录。&lt;/p&gt;
&lt;p&gt;3、在 /system/etc/security/cacerts/ 上面挂载一个 tmpfs 内存文件系统。这实际上将一个可写的全新空文件系统放在了 /system 的一小部分上面。
将复制的系统证书移回到该挂载点。&lt;/p&gt;
&lt;p&gt;4、将 HTTP Toolkit CA 证书也移动到该挂载点。&lt;/p&gt;
&lt;p&gt;5、更新临时挂载点中所有文件的权限为 644，并将系统文件的 SELinux 标签设置为 system_file，以使其看起来像是合法的 Android 系统文件。&lt;/p&gt;
&lt;p&gt;关键点就是挂载一个 内存文件系统，太有才了。&lt;/p&gt;
&lt;p&gt;Show me the Code&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;bash&#34;&gt;# htk-inject-system-cert.sh
set -e # Fail on error
# Create a separate temp directory, to hold the current certificates
# Without this, when we add the mount we can&amp;#39;t read the current certs anymore.
mkdir -m 700 /data/local/tmp/htk-ca-copy
# Copy out the existing certificates
cp /system/etc/security/cacerts/* /data/local/tmp/htk-ca-copy/
# Create the in-memory mount on top of the system certs folder
mount -t tmpfs tmpfs /system/etc/security/cacerts
# Copy the existing certs back into the tmpfs mount, so we keep trusting them
mv /data/local/tmp/htk-ca-copy/* /system/etc/security/cacerts/
# Copy our new cert in, so we trust that too
cp /data/local/tmp/c88f7ed0.0 /system/etc/security/cacerts/
# Update the perms &amp;amp; selinux context labels, so everything is as readable as before
chown root:root /system/etc/security/cacerts/*
chmod 644 /system/etc/security/cacerts/*
chcon u:object_r:system_file:s0 /system/etc/security/cacerts/*
# Delete the temp cert directory &amp;amp; this script itself
rm -r /data/local/tmp/htk-ca-copy
# rm ${injectionScriptPath}
echo &amp;#34;System cert successfully injected&amp;#34;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;内存文件系统嘛，重启之后肯定就失效了，所以保存成脚本，抓包之前跑一下，也不是很麻烦的。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_三总结&#34;&gt;三、总结&lt;/h2&gt;&lt;p&gt;有时候神奇的技术就是一层窗户纸，捅破了，你会惊叹，原来这么简单。&lt;/p&gt;
&lt;p&gt;掌握了新的方案之后，未来就可以举一反三了。&lt;/p&gt;
&lt;p&gt;参考
&lt;a href=&#34;https://httptoolkit.com/blog/intercepting-android-https/&#34;&gt;https://httptoolkit.com/blog/intercepting-android-https/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/httptoolkit/httptoolkit-server/blob/8a4b4d283fbe98694ddd09a44d6e9c9941aa91e2/src/interceptors/android/adb-commands.ts&#34;&gt;https://github.com/httptoolkit/httptoolkit-server/blob/8a4b4d283fbe98694ddd09a44d6e9c9941aa91e2/src/interceptors/android/adb-commands.ts&lt;/a&gt;&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Certificate/ffshow.jpeg&#34; alt=&#34;ffshow&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ffshow&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;mark&gt;着眼总是浮游 观化颇领幻趣&lt;/mark&gt;&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;: 本文的目的只有一个就是学习更多的逆向技巧和思路，如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担，和本文以及作者没关系，本文涉及到的代码项目可以去 &lt;mark&gt;奋飞的朋友们&lt;/mark&gt; 知识星球自取，欢迎加入知识星球一起学习探讨技术。有问题可以加我wx: &lt;mark&gt;fenfei331&lt;/mark&gt; 讨论下。&lt;/p&gt;&lt;/aside&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ffzsxq.jpg&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;
&lt;p&gt;关注微信公众号，最新技术干货实时推送&lt;/p&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ff330.png&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;&lt;/section&gt;&lt;/div&gt;&lt;footer&gt;&lt;div id=&#34;footer-text&#34;&gt;&lt;br/&gt;Last updated 2026-04-27 18:48:42 +0800&lt;/div&gt;&lt;/footer&gt;
</description>
      
    </item>
    
    <item>
      <title>代码还原小试牛刀(一)：魔改的MD5</title>
      <link>http://91fans.com.cn/post/md5/</link>
      <pubDate>Wed, 22 Feb 2023 11:56:39 +0800</pubDate>
      
      <guid>http://91fans.com.cn/post/md5/</guid>
      
        <description>&lt;meta charset=&#34;UTF-8&#34;/&gt;&lt;meta http-equiv=&#34;X-UA-Compatible&#34; content=&#34;IE=edge&#34;/&gt;&lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1.0&#34;/&gt;&lt;meta name=&#34;generator&#34; content=&#34;Asciidoctor 2.0.20&#34;/&gt;&lt;title&gt;一、目标&lt;/title&gt;&lt;style&gt;/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import &#34;https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700&#34;; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:&#34;\201C&#34; &#34;\201D&#34; &#34;\2018&#34; &#34;\2019&#34;}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock&gt;.content&gt;.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock&gt;.content&gt;.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock&gt;.content&gt;.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:&#34; &#34;;display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])&gt;code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre&gt;code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:&#34;Droid Sans Mono&#34;,&#34;DejaVu Sans Mono&#34;,monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:&#34;[&#34;;padding:0 3px 0 2px}
b.button::after{content:&#34;]&#34;;padding:0 2px 0 3px}
p a&gt;code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:&#34; &#34;;display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header&gt;h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header&gt;h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header&gt;h1:only-child,body.toc2 #header&gt;h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:&#34;\00a0\2013\00a0&#34;}
#header .details br+span.author::before{content:&#34;\00a0\22c5\00a0&#34;;color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:&#34;\00a0|\00a0&#34;}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:&#34;\00a0&#34;}
#content&gt;h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc&gt;ul{margin-left:.125em}
#toc ul.sectlevel0&gt;li&gt;a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2&gt;ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2&gt;ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc&gt;:first-child{margin-top:0}
#content #toc&gt;:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1&gt;a.anchor,h2&gt;a.anchor,h3&gt;a.anchor,#toctitle&gt;a.anchor,.sidebarblock&gt;.content&gt;.title&gt;a.anchor,h4&gt;a.anchor,h5&gt;a.anchor,h6&gt;a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1&gt;a.anchor::before,h2&gt;a.anchor::before,h3&gt;a.anchor::before,#toctitle&gt;a.anchor::before,.sidebarblock&gt;.content&gt;.title&gt;a.anchor::before,h4&gt;a.anchor::before,h5&gt;a.anchor::before,h6&gt;a.anchor::before{content:&#34;\00A7&#34;;font-size:.85em;display:block;padding-top:.1em}
#content h1:hover&gt;a.anchor,#content h1&gt;a.anchor:hover,h2:hover&gt;a.anchor,h2&gt;a.anchor:hover,h3:hover&gt;a.anchor,#toctitle:hover&gt;a.anchor,.sidebarblock&gt;.content&gt;.title:hover&gt;a.anchor,h3&gt;a.anchor:hover,#toctitle&gt;a.anchor:hover,.sidebarblock&gt;.content&gt;.title&gt;a.anchor:hover,h4:hover&gt;a.anchor,h4&gt;a.anchor:hover,h5:hover&gt;a.anchor,h5&gt;a.anchor:hover,h6:hover&gt;a.anchor,h6&gt;a.anchor:hover{visibility:visible}
#content h1&gt;a.link,h2&gt;a.link,h3&gt;a.link,#toctitle&gt;a.link,.sidebarblock&gt;.content&gt;.title&gt;a.link,h4&gt;a.link,h5&gt;a.link,h6&gt;a.link{color:#ba3925;text-decoration:none}
#content h1&gt;a.link:hover,h2&gt;a.link:hover,h3&gt;a.link:hover,#toctitle&gt;a.link:hover,.sidebarblock&gt;.content&gt;.title&gt;a.link:hover,h4&gt;a.link:hover,h5&gt;a.link:hover,h6&gt;a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details&gt;summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details&gt;summary::-webkit-details-marker{display:none}
details&gt;summary::before{content:&#34;&#34;;border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]&gt;summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details&gt;summary::after{content:&#34;&#34;;width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content&gt;.title,.audioblock&gt;.title,.exampleblock&gt;.title,.imageblock&gt;.title,.listingblock&gt;.title,.literalblock&gt;.title,.stemblock&gt;.title,.openblock&gt;.title,.paragraph&gt;.title,.quoteblock&gt;.title,table.tableblock&gt;.title,.verseblock&gt;.title,.videoblock&gt;.title,.dlist&gt;.title,.olist&gt;.title,.ulist&gt;.title,.qlist&gt;.title,.hdlist&gt;.title{text-rendering:optimizeLegibility;text-align:left;font-family:&#34;Noto Serif&#34;,&#34;DejaVu Serif&#34;,serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content&gt;caption.title{white-space:nowrap;width:0}
.paragraph.lead&gt;p,#preamble&gt;.sectionbody&gt;[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock&gt;table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock&gt;table td.icon{text-align:center;width:80px}
.admonitionblock&gt;table td.icon img{max-width:none}
.admonitionblock&gt;table td.icon .title{font-weight:bold;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;text-transform:uppercase}
.admonitionblock&gt;table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock&gt;table td.content&gt;:last-child&gt;:last-child{margin-bottom:0}
.exampleblock&gt;.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock&gt;.content&gt;.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock&gt;.content&gt;:first-child,.sidebarblock&gt;.content&gt;:first-child{margin-top:0}
.exampleblock&gt;.content&gt;:last-child,.exampleblock&gt;.content&gt;:last-child&gt;:last-child,.exampleblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.exampleblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child,.sidebarblock&gt;.content&gt;:last-child&gt;:last-child,.sidebarblock&gt;.content .olist&gt;ol&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .ulist&gt;ul&gt;li:last-child&gt;:last-child,.sidebarblock&gt;.content .qlist&gt;ol&gt;li:last-child&gt;:last-child{margin-bottom:0}
.literalblock pre,.listingblock&gt;.content&gt;pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock&gt;.content&gt;pre{font-size:1em}}
.literalblock pre,.listingblock&gt;.content&gt;pre:not(.highlight),.listingblock&gt;.content&gt;pre[class=highlight],.listingblock&gt;.content&gt;pre[class^=&#34;highlight &#34;]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock&gt;.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:&#34;$&#34;}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs&gt;code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)&gt;.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:&#34;\201c&#34;;float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote&gt;.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract&gt;.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt&gt;blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock&gt;.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock&gt;.content&gt;:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all&gt;*&gt;tr&gt;*{border-width:1px}
table.grid-cols&gt;*&gt;tr&gt;*{border-width:0 1px}
table.grid-rows&gt;*&gt;tr&gt;*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none&gt;colgroup+*&gt;:first-child&gt;*,table.frame-sides&gt;colgroup+*&gt;:first-child&gt;*{border-top-width:0}
table.frame-none&gt;:last-child&gt;:last-child&gt;*,table.frame-sides&gt;:last-child&gt;:last-child&gt;*{border-bottom-width:0}
table.frame-none&gt;*&gt;tr&gt;:first-child,table.frame-ends&gt;*&gt;tr&gt;:first-child{border-left-width:0}
table.frame-none&gt;*&gt;tr&gt;:last-child,table.frame-ends&gt;*&gt;tr&gt;:last-child{border-right-width:0}
table.stripes-all&gt;*&gt;tr,table.stripes-odd&gt;*&gt;tr:nth-of-type(odd),table.stripes-even&gt;*&gt;tr:nth-of-type(even),table.stripes-hover&gt;*&gt;tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock&gt;code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child&gt;:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li&gt;p:empty:only-child::before{content:&#34;&#34;;display:inline-block}
ul.checklist&gt;li&gt;p:first-child{margin-left:-1em}
ul.checklist&gt;li&gt;p:first-child&gt;.fa-square-o:first-child,ul.checklist&gt;li&gt;p:first-child&gt;.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist&gt;li&gt;p:first-child&gt;input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline&gt;li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist&gt;table,.colist&gt;table{border:0;background:none}
.hdlist&gt;table&gt;tbody&gt;tr,.colist&gt;table&gt;tbody&gt;tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock&gt;.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb&gt;.title,.imageblock.th&gt;.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon&gt;.fa{cursor:default}
a span.icon&gt;.fa{cursor:inherit}
.admonitionblock td.icon [class^=&#34;fa icon-&#34;]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:&#34;\f05a&#34;;color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:&#34;\f0eb&#34;;text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:&#34;\f071&#34;;color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:&#34;\f06d&#34;;color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:&#34;\f06a&#34;;color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:&#34;Open Sans&#34;,&#34;DejaVu Sans&#34;,sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock&gt;.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^=&#34;#&#34;],a[href^=&#34;mailto:&#34;]{text-decoration:none!important}
a[href^=&#34;http:&#34;]:not(.bare)::after,a[href^=&#34;https:&#34;]:not(.bare)::after{content:&#34;(&#34; attr(href) &#34;)&#34;;display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:&#34; (&#34; attr(title) &#34;)&#34;}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock&gt;.content&gt;.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock&gt;.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header&gt;h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1&gt;h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header&gt;h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}&lt;/style&gt;
&lt;style&gt;
/*! Stylesheet for CodeRay to loosely match GitHub themes | MIT License */
pre.CodeRay{background:#f7f7f8}
.CodeRay .line-numbers{border-right:1px solid;opacity:.35;padding:0 .5em 0 0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.CodeRay span.line-numbers{display:inline-block;margin-right:.75em}
.CodeRay .line-numbers strong{color:#000}
table.CodeRay{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.CodeRay td{vertical-align:top;line-height:inherit}
table.CodeRay td.line-numbers{text-align:right}
table.CodeRay td.code{padding:0 0 0 .75em}
.CodeRay .debug{color:#fff!important;background:navy!important}
.CodeRay .annotation{color:#007}
.CodeRay .attribute-name{color:navy}
.CodeRay .attribute-value{color:#700}
.CodeRay .binary{color:#509}
.CodeRay .comment{color:#998;font-style:italic}
.CodeRay .char{color:#04d}
.CodeRay .char .content{color:#04d}
.CodeRay .char .delimiter{color:#039}
.CodeRay .class{color:#458;font-weight:bold}
.CodeRay .complex{color:#a08}
.CodeRay .constant,.CodeRay .predefined-constant{color:teal}
.CodeRay .color{color:#099}
.CodeRay .class-variable{color:#369}
.CodeRay .decorator{color:#b0b}
.CodeRay .definition{color:#099}
.CodeRay .delimiter{color:#000}
.CodeRay .doc{color:#970}
.CodeRay .doctype{color:#34b}
.CodeRay .doc-string{color:#d42}
.CodeRay .escape{color:#666}
.CodeRay .entity{color:#800}
.CodeRay .error{color:#808}
.CodeRay .exception{color:inherit}
.CodeRay .filename{color:#099}
.CodeRay .function{color:#900;font-weight:bold}
.CodeRay .global-variable{color:teal}
.CodeRay .hex{color:#058}
.CodeRay .integer,.CodeRay .float{color:#099}
.CodeRay .include{color:#555}
.CodeRay .inline{color:#000}
.CodeRay .inline .inline{background:#ccc}
.CodeRay .inline .inline .inline{background:#bbb}
.CodeRay .inline .inline-delimiter{color:#d14}
.CodeRay .inline-delimiter{color:#d14}
.CodeRay .important{color:#555;font-weight:bold}
.CodeRay .interpreted{color:#b2b}
.CodeRay .instance-variable{color:teal}
.CodeRay .label{color:#970}
.CodeRay .local-variable{color:#963}
.CodeRay .octal{color:#40e}
.CodeRay .predefined{color:#369}
.CodeRay .preprocessor{color:#579}
.CodeRay .pseudo-class{color:#555}
.CodeRay .directive{font-weight:bold}
.CodeRay .type{font-weight:bold}
.CodeRay .predefined-type{color:inherit}
.CodeRay .reserved,.CodeRay .keyword{color:#000;font-weight:bold}
.CodeRay .key{color:#808}
.CodeRay .key .delimiter{color:#606}
.CodeRay .key .char{color:#80f}
.CodeRay .value{color:#088}
.CodeRay .regexp .delimiter{color:#808}
.CodeRay .regexp .content{color:#808}
.CodeRay .regexp .modifier{color:#808}
.CodeRay .regexp .char{color:#d14}
.CodeRay .regexp .function{color:#404;font-weight:bold}
.CodeRay .string{color:#d20}
.CodeRay .string .string .string{background:#ffd0d0}
.CodeRay .string .content{color:#d14}
.CodeRay .string .char{color:#d14}
.CodeRay .string .delimiter{color:#d14}
.CodeRay .shell{color:#d14}
.CodeRay .shell .delimiter{color:#d14}
.CodeRay .symbol{color:#990073}
.CodeRay .symbol .content{color:#a60}
.CodeRay .symbol .delimiter{color:#630}
.CodeRay .tag{color:teal}
.CodeRay .tag-special{color:#d70}
.CodeRay .variable{color:#036}
.CodeRay .insert{background:#afa}
.CodeRay .delete{background:#faa}
.CodeRay .change{color:#aaf;background:#007}
.CodeRay .head{color:#f8f;background:#505}
.CodeRay .insert .insert{color:#080}
.CodeRay .delete .delete{color:#800}
.CodeRay .change .change{color:#66f}
.CodeRay .head .head{color:#f4f}
&lt;/style&gt;&lt;/head&gt;&lt;body class=&#34;article&#34;&gt;&lt;header&gt;&lt;/header&gt;&lt;div id=&#34;content&#34;&gt;&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_一目标&#34;&gt;一、目标&lt;/h2&gt;&lt;p&gt;2023年了，MD5已经是最基础的签名算法了，但如果你还只是对输入做了简单的MD5，肯定会被同行们嘲笑。加点盐（salt）是一种基本的提升，但在这个就业形势严峻的时代，仅仅加盐肯定不够了。&lt;/p&gt;
&lt;p&gt;今天我们就来讲一讲魔改的MD5，让这个算法高大上起来。&lt;/p&gt;
&lt;p&gt;1、菜卷&lt;/p&gt;
&lt;p&gt;最简单的魔改方法就是改变MD5的初始参数，&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;     context-&amp;gt;state[&lt;span class=&#34;integer&#34;&gt;0&lt;/span&gt;] = &lt;span class=&#34;hex&#34;&gt;0x67452301&lt;/span&gt;;
     context-&amp;gt;state[&lt;span class=&#34;integer&#34;&gt;1&lt;/span&gt;] = &lt;span class=&#34;hex&#34;&gt;0xEFCDAB89&lt;/span&gt;;
     context-&amp;gt;state[&lt;span class=&#34;integer&#34;&gt;2&lt;/span&gt;] = &lt;span class=&#34;hex&#34;&gt;0x98BADCFE&lt;/span&gt;;
     context-&amp;gt;state[&lt;span class=&#34;integer&#34;&gt;3&lt;/span&gt;] = &lt;span class=&#34;hex&#34;&gt;0x10325476&lt;/span&gt;;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;把这四个参数修改一下就行了。通过修改这些参数，我们可以改变MD5的运算结果。但这种方法实在太简单了，卷不起来。&lt;/p&gt;
&lt;p&gt;接下来，我们要介绍更高级的卷法。&lt;/p&gt;
&lt;p&gt;2、肉卷&lt;/p&gt;
&lt;p&gt;md5会进行64轮运算，每轮运算都会用到一个常量，组成一个常量表K。&lt;/p&gt;
&lt;p&gt;K原始值的计算方式是 2^32 * |sin i |，而后取其整数部分。&lt;/p&gt;
&lt;p&gt;那么有理想的同学就可以更改这个K值，比如把 sin改成 cos或者tan之类的，这样就可以卷起来了。&lt;/p&gt;
&lt;p&gt;3、卷中卷&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;comment&#34;&gt;//F,G,H,I四个非线性变换函数&lt;/span&gt;
&lt;span class=&#34;preprocessor&#34;&gt;#define&lt;/span&gt; F(x,y,z) ((x &amp;amp; y) | (~x &amp;amp; z))
&lt;span class=&#34;preprocessor&#34;&gt;#define&lt;/span&gt; G(x,y,z) ((x &amp;amp; z) | (y &amp;amp; ~z))
&lt;span class=&#34;preprocessor&#34;&gt;#define&lt;/span&gt; H(x,y,z) (x^y^z)
&lt;span class=&#34;preprocessor&#34;&gt;#define&lt;/span&gt; I(x,y,z) (y ^ (x | ~z))
&lt;span class=&#34;comment&#34;&gt;//x循环左移n位的操作&lt;/span&gt;
&lt;span class=&#34;preprocessor&#34;&gt;#define&lt;/span&gt; ROTATE_LEFT(x,n) ((x &amp;lt;&amp;lt; n) | (x &amp;gt;&amp;gt; (&lt;span class=&#34;integer&#34;&gt;32&lt;/span&gt;-n)))&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;要真正卷起来，我们需要改变MD5中的四个非线性变换函数F、G、H、I。我们可以加上 &lt;mark&gt;异或&lt;/mark&gt; 或者 减少 &lt;mark&gt;与&lt;/mark&gt; 操作，整个算法就换了个面貌。这种高级卷法可以忽悠住老板，让算法高大上起来。&lt;/p&gt;
&lt;p&gt;我们今天的目标是尝试还原一个魔改之后的MD5算法，通过这次实践来了解算法还原的基本方法。&lt;/p&gt;
&lt;p&gt;这个样本我们的入参是字符串:  &lt;mark&gt;&amp;#34;1677038066553&amp;#34;&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;返回值是32个字符：  &lt;mark&gt;&amp;#34;DD89CA684D91818B970710F75A75743D&amp;#34;&lt;/mark&gt;&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_二步骤&#34;&gt;二、步骤&lt;/h2&gt;&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_第一步&#34;&gt;第一步&lt;/h3&gt;&lt;div class=&#34;literal-block&#34;&gt;&lt;pre&gt;我们需要用Unidbg跑通算法，比起上古时期用ida调试的前辈，Unidbg的出现直接把算法还原的难度降了一个数量级。&lt;/pre&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-2&#34;&gt;&lt;h3 id=&#34;_第二步&#34;&gt;第二步&lt;/h3&gt;&lt;div class=&#34;literal-block&#34;&gt;&lt;pre&gt;我们需要把结果Z通过反向推导一步一步回到原始输入A。这种方法叫做倒果为因，是逆向分析的一种基本套路。&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&#34;literal-block&#34;&gt;&lt;pre&gt;我们假设这个样本是MD5或者是魔改的MD5，我们可以用以下几种方法来还原算法：&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&#34;literal-block&#34;&gt;&lt;pre&gt;1、调试断点&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&#34;literal-block&#34;&gt;&lt;pre&gt;2、条件断点&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&#34;literal-block&#34;&gt;&lt;pre&gt;3、数据打印&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&#34;literal-block&#34;&gt;&lt;pre&gt;4、Trace内存读写&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&#34;literal-block&#34;&gt;&lt;pre&gt;5、Trace代码&lt;/pre&gt;&lt;/div&gt;
&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_1调试断点&#34;&gt;1、调试断点&lt;/h4&gt;&lt;p&gt;逆向分析是经验科学，虽然有一些基本套路，但是还是以试为主，先用IDA打开 libnative-lib.so，从 Exports 导出表里面找到导出函数 &lt;mark&gt;Java_com_littleq_cryptography_md5_MainActivity_sign&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;这个函数的开始地址在0x1234, 结束地址在0x12B4,但是主要的代码逻辑在函数sub_A3C里面， 我们先在sub_A3C函数的末端下个断点试试，&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;label&#34;&gt;text:&lt;/span&gt;&lt;span class=&#34;octal&#34;&gt;00000000000011&lt;/span&gt;D4 E0 &lt;span class=&#34;octal&#34;&gt;07&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;40&lt;/span&gt; F9                 LDR             X0, [SP,&lt;span class=&#34;preprocessor&#34;&gt;#0x110&lt;/span&gt;+var_108]
.text:&lt;span class=&#34;octal&#34;&gt;00000000000011&lt;/span&gt;D8 &lt;span class=&#34;octal&#34;&gt;03&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;00&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;00&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;90&lt;/span&gt;+                ADRL            X3, aSSSS ; &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;%s%s%s%s&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;
.text:&lt;span class=&#34;octal&#34;&gt;00000000000011&lt;/span&gt;D8 &lt;span class=&#34;integer&#34;&gt;63&lt;/span&gt; EC &lt;span class=&#34;integer&#34;&gt;0&lt;/span&gt;A &lt;span class=&#34;integer&#34;&gt;91&lt;/span&gt;
.text:&lt;span class=&#34;octal&#34;&gt;0000000000001&lt;/span&gt;&lt;span class=&#34;float&#34;&gt;1&lt;/span&gt;E0 E4 &lt;span class=&#34;integer&#34;&gt;83&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;01&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;91&lt;/span&gt;                 ADD             X4, SP, &lt;span class=&#34;preprocessor&#34;&gt;#0x110&lt;/span&gt;+var_B0
.text:&lt;span class=&#34;octal&#34;&gt;0000000000001&lt;/span&gt;&lt;span class=&#34;float&#34;&gt;1&lt;/span&gt;E4 E5 &lt;span class=&#34;integer&#34;&gt;43&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;01&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;91&lt;/span&gt;                 ADD             X5, SP, &lt;span class=&#34;preprocessor&#34;&gt;#0x110&lt;/span&gt;+var_C0
.text:&lt;span class=&#34;octal&#34;&gt;0000000000001&lt;/span&gt;&lt;span class=&#34;float&#34;&gt;1&lt;/span&gt;E8 E6 &lt;span class=&#34;octal&#34;&gt;03&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;01&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;91&lt;/span&gt;                 ADD             X6, SP, &lt;span class=&#34;preprocessor&#34;&gt;#0x110&lt;/span&gt;+var_D0
.text:&lt;span class=&#34;octal&#34;&gt;0000000000001&lt;/span&gt;&lt;span class=&#34;float&#34;&gt;1&lt;/span&gt;EC E7 C3 &lt;span class=&#34;octal&#34;&gt;00&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;91&lt;/span&gt;                 ADD             X7, SP, &lt;span class=&#34;preprocessor&#34;&gt;#0x110&lt;/span&gt;+var_E0
.text:&lt;span class=&#34;octal&#34;&gt;0000000000001&lt;/span&gt;&lt;span class=&#34;float&#34;&gt;1F&lt;/span&gt;&lt;span class=&#34;integer&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;01&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;00&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;80&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;92&lt;/span&gt;                 MOV             X1, &lt;span class=&#34;preprocessor&#34;&gt;#0xFFFFFFFFFFFFFFFF&lt;/span&gt;
.text:&lt;span class=&#34;octal&#34;&gt;0000000000001&lt;/span&gt;&lt;span class=&#34;float&#34;&gt;1F&lt;/span&gt;&lt;span class=&#34;integer&#34;&gt;4&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;02&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;08&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;80&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;52&lt;/span&gt;                 MOV             W2, &lt;span class=&#34;preprocessor&#34;&gt;#0x40&lt;/span&gt; ; &lt;span class=&#34;char&#34;&gt;&amp;#39;@&amp;#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这个 0x11D8 很像是格式化字符串。&lt;/p&gt;
&lt;p&gt;我们在Unidbg里面给 0x11D8 下个断点&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;java&#34;&gt;    Debugger &lt;span class=&#34;keyword&#34;&gt;debugger&lt;/span&gt; = emulator.attach();
    &lt;span class=&#34;keyword&#34;&gt;debugger&lt;/span&gt;.addBreakPoint(module.base + &lt;span class=&#34;hex&#34;&gt;0x11D8&lt;/span&gt;);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;运行一下，顺利的断下来了&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;java&#34;&gt;&lt;span class=&#34;keyword&#34;&gt;debugger&lt;/span&gt; &lt;span class=&#34;keyword&#34;&gt;break&lt;/span&gt; at: &lt;span class=&#34;hex&#34;&gt;0x400011d8&lt;/span&gt; &lt;span class=&#34;error&#34;&gt;@&lt;/span&gt; Function64 address=&lt;span class=&#34;hex&#34;&gt;0x40001234&lt;/span&gt;, arguments=[unidbg&lt;span class=&#34;error&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;hex&#34;&gt;0xfffe1640&lt;/span&gt;[libandroid.so]&lt;span class=&#34;hex&#34;&gt;0x640&lt;/span&gt;, &lt;span class=&#34;integer&#34;&gt;1853170425&lt;/span&gt;, &lt;span class=&#34;integer&#34;&gt;2008362258&lt;/span&gt;]
&amp;gt;&amp;gt;&amp;gt; x0=&lt;span class=&#34;hex&#34;&gt;0xbffff690&lt;/span&gt;(-&lt;span class=&#34;integer&#34;&gt;1073744240&lt;/span&gt;) x1=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x2=&lt;span class=&#34;hex&#34;&gt;0x4&lt;/span&gt; x3=&lt;span class=&#34;hex&#34;&gt;0xbfffed20&lt;/span&gt; x4=&lt;span class=&#34;hex&#34;&gt;0x40230200&lt;/span&gt; x5=&lt;span class=&#34;hex&#34;&gt;0x402302c0&lt;/span&gt; x6=&lt;span class=&#34;hex&#34;&gt;0x1&lt;/span&gt; x7=&lt;span class=&#34;hex&#34;&gt;0xbffff708&lt;/span&gt; x8=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x9=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x10=&lt;span class=&#34;hex&#34;&gt;0x1&lt;/span&gt; x11=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x12=&lt;span class=&#34;hex&#34;&gt;0x8&lt;/span&gt; x13=&lt;span class=&#34;hex&#34;&gt;0x8&lt;/span&gt; x14=&lt;span class=&#34;hex&#34;&gt;0x8&lt;/span&gt;
&amp;gt;&amp;gt;&amp;gt; x15=&lt;span class=&#34;hex&#34;&gt;0x8&lt;/span&gt; x16=&lt;span class=&#34;hex&#34;&gt;0x40228d70&lt;/span&gt; x17=&lt;span class=&#34;hex&#34;&gt;0x40177ddc&lt;/span&gt; x18=&lt;span class=&#34;hex&#34;&gt;0x8&lt;/span&gt; x19=&lt;span class=&#34;hex&#34;&gt;0x4cf3a208&lt;/span&gt; x20=&lt;span class=&#34;hex&#34;&gt;0x400012b8&lt;/span&gt; x21=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x22=&lt;span class=&#34;hex&#34;&gt;0x68ca89dd&lt;/span&gt; x23=&lt;span class=&#34;hex&#34;&gt;0x3d74755a&lt;/span&gt; x24=&lt;span class=&#34;hex&#34;&gt;0x72e737bb&lt;/span&gt; x25=&lt;span class=&#34;hex&#34;&gt;0xddf5ac1&lt;/span&gt; x26=&lt;span class=&#34;hex&#34;&gt;0xd0d5adc6&lt;/span&gt; x27=&lt;span class=&#34;hex&#34;&gt;0x8b81914d&lt;/span&gt; x28=&lt;span class=&#34;hex&#34;&gt;0xf7100797&lt;/span&gt; fp=&lt;span class=&#34;hex&#34;&gt;0xbffff680&lt;/span&gt;
LR=RX&lt;span class=&#34;error&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;hex&#34;&gt;0x400011d4&lt;/span&gt;[libnative-lib.so]&lt;span class=&#34;hex&#34;&gt;0x11d4&lt;/span&gt;
SP=&lt;span class=&#34;hex&#34;&gt;0xbffff570&lt;/span&gt;
PC=RX&lt;span class=&#34;error&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;hex&#34;&gt;0x400011d8&lt;/span&gt;[libnative-lib.so]&lt;span class=&#34;hex&#34;&gt;0x11d8&lt;/span&gt;
nzcv: N=&lt;span class=&#34;integer&#34;&gt;0&lt;/span&gt;, Z=&lt;span class=&#34;integer&#34;&gt;1&lt;/span&gt;, C=&lt;span class=&#34;integer&#34;&gt;1&lt;/span&gt;, V=&lt;span class=&#34;integer&#34;&gt;0&lt;/span&gt;, EL0, use SP_EL0
start + &lt;span class=&#34;hex&#34;&gt;0xae8&lt;/span&gt;
=&amp;gt; *[libnative-lib.so*&lt;span class=&#34;hex&#34;&gt;0x011d8&lt;/span&gt;]*[&lt;span class=&#34;integer&#34;&gt;03000090&lt;/span&gt;]*&lt;span class=&#34;hex&#34;&gt;0x400011d8&lt;/span&gt;:*&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;adrp x3, #0x40001000&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;
    [libnative-lib.so &lt;span class=&#34;hex&#34;&gt;0x011dc&lt;/span&gt;] [&lt;span class=&#34;integer&#34;&gt;63&lt;/span&gt;ec0a91] &lt;span class=&#34;hex&#34;&gt;0x400011dc&lt;/span&gt;: &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;add x3, x3, #0x2bb&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;
    [libnative-lib.so &lt;span class=&#34;hex&#34;&gt;0x011e0&lt;/span&gt;] [e4830191] &lt;span class=&#34;hex&#34;&gt;0x400011e0&lt;/span&gt;: &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;add x4, sp, #0x60&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;
    [libnative-lib.so &lt;span class=&#34;hex&#34;&gt;0x011e4&lt;/span&gt;] [e5430191] &lt;span class=&#34;hex&#34;&gt;0x400011e4&lt;/span&gt;: &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;add x5, sp, #0x50&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;
    [libnative-lib.so &lt;span class=&#34;hex&#34;&gt;0x011e8&lt;/span&gt;] [e6030191] &lt;span class=&#34;hex&#34;&gt;0x400011e8&lt;/span&gt;: &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;add x6, sp, #0x40&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;
    [libnative-lib.so &lt;span class=&#34;hex&#34;&gt;0x011ec&lt;/span&gt;] [e7c30091] &lt;span class=&#34;hex&#34;&gt;0x400011ec&lt;/span&gt;: &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;add x7, sp, #0x30&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;
    [libnative-lib.so &lt;span class=&#34;hex&#34;&gt;0x011f0&lt;/span&gt;] [&lt;span class=&#34;integer&#34;&gt;01008092&lt;/span&gt;] &lt;span class=&#34;hex&#34;&gt;0x400011f0&lt;/span&gt;: &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;mov x1, #-1&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;
    [libnative-lib.so &lt;span class=&#34;hex&#34;&gt;0x011f4&lt;/span&gt;] [&lt;span class=&#34;integer&#34;&gt;02088052&lt;/span&gt;] &lt;span class=&#34;hex&#34;&gt;0x400011f4&lt;/span&gt;: &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;mov w2, #0x40&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;
    [libnative-lib.so &lt;span class=&#34;hex&#34;&gt;0x011f8&lt;/span&gt;] [&lt;span class=&#34;integer&#34;&gt;5&lt;/span&gt;bfdff97] &lt;span class=&#34;hex&#34;&gt;0x400011f8&lt;/span&gt;: &lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;bl #0x40000764&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;在Arm汇编里面，调用一个函数之前，会把入参存入到 x0,x1,x2 …​…​&lt;/p&gt;
&lt;p&gt;从这段代码可以看出 地址 0x400011f8 会调用 0x40000764 函数，并且传入了 7个参数， 从x0，一直赋值到x7。&lt;/p&gt;
&lt;p&gt;Unidbg的调试虽然有些简陋，但是已经够用了，有如此神器在手，你还要啥自行车？&lt;/p&gt;
&lt;p&gt;调试命令先掌握以下几个：&lt;/p&gt;
&lt;p&gt;s 单步步入，就是遇到函数调用会进入。&lt;/p&gt;
&lt;p&gt;n 单步步过，遇到函数调用不会进入函数。&lt;/p&gt;
&lt;p&gt;c 继续执行&lt;/p&gt;
&lt;p&gt;b 下断点&lt;/p&gt;
&lt;p&gt;r 取消当前断点&lt;/p&gt;
&lt;p&gt;m 查看内存&lt;/p&gt;
&lt;p&gt;我们先 s s s 几下，单步执行到 0x400011f8&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;debugger &lt;span class=&#34;keyword&#34;&gt;break&lt;/span&gt; at: &lt;span class=&#34;hex&#34;&gt;0x400011f8&lt;/span&gt; &lt;span class=&#34;error&#34;&gt;@&lt;/span&gt; Function64 address=&lt;span class=&#34;hex&#34;&gt;0x40001234&lt;/span&gt;, arguments=[unidbg&lt;span class=&#34;error&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;hex&#34;&gt;0xfffe1640&lt;/span&gt;[libandroid.so]&lt;span class=&#34;hex&#34;&gt;0x640&lt;/span&gt;, &lt;span class=&#34;integer&#34;&gt;1853170425&lt;/span&gt;, &lt;span class=&#34;integer&#34;&gt;2008362258&lt;/span&gt;]
&amp;gt;&amp;gt;&amp;gt; x0=&lt;span class=&#34;hex&#34;&gt;0xbffff690&lt;/span&gt;(-&lt;span class=&#34;integer&#34;&gt;1073744240&lt;/span&gt;) x1=&lt;span class=&#34;hex&#34;&gt;0xffffffffffffffff&lt;/span&gt; x2=&lt;span class=&#34;hex&#34;&gt;0x40&lt;/span&gt; x3=&lt;span class=&#34;hex&#34;&gt;0x400012bb&lt;/span&gt; x4=&lt;span class=&#34;hex&#34;&gt;0xbffff5d0&lt;/span&gt; x5=&lt;span class=&#34;hex&#34;&gt;0xbffff5c0&lt;/span&gt; x6=&lt;span class=&#34;hex&#34;&gt;0xbffff5b0&lt;/span&gt; x7=&lt;span class=&#34;hex&#34;&gt;0xbffff5a0&lt;/span&gt; x8=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x9=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x10=&lt;span class=&#34;hex&#34;&gt;0x1&lt;/span&gt; x11=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x12=&lt;span class=&#34;hex&#34;&gt;0x8&lt;/span&gt; x13=&lt;span class=&#34;hex&#34;&gt;0x8&lt;/span&gt; x14=&lt;span class=&#34;hex&#34;&gt;0x8&lt;/span&gt;
LR=RX&lt;span class=&#34;error&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;hex&#34;&gt;0x400011d4&lt;/span&gt;[libnative-lib.so]&lt;span class=&#34;hex&#34;&gt;0x11d4&lt;/span&gt;
SP=&lt;span class=&#34;hex&#34;&gt;0xbffff570&lt;/span&gt;
PC=RX&lt;span class=&#34;error&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;hex&#34;&gt;0x400011f8&lt;/span&gt;[libnative-lib.so]&lt;span class=&#34;hex&#34;&gt;0x11f8&lt;/span&gt;
nzcv: N=&lt;span class=&#34;integer&#34;&gt;0&lt;/span&gt;, Z=&lt;span class=&#34;integer&#34;&gt;1&lt;/span&gt;, C=&lt;span class=&#34;integer&#34;&gt;1&lt;/span&gt;, V=&lt;span class=&#34;integer&#34;&gt;0&lt;/span&gt;, EL0, use SP_EL0
start + &lt;span class=&#34;hex&#34;&gt;0xb08&lt;/span&gt;
=&amp;gt; *[libnative-lib.so*&lt;span class=&#34;hex&#34;&gt;0x011f8&lt;/span&gt;]*[&lt;span class=&#34;integer&#34;&gt;5&lt;/span&gt;bfdff97]*&lt;span class=&#34;hex&#34;&gt;0x400011f8&lt;/span&gt;:*&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;bl #0x40000764&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这个时间点，入参都已经准备好了，我们来一个一个看看这些入参。&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;mx7

&amp;gt;-----------------------------------------------------------------------------&amp;lt;
[&lt;span class=&#34;integer&#34;&gt;10&lt;/span&gt;:&lt;span class=&#34;integer&#34;&gt;40&lt;/span&gt;:&lt;span class=&#34;integer&#34;&gt;26&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;646&lt;/span&gt;]x7=unidbg&lt;span class=&#34;error&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;hex&#34;&gt;0xbffff5a0&lt;/span&gt;, md5=d6c164ca9ef531557fc14e1bf7173663,
size: &lt;span class=&#34;integer&#34;&gt;112&lt;/span&gt;
&lt;span class=&#34;octal&#34;&gt;0000&lt;/span&gt;: &lt;span class=&#34;integer&#34;&gt;35&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;41&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;37&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;35&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;37&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;34&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;33&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;44&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;00&lt;/span&gt; B3 &lt;span class=&#34;integer&#34;&gt;22&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;40&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;00&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;00&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;00&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;00&lt;/span&gt;    &lt;span class=&#34;integer&#34;&gt;5&lt;/span&gt;A75743D..&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;@....
0010: 39 37 30 37 31 30 46 37 00 8D 09 40 00 00 00 00    970710F7...@....
0020: 34 44 39 31 38 31 38 42 00 77 12 40 02 00 00 00    4D91818B.w.@....
0030: 44 44 38 39 43 41 36 38 00 1B 17 40 02 00 00 00    DD89CA68...@....
0040: 31 36 37 37 30 33 38 30 36 36 35 35 33 80 00 00    1677038066553...
0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
^-----------------------------------------------------------------------------^&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;可以看到这次调用 函数 0x40000764， 基本就是在组装最后的结果了。&lt;/p&gt;
&lt;p&gt;我们要做的就是找到这些结果生成的位置，来分析最终结果是如何计算出来的，也就是 Y → Z 的过程。&lt;/p&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-3&#34;&gt;&lt;h4 id=&#34;_4trace内存读写&#34;&gt;4、Trace内存读写&lt;/h4&gt;&lt;p&gt;现在我们已经知道了结果Z的位置，下一步就是需要知道谁计算出了Z。&lt;/p&gt;
&lt;p&gt;这就需要用到Unidbg的一个强大功能：内存读写监控&lt;/p&gt;
&lt;p&gt;这一次我们先把调试断点下早一点，在 sub_A3C 函数开头就断下来。&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;debugger &lt;span class=&#34;keyword&#34;&gt;break&lt;/span&gt; at: &lt;span class=&#34;hex&#34;&gt;0x40000a3c&lt;/span&gt; &lt;span class=&#34;error&#34;&gt;@&lt;/span&gt; Function64 address=&lt;span class=&#34;hex&#34;&gt;0x40001234&lt;/span&gt;, arguments=[unidbg&lt;span class=&#34;error&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;hex&#34;&gt;0xfffe1640&lt;/span&gt;[libandroid.so]&lt;span class=&#34;hex&#34;&gt;0x640&lt;/span&gt;, &lt;span class=&#34;integer&#34;&gt;1853170425&lt;/span&gt;, &lt;span class=&#34;integer&#34;&gt;2008362258&lt;/span&gt;]
&amp;gt;&amp;gt;&amp;gt; x0=&lt;span class=&#34;hex&#34;&gt;0x40004000&lt;/span&gt; x1=&lt;span class=&#34;hex&#34;&gt;0xbffff690&lt;/span&gt; x2=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x3=&lt;span class=&#34;hex&#34;&gt;0x1&lt;/span&gt; x4=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x5=&lt;span class=&#34;hex&#34;&gt;0x1&lt;/span&gt; x6=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x7=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x8=&lt;span class=&#34;hex&#34;&gt;0xfffe0a70&lt;/span&gt; x9=&lt;span class=&#34;hex&#34;&gt;0x3002&lt;/span&gt; x10=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x11=&lt;span class=&#34;hex&#34;&gt;0x1&lt;/span&gt; x12=&lt;span class=&#34;hex&#34;&gt;0x3&lt;/span&gt; x13=&lt;span class=&#34;hex&#34;&gt;0x40003018&lt;/span&gt; x14=&lt;span class=&#34;hex&#34;&gt;0x40003028&lt;/span&gt;
&amp;gt;&amp;gt;&amp;gt; x15=&lt;span class=&#34;hex&#34;&gt;0x1&lt;/span&gt; x16=&lt;span class=&#34;hex&#34;&gt;0x40228910&lt;/span&gt; x17=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x18=&lt;span class=&#34;hex&#34;&gt;0x17&lt;/span&gt; x19=&lt;span class=&#34;hex&#34;&gt;0xfffe1640&lt;/span&gt; x20=&lt;span class=&#34;hex&#34;&gt;0xbffff708&lt;/span&gt; x21=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x22=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x23=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x24=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x25=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x26=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x27=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x28=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; fp=&lt;span class=&#34;hex&#34;&gt;0xbffff6f0&lt;/span&gt;
LR=RX&lt;span class=&#34;error&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;hex&#34;&gt;0x40001280&lt;/span&gt;[libnative-lib.so]&lt;span class=&#34;hex&#34;&gt;0x1280&lt;/span&gt;
SP=&lt;span class=&#34;hex&#34;&gt;0xbffff690&lt;/span&gt;
PC=RX&lt;span class=&#34;error&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;hex&#34;&gt;0x40000a3c&lt;/span&gt;[libnative-lib.so]&lt;span class=&#34;hex&#34;&gt;0xa3c&lt;/span&gt;
nzcv: N=&lt;span class=&#34;integer&#34;&gt;0&lt;/span&gt;, Z=&lt;span class=&#34;integer&#34;&gt;0&lt;/span&gt;, C=&lt;span class=&#34;integer&#34;&gt;1&lt;/span&gt;, V=&lt;span class=&#34;integer&#34;&gt;0&lt;/span&gt;, EL0, use SP_EL0
start + &lt;span class=&#34;hex&#34;&gt;0x34c&lt;/span&gt;
=&amp;gt; *[libnative-lib.so*&lt;span class=&#34;hex&#34;&gt;0x00a3c&lt;/span&gt;]*[ff8304d1]*&lt;span class=&#34;hex&#34;&gt;0x40000a3c&lt;/span&gt;:*&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;sub sp, sp, #0x120&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;

traceWrite &lt;span class=&#34;hex&#34;&gt;0xbffff5d0&lt;/span&gt; &lt;span class=&#34;hex&#34;&gt;0xbffff5d8&lt;/span&gt;
Set trace &lt;span class=&#34;hex&#34;&gt;0xbffff5d0&lt;/span&gt;-&amp;gt;&lt;span class=&#34;hex&#34;&gt;0xbffff5d8&lt;/span&gt; memory write success.
c
[&lt;span class=&#34;integer&#34;&gt;11&lt;/span&gt;:&lt;span class=&#34;integer&#34;&gt;41&lt;/span&gt;:&lt;span class=&#34;integer&#34;&gt;41&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;656&lt;/span&gt;] Memory WRITE at &lt;span class=&#34;hex&#34;&gt;0xbffff5d8&lt;/span&gt;, data size = &lt;span class=&#34;integer&#34;&gt;1&lt;/span&gt;, data value = &lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt;, PC=RX&lt;span class=&#34;error&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;hex&#34;&gt;0x40001168&lt;/span&gt;[libnative-lib.so]&lt;span class=&#34;hex&#34;&gt;0x1168&lt;/span&gt;, LR=null
[&lt;span class=&#34;integer&#34;&gt;11&lt;/span&gt;:&lt;span class=&#34;integer&#34;&gt;41&lt;/span&gt;:&lt;span class=&#34;integer&#34;&gt;41&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;657&lt;/span&gt;] Memory WRITE at &lt;span class=&#34;hex&#34;&gt;0xbffff5d0&lt;/span&gt;, data size = &lt;span class=&#34;integer&#34;&gt;8&lt;/span&gt;, data value = &lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt;, PC=RX&lt;span class=&#34;error&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;hex&#34;&gt;0x4000116c&lt;/span&gt;[libnative-lib.so]&lt;span class=&#34;hex&#34;&gt;0x116c&lt;/span&gt;, LR=null
[&lt;span class=&#34;integer&#34;&gt;11&lt;/span&gt;:&lt;span class=&#34;integer&#34;&gt;41&lt;/span&gt;:&lt;span class=&#34;integer&#34;&gt;41&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;661&lt;/span&gt;] Memory WRITE at &lt;span class=&#34;hex&#34;&gt;0xbffff5d8&lt;/span&gt;, data size = &lt;span class=&#34;integer&#34;&gt;1&lt;/span&gt;, data value = &lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt;, PC=RX&lt;span class=&#34;error&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;hex&#34;&gt;0x401b48cc&lt;/span&gt;[libc.so]&lt;span class=&#34;hex&#34;&gt;0x648cc&lt;/span&gt;, LR=RX&lt;span class=&#34;error&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;hex&#34;&gt;0x401b48c8&lt;/span&gt;[libc.so]&lt;span class=&#34;hex&#34;&gt;0x648c8&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;traceWrite 就是监控写内存命令。&lt;/p&gt;
&lt;p&gt;看上去0xbffff5d0这段内存，写入 &lt;mark&gt;DD89CA68&lt;/mark&gt; 数据的位置是： 0x116c&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;label&#34;&gt;text:&lt;/span&gt;&lt;span class=&#34;octal&#34;&gt;000000000000114&lt;/span&gt;C &lt;span class=&#34;integer&#34;&gt;14&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;00&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;00&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;90&lt;/span&gt;+                ADRL            X20, unk_12B8
.text:&lt;span class=&#34;octal&#34;&gt;000000000000114&lt;/span&gt;C &lt;span class=&#34;integer&#34;&gt;94&lt;/span&gt; E2 &lt;span class=&#34;integer&#34;&gt;0&lt;/span&gt;A &lt;span class=&#34;integer&#34;&gt;91&lt;/span&gt;
.text:&lt;span class=&#34;octal&#34;&gt;0000000000001154&lt;/span&gt; C4 &lt;span class=&#34;integer&#34;&gt;0&lt;/span&gt;A C0 &lt;span class=&#34;integer&#34;&gt;5&lt;/span&gt;A                 REV             W4, W22
.text:&lt;span class=&#34;octal&#34;&gt;00000000000011&lt;/span&gt;&lt;span class=&#34;integer&#34;&gt;58&lt;/span&gt; E0 &lt;span class=&#34;integer&#34;&gt;83&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;01&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;91&lt;/span&gt;                 ADD             X0, SP, &lt;span class=&#34;preprocessor&#34;&gt;#0x110&lt;/span&gt;+var_B0
.text:&lt;span class=&#34;octal&#34;&gt;000000000000115&lt;/span&gt;C &lt;span class=&#34;integer&#34;&gt;21&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;01&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;80&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;52&lt;/span&gt;                 MOV             W1, &lt;span class=&#34;preprocessor&#34;&gt;#9&lt;/span&gt;
.text:&lt;span class=&#34;octal&#34;&gt;0000000000001160&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;22&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;01&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;80&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;52&lt;/span&gt;                 MOV             W2, &lt;span class=&#34;preprocessor&#34;&gt;#9&lt;/span&gt;
.text:&lt;span class=&#34;octal&#34;&gt;0000000000001164&lt;/span&gt; E3 &lt;span class=&#34;octal&#34;&gt;03&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;14&lt;/span&gt; AA                 MOV             X3, X20
.text:&lt;span class=&#34;octal&#34;&gt;00000000000011&lt;/span&gt;&lt;span class=&#34;integer&#34;&gt;68&lt;/span&gt; FF A3 &lt;span class=&#34;octal&#34;&gt;01&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;39&lt;/span&gt;                 STRB            WZR, [SP,&lt;span class=&#34;preprocessor&#34;&gt;#0x110&lt;/span&gt;+var_A8]
.text:&lt;span class=&#34;octal&#34;&gt;000000000000116&lt;/span&gt;C FF &lt;span class=&#34;integer&#34;&gt;33&lt;/span&gt; &lt;span class=&#34;octal&#34;&gt;00&lt;/span&gt; F9                 STR             XZR, [SP,&lt;span class=&#34;preprocessor&#34;&gt;#0x110&lt;/span&gt;+var_B0]
.text:&lt;span class=&#34;octal&#34;&gt;0000000000001170&lt;/span&gt; &lt;span class=&#34;integer&#34;&gt;7&lt;/span&gt;D FD FF &lt;span class=&#34;integer&#34;&gt;97&lt;/span&gt;                 BL              sub_764&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;0x116c 的指令 STR XZR 是写入 没错，但是看上去不像是写入数据，而是把  &lt;mark&gt;SP,#0x110+var_B0&lt;/mark&gt; 这个地址的数据清零。&lt;/p&gt;
&lt;p&gt;那我们重来一次，(Unidbg的优点就是可以无限重放，比真机调试App方便了不知道多少倍。)&lt;/p&gt;
&lt;p&gt;这次往前一点点，在 0x114C 下断点。&lt;/p&gt;
&lt;p&gt;断下来之后，每s单步一次之后，就去查看 m0xbffff5d0。&lt;/p&gt;
&lt;p&gt;最后发现跑完 0x1170 ,  0xbffff5d0内存的值就改变成了， &lt;mark&gt;DD89CA68&lt;/mark&gt; 。 这说明  0xbffff5d0 是 sub_764 函数去写的。&lt;/p&gt;
&lt;div class=&#34;listing-block&#34;&gt;&lt;pre class=&#34;CodeRay highlight nowrap&#34;&gt;&lt;code data-lang=&#34;cpp&#34;&gt;debugger &lt;span class=&#34;keyword&#34;&gt;break&lt;/span&gt; at: &lt;span class=&#34;hex&#34;&gt;0x40001170&lt;/span&gt; &lt;span class=&#34;error&#34;&gt;@&lt;/span&gt; Function64 address=&lt;span class=&#34;hex&#34;&gt;0x40001234&lt;/span&gt;, arguments=[unidbg&lt;span class=&#34;error&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;hex&#34;&gt;0xfffe1640&lt;/span&gt;[libandroid.so]&lt;span class=&#34;hex&#34;&gt;0x640&lt;/span&gt;, &lt;span class=&#34;integer&#34;&gt;1853170425&lt;/span&gt;, &lt;span class=&#34;integer&#34;&gt;2008362258&lt;/span&gt;]
&amp;gt;&amp;gt;&amp;gt; x0=&lt;span class=&#34;hex&#34;&gt;0xbffff5d0&lt;/span&gt;(-&lt;span class=&#34;integer&#34;&gt;1073744432&lt;/span&gt;) x1=&lt;span class=&#34;hex&#34;&gt;0x9&lt;/span&gt; x2=&lt;span class=&#34;hex&#34;&gt;0x9&lt;/span&gt; x3=&lt;span class=&#34;hex&#34;&gt;0x400012b8&lt;/span&gt; x4=&lt;span class=&#34;hex&#34;&gt;0xdd89ca68&lt;/span&gt; x5=&lt;span class=&#34;hex&#34;&gt;0xe6cd8e62&lt;/span&gt; x6=&lt;span class=&#34;hex&#34;&gt;0x24523012&lt;/span&gt; x7=&lt;span class=&#34;hex&#34;&gt;0x29b9c389&lt;/span&gt; x8=&lt;span class=&#34;hex&#34;&gt;0x40&lt;/span&gt; x9=&lt;span class=&#34;hex&#34;&gt;0x40318041&lt;/span&gt; x10=&lt;span class=&#34;hex&#34;&gt;0xbffff5e0&lt;/span&gt; x11=&lt;span class=&#34;hex&#34;&gt;0x40&lt;/span&gt; x12=&lt;span class=&#34;hex&#34;&gt;0x3d5ebb2b&lt;/span&gt; x13=&lt;span class=&#34;hex&#34;&gt;0x6450c165&lt;/span&gt; x14=&lt;span class=&#34;hex&#34;&gt;0xfc63b7e7&lt;/span&gt;
&amp;gt;&amp;gt;&amp;gt; x15=&lt;span class=&#34;hex&#34;&gt;0x49ac16b&lt;/span&gt; x16=&lt;span class=&#34;hex&#34;&gt;0xac6af723&lt;/span&gt; x17=&lt;span class=&#34;hex&#34;&gt;0xf3d1564b&lt;/span&gt; x18=&lt;span class=&#34;hex&#34;&gt;0x18&lt;/span&gt; x19=&lt;span class=&#34;hex&#34;&gt;0x4cf3a208&lt;/span&gt; x20=&lt;span class=&#34;hex&#34;&gt;0x400012b8&lt;/span&gt; x21=&lt;span class=&#34;hex&#34;&gt;0x0&lt;/span&gt; x22=&lt;span class=&#34;hex&#34;&gt;0x68ca89dd&lt;/span&gt; x23=&lt;span class=&#34;hex&#34;&gt;0x3d74755a&lt;/span&gt; x24=&lt;span class=&#34;hex&#34;&gt;0x72e737bb&lt;/span&gt; x25=&lt;span class=&#34;hex&#34;&gt;0xddf5ac1&lt;/span&gt; x26=&lt;span class=&#34;hex&#34;&gt;0xd0d5adc6&lt;/span&gt; x27=&lt;span class=&#34;hex&#34;&gt;0x8b81914d&lt;/span&gt; x28=&lt;span class=&#34;hex&#34;&gt;0xf7100797&lt;/span&gt; fp=&lt;span class=&#34;hex&#34;&gt;0xbffff680&lt;/span&gt;
LR=null
SP=&lt;span class=&#34;hex&#34;&gt;0xbffff570&lt;/span&gt;
PC=RX&lt;span class=&#34;error&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;hex&#34;&gt;0x40001170&lt;/span&gt;[libnative-lib.so]&lt;span class=&#34;hex&#34;&gt;0x1170&lt;/span&gt;
nzcv: N=&lt;span class=&#34;integer&#34;&gt;0&lt;/span&gt;, Z=&lt;span class=&#34;integer&#34;&gt;1&lt;/span&gt;, C=&lt;span class=&#34;integer&#34;&gt;1&lt;/span&gt;, V=&lt;span class=&#34;integer&#34;&gt;0&lt;/span&gt;, EL0, use SP_EL0
start + &lt;span class=&#34;hex&#34;&gt;0xa80&lt;/span&gt;
=&amp;gt; *[libnative-lib.so*&lt;span class=&#34;hex&#34;&gt;0x01170&lt;/span&gt;]*[&lt;span class=&#34;integer&#34;&gt;7&lt;/span&gt;dfdff97]*&lt;span class=&#34;hex&#34;&gt;0x40001170&lt;/span&gt;:*&lt;span class=&#34;string&#34;&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;content&#34;&gt;bl #0x40000764&lt;/span&gt;&lt;span class=&#34;delimiter&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;不过回到 0x1170,我们发现了一串熟悉的数字 &lt;mark&gt;x4=0xdd89ca68&lt;/mark&gt; ， 好吧，我们的问题又变成了 x4的值是怎么算出来的？&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section class=&#34;doc-section level-1&#34;&gt;&lt;h2 id=&#34;_三总结&#34;&gt;三、总结&lt;/h2&gt;&lt;p&gt;首先要习惯看Arm汇编，一步一步单步调试，然后熟悉寄存器的变化。特别对一些关键数字要敏感。&lt;/p&gt;
&lt;p&gt;要掌握Unidbg的基础调试命令。&lt;/p&gt;
&lt;p&gt;常见的加密算法要熟悉一下，在开发环境里多调试几遍，熟悉它的算法流程。&lt;/p&gt;
&lt;figure class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/Md5/ffshow.jpg&#34; alt=&#34;ffshow&#34; height=&#34;，50&#34;/&gt;
&lt;figcaption&gt;1:ffshow&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;mark&gt;多方分别，是非之窦易开；一味圆融，人我之见不立。&lt;/mark&gt;&lt;/p&gt;
&lt;aside class=&#34;admonition-block tip&#34; role=&#34;doc-tip&#34;&gt;&lt;h6 class=&#34;block-title label-only&#34;&gt;&lt;span class=&#34;title-label&#34;&gt;Tip: &lt;/span&gt;&lt;/h6&gt;&lt;p&gt;: 本文的目的只有一个就是学习更多的逆向技巧和思路，如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担，和本文以及作者没关系，本文涉及到的代码项目可以去 &lt;mark&gt;奋飞的朋友们&lt;/mark&gt; 知识星球自取，欢迎加入知识星球一起学习探讨技术。有问题可以加我wx: &lt;mark&gt;fenfei331&lt;/mark&gt; 讨论下。&lt;/p&gt;&lt;/aside&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ffzsxq.jpg&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;
&lt;p&gt;关注微信公众号，最新技术干货实时推送&lt;/p&gt;
&lt;div class=&#34;image-block&#34;&gt;&lt;img src=&#34;http://91fans.com.cn/img/ff330.png&#34; alt=&#34;100&#34;/&gt;&lt;/div&gt;&lt;/section&gt;&lt;/div&gt;&lt;footer&gt;&lt;div id=&#34;footer-text&#34;&gt;&lt;br/&gt;Last updated 2026-04-27 18:48:44 +0800&lt;/div&gt;&lt;/footer&gt;
</description>
      
    </item>
    
  </channel>
</rss>
