<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>rootkiter</title>
<link href="/atom.xml" rel="self"/>
<link href="" />
<updated>2020-12-23T11:55:14+00:00</updated>
<id>http://rootkiter.github.io/</id>
<author>
<name>RootKiter</name>
<email>2559964169@qq.com</email>
</author>

<entry>
	<title>ISC2020 议题汇总</title>
        <link href="/2020/08/15/ISC2020%E5%A5%BD%E8%AE%AE%E9%A2%98%E6%B1%87%E6%80%BB.html"/>
	<updated>2020-08-15T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2020/08/15/ISC2020好议题汇总</id>
	<content type="html">&lt;h2 id=&quot;引&quot;&gt;引&lt;/h2&gt;

&lt;p&gt;受疫情因素影响，2020年，国内安全行业的两个重要的安全大会ISC和BCS都开启了线上
参会渠道，议题数量和规模也较之前几届增加了不少。云参会几天下来，整体感觉比线
下参会效果更好，收获更多。线下参会时，经常因为不同论坛的 议题冲突/演讲时间/
议题顺序/听讲走神/突遇熟人, 等诸多不可控因素，导致想听的议题没听全，或者没听到，
甚至由于各个分论坛位置分散，也会导致参会中大量的时间被浪费在赶场的路上。&lt;/p&gt;

&lt;p&gt;线上参会则完美解决了所有这些问题，我甚至觉得，这种会议早就该这么举办了。&lt;/p&gt;

&lt;p&gt;通过几天的观看，个人感觉收获还是挺大的。这里单独整理一个技术类干货列表，并配有
简单的点评，供时间不充裕的小伙伴们自行查阅。同时该列表将一直更新，像ISC2020 的
口号一样永不闭幕。也欢迎各位读者通过邮箱(rootkiter@rootkiter.com)的方式挖掘更多
的干货视频到这里。&lt;/p&gt;

&lt;h2 id=&quot;isc2020-干货&quot;&gt;ISC2020 干货&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;舒首衡 – 《&lt;a href=&quot;https://isc.360.com/2020/detail.html?id=37&amp;amp;vid=545&quot;&gt;网络安全保险解决方案&lt;/a&gt;》&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;点评&lt;/strong&gt;: “卖网络安全保险”前两年老周曾经提过这个事，我一直以为是个玩笑。结果，
没想到，还真有这样的公司。不过听了他的演讲，我觉得，“卖保险”完全是另一个领域的
东西，是一个从另外的领域解决安全问题的思路。确实有点意思。&lt;/p&gt;

&lt;p&gt;https://isc.360.com/2020/detail.html?id=37&amp;amp;vid=545&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;宋申雷 – 《&lt;a href=&quot;https://isc.360.com/2020/detail.html?vid=135&amp;amp;id=22&quot;&gt;基于高级威胁情报狩猎APT组织&lt;/a&gt;》&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;点评&lt;/strong&gt;: 按照以往的开会经验，很少看到副院长这个级别的大佬出来讲纯技术，原因
其实很简单，安全这个圈子很小，细分到一个具体领域之后，议题受众群就更小了。
在线下的会议中，参会的人很多，但其实真正的受众可能只有1-2个人，在这样的背景下
大佬出来演讲，对大佬来说就很不划算，有这个时间还不如解决个问题来的实在。但是
这种线上会议就不同了，一次演讲过后，多少年之后都可以继续查看，这就扩大了一次
演讲的受众群。如此的收益，就可以一试了。所以大佬们也就都出来搞分享了。具体到
这个议题之中，则是大佬所在团队如何基于威胁情报发现并跟踪海莲花APT组织，也让我
了解到现代的APT攻击事件，是如何进行的，有哪些步骤，实际攻击时的效果和威力又如
何。&lt;/p&gt;

&lt;p&gt;https://isc.360.com/2020/detail.html?vid=135&amp;amp;id=22&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;赵光远 – 《&lt;a href=&quot;https://isc.360.com/2020/detail.html?vid=170&amp;amp;id=23&quot;&gt;疫情之下黑产的索财之道&lt;/a&gt;》&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;点评&lt;/strong&gt;：这个议题讲了我们内部代号为pink的一个僵尸网络。这是个影响很大的僵尸
网络，而且涉及到的技术面非常广阔，背后是个在多领域都很专业的人（或团伙），
其实我从去年11月份就在关注并参与处置这个僵尸网络，但受疫情影响，处置工作一
直没有结束，所以我们一直也没敢公开发报告。这里就借机会简单补充下背景信息吧。
pink 在去年10月份到11月份之间和厂商展开了非常激烈的攻防对抗，他们貌似没有看到，
稍稍有些遗憾，算是错过了一出好戏。至于 github 那个页面，背后其实也有一段故事。
更多内容就不方便说了，希望以后有机会公开吧。&lt;/p&gt;

&lt;p&gt;https://isc.360.com/2020/detail.html?vid=170&amp;amp;id=23&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;杜元正 – 《&lt;a href=&quot;https://isc.360.com/2020/detail.html?vid=169&amp;amp;id=23&quot;&gt;基于图卷积神经网络的恶意样本家族分类&lt;/a&gt;》&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;点评&lt;/strong&gt;: 安全行业内常见的恶意样本分类需求，一般集中在二分类的需求，用途也很固
定就是样本判黑，但随着安全行业的发展，二分类需求已经无法提供更详尽的信息，供安
全人员了解样本背后的信息。近几年，越来越多的安全从业者开始加入这个领域，试图从
样本中挖掘到更多的信息。其实这个方向也是我最近在研究的方向，所以对这个议题很有
感觉。议题前半部分内容和我手头的工作有点类似，所以没太提起我的兴趣，但是后半部
分关于脱壳的研究，却让我有些眼前一亮。讲者在分析恶意样本的过程中，会遇到不少带
壳样本，他基于 “机器学习+沙箱定制” 的方式提供了一种比较新的脱壳思路。&lt;/p&gt;

&lt;p&gt;https://isc.360.com/2020/detail.html?vid=169&amp;amp;id=23&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;徐洋 – 《&lt;a href=&quot;https://isc.360.com/2020/detail.html?id=23&amp;amp;vid=145&quot;&gt;通过数据分析拿网站&lt;/a&gt;》&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;点评&lt;/strong&gt;：讲者本身是做数据分析的技术专家，他的工作内容也不是做渗透的。但当数据
分析领域遇到渗透领域之后，奇妙的事情就发生了。当他以一个全新的视角审视渗透测试
之后，反而可以成为一个网站收割机。所以，我也一直认为：对于技术人员来说，技术的
深度和广度同样重要。技术深度为立身之本，技术广度却可以让你抵达更广阔的世界。&lt;/p&gt;

&lt;p&gt;https://isc.360.com/2020/detail.html?id=23&amp;amp;vid=145&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;张在峰 – 《&lt;a href=&quot;https://isc.360.com/2020/detail.html?vid=135&amp;amp;id=22&quot;&gt;评估威胁情报中的IOC&lt;/a&gt;》&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;点评&lt;/strong&gt;：威胁情报火了好多年，就如同天上的云，好看但不好用，一直无法真正的落地并
指导企业安全生产。这中间有个很严重的问题，就是：威胁情报在流动过程中，每经过
一个节点都会丢失一部分细节，当流到客户手里的时候，除了域名和MD5，其他信息所剩
无几，各情报厂商手中的IOC都很多，但能够解读手中情报的情报商却基本没有，能解读
每一条IOC背后故事的情报商更是寥寥无几。所以如果想切实的解决自身安全问题，必然要
对情报商提供的情报质量做判别，只有对每一条情报有足够的信心，才可以切实的落实
到生产环境中，为企业提供安全防护。所以我认为本议题中提出的评估方法很重要，不
可不看。&lt;/p&gt;

&lt;p&gt;https://isc.360.com/2020/detail.html?vid=135&amp;amp;id=22&lt;/p&gt;

&lt;h1 id=&quot;尾&quot;&gt;尾&lt;/h1&gt;

&lt;p&gt;ISC 上的议题也没听全，暂时就整理了上面这些内容，本列表会不定期更新。如果你发现
好的议题，也欢迎邮件推荐我一下，如果内容确实不错，我也会整理过来的。&lt;/p&gt;
</content>
</entry>

<entry>
	<title><<一道即将尘封十几年的封印，不来尝试解开吗？>>第八关Write-Up</title>
        <link href="/2020/06/27/%E4%B8%80%E9%81%93%E5%8D%B3%E5%B0%86%E5%B0%98%E5%B0%81%E5%8D%81%E5%87%A0%E5%B9%B4%E7%9A%84%E5%B0%81%E5%8D%B0-%E4%B8%8D%E6%9D%A5%E5%B0%9D%E8%AF%95%E8%A7%A3%E5%BC%80%E5%90%97-%E7%AC%AC%E5%85%AB%E5%85%B3%E8%A7%A3.html"/>
	<updated>2020-06-27T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2020/06/27/<<一道即将尘封十几年的封印，不来尝试解开吗？>>第八关解</id>
	<content type="html">&lt;h2 id=&quot;引&quot;&gt;引&lt;/h2&gt;

&lt;p&gt;腾讯安全平台，最近开启了一个线上解谜游戏，题目构思很是巧妙，像个套娃一样，先给出一段代码
每打开一层，里面还有一层，一直指向最终的第八关。玩过的小伙伴们也是深陷其中难以自拔。凑个
热闹我也试着解了一下第八关。应该说这一关设计的比较巧妙，所以这里
简单整理一下解题思路，供小伙伴们自行参阅。&lt;/p&gt;

&lt;p&gt;原题目链接: «&lt;a href=&quot;https://mp.weixin.qq.com/s/tZ9BmXfzGYpzrNm2Jl5Mrw&quot;&gt;一道即将尘封十几年的封印，不来尝试解开吗？&lt;/a&gt;»&lt;/p&gt;

&lt;h2 id=&quot;原题描述&quot;&gt;原题描述&lt;/h2&gt;

&lt;p&gt;将第七关的密码输入后，将会看到第八关的关卡题目，如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2020_06_27_15_30/level8_Subject.png&quot; alt=&quot;subject&quot; /&gt;&lt;/p&gt;

&lt;p&gt;其中，第 2 行代码，给了一个提示，“时间可能非常长…”，这表明本题核心其实是一个
代码/算法优化类题目。&lt;/p&gt;

&lt;p&gt;随后，3-6 行代码分别代表虚拟机的“栈/指令长度/寄存器/代码”等结构，&lt;/p&gt;

&lt;p&gt;再后，7-28 行实现了一套简易的虚拟机系统;&lt;/p&gt;

&lt;p&gt;最后，第30行，为通关密码的结果。&lt;/p&gt;

&lt;p&gt;综上，题目中其实是构造了一个轻巧的虚拟机，麻雀虽小却五脏俱全。它包含16个寄存器，
15种指令码，加/减/乘/除/取余/入栈/出栈/循环/跳转，各类型指令具在。&lt;/p&gt;

&lt;p&gt;不难看出命题人真是花了很多心思在里面，这样用心的
题目值得我花时间探究一下。事实也证明，我在通关后仍然意犹未尽，这样的
感觉已经很久没有过了，畅快。&lt;/p&gt;

&lt;h2 id=&quot;题意分析&quot;&gt;题意分析&lt;/h2&gt;

&lt;p&gt;通读虚拟机代码，不难发现，本题目的几个核心的点：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;一个本意考察算法优化的题目，题面却是个虚拟机;&lt;/li&gt;
  &lt;li&gt;第6行的 code 为虚拟机实际执行的代码指令;&lt;/li&gt;
  &lt;li&gt;reg[15] 为指令寄存器，相当于 X86 架构下的 EIP 寄存器。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;综合分析以上三点，要解决这个问题，大概分两步：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;伪代码还原（俗语说的：逆向分析）&lt;/li&gt;
  &lt;li&gt;代码/算法优化&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;巧的是，这两项，都踩在了我的感兴趣点上，所以，我应该解决它。&lt;/p&gt;

&lt;h2 id=&quot;解题&quot;&gt;解题&lt;/h2&gt;

&lt;h3 id=&quot;伪代码还原&quot;&gt;伪代码还原&lt;/h3&gt;

&lt;p&gt;伪代码还原，对我来说还原代码并不难，只是有点花精力，
只要抓住，reg[15] 是指令寄存器，code 为虚拟代码，再配合上阅读每一条 if-else 语句，
相信任何人都能够轻松解决 code 内容到伪代码的还原。还原后的伪代码如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2020_06_27_15_30/level8_asmcode.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;其中每一行内容中：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;第一列: 代码在 code 中的偏移，可近似理解为指令地址;  &lt;br /&gt;
第二列: 指令长度，这是依据指令码 ins 在 ins_len 中查询到的结果;&lt;br /&gt;
第三列: 指令码 ins  ; &lt;br /&gt;
其他  : 是指令的伪代码。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;仔细阅读这段代码，不难发现，10-27 的伪代码其实是一个循环代码段，对应的
循环寄存器是 reg_2，其初始化代码的地址为 off-57 。这段循环，在代码中表现为一个二层循环，
分别由，28 和 30 地址的代码控制跳回。而每次外层循环，都会将 reg_2 压栈，也就是说：
这是个 O(n^2) 复杂度的代码，循环的代码段将执行至少 n^2 次（具体执行多少次我也懒得
算了，总之这段代码如果要执行完，大概得执行个几天几夜才能出结果吧）。&lt;/p&gt;

&lt;p&gt;要想快速算出通关 key 值，不做优化是不行的。但优化之前，得先把它转化成一段
逻辑清晰的代码才能理清逻辑。所以，我把这段代码又做了进一步还原，如下图所示:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2020_06_27_15_30/level8_python.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;通过阅读这段代码，程序逻辑就非常清晰了。我是用递归调用 Factorial 函数的方式描述
那两层循环的。而循环代码段的具体操作在 calc 函数中。主函数中，只要将运算后的
r0 和 r1 寄存器的值，打出来，就是最终的通关 key 了。&lt;/p&gt;

&lt;h3 id=&quot;优化分析&quot;&gt;优化分析&lt;/h3&gt;

&lt;p&gt;这段代码的优化核心在于 Factorial 函数。这是一个递归调用的函数。需要把它的时间复杂度
进行降级优化，但是它每一次递归调用都依赖前一次调用 calc 后的 r0/r1 值。也就是说，
要想优化这段代码，首先要将 calc 的逻辑进行抽象，如果能为它建立一个通项公式，
就最完美了。&lt;/p&gt;

&lt;p&gt;继续分析 calc 的代码，不难发现，99999999999999997 这个值非常地可疑。通过搜索引擎，
我们可以迅速知道这是一个比较大的 质数（素数）。而了解过“密码学”或者学过“离散数学”
的读者都知道，质数取余这个操作，有很多奇妙的性质。
也就是说，这段代码值得挖掘。继续研究，可以得到如下的推导过程:&lt;/p&gt;

&lt;p&gt;令：r0 为 A, r1 为 B，则，calc 函数对 (A1, B1) 可以描述为（暂时先不考虑取余操作）:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A1 = 3 * A0 + 9 * B0&lt;br /&gt;
B1 = 7 * A0 + 8 * B0&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;再迭代一级后，(A2, B2) 可描述为：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A2 = 3 * ( 3 * A0 + 9 * B0 ) + 9 * ( 7 * A0 + 8 * B0 )&lt;br /&gt;
B2 = 7 * ( 3 * A0 + 9 * B0 ) + 8 * ( 7 * A0 + 8 * B0 )&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;这种非等差数列的元组，似乎不存在容易观察的通项公式。
但，这些数学式子却让我想起了“矩阵乘法”，
如果用“矩阵”描述上面的逻辑, 不难得到如下内容:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2020_06_27_15_30/level8_A1B1_Matrix.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;和&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2020_06_27_15_30/level8_A2B2_Matrix.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;而矩阵乘法，满足结合律，所以，很容易就可以得到下面的式子：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2020_06_27_15_30/level8_AnBn_Matrix.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;拿到这个公式，就比较完美了，它意味着：“中间所有的循环迭代，本质上都只是对前面系数矩阵的
乘法操作，当需要运算最终结果时，再把 (A0, B0) 带入到上面的式子，就能一步求出 (An, Bn)。&lt;/p&gt;

&lt;p&gt;这时，不要忘记前面忽略的“素数取余”操作，但是，我们知道素数取余这个操作满足分配律:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2020_06_27_15_30/level8_AB_ModN.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;也就是说，我可以把取余这个操作，分配到每一次运算的过程之中。它和矩阵运算的逻辑完全不冲突。&lt;/p&gt;

&lt;p&gt;至此，优化分析的过程完成。对这段代码优化的任务完全可解。&lt;/p&gt;

&lt;h4 id=&quot;代码算法优化&quot;&gt;代码/算法优化&lt;/h4&gt;

&lt;p&gt;拿到了 calc 的通项公式后，下一步就是大刀阔斧的改造 Factorial 函数了，基于通项公式，
我们知道，Factorial 函数的本质是系数矩阵的乘法，我们只要拿到通项公式中的 n 值，
就可以算出最终结果，而依赖 reg_2 的初始值 127 ，所以实际的 n 值应该是 (2^127-1) 
粗看一眼，这个数应该还是挺大的。于此同时矩阵幂运算对取余也没听到过什么特性。
这里就需要再进一步考虑这个问题了。&lt;/p&gt;

&lt;p&gt;其实类似的问题，在现代密码学中会经常遇到，在实现各种密码学库的过程中，
会遇到各种指数级别的运算优化。这样的问题对于这些“密码学库”来说完全是小菜一碟。
更幸运的是，我工作之后，有一个系统学习“密码学库实现”的机会。&lt;/p&gt;

&lt;p&gt;所以我知道，在基于“椭圆曲线”的运算中，有一个使用“倍点计算”的优化方案。
它的核心优化思路：“把某些计算（“点乘”运算）得到的中间结果保存下来，
再把它使用到最终的运算中。”。其实，这个思路就非常符合现在遇到的这个问题，
虽然通项公式中 n 这个数值本身是 2^n 级别的一个值。但我可以用保存幂级运算中间结果
的方式去追赶它，换句话说，如果我把系数矩阵中每一个 2^n 的幂次存起来，得到一个
2^n 幂次的矩阵结果表，再用这个结果表去计算最终的值，就可以非常快的算出最终结果了。
而且，在计算 2^n 这个过程中的每一次计算，其实都是前一次计算结果的倍乘，这样，我只需要循环127次，
就可以得到最终的系数矩阵结果了。这样可就完美多了。&lt;/p&gt;

&lt;p&gt;基于这个思路，我最终完成了对这段代码的优化，虽然最终代码只有40行，但看完上面的解题过程，
应该也能知道，这几行代码的编写其实并不容易，最终代码的截图如下：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2020_06_27_15_30/level8_Finally.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;其中 getRealResult 函数，就是带入 (A0, B0) 计算出最终结果的函数。 MatrixMul 是矩阵乘法
的实现函数。MatrixMap 是计算系数矩阵乘法的函数，SqueareMapMatrix 是计算系数矩阵 2^n
次幂结果表的函数，FactorialMatrix 是优化后的 Factorial 函数，该函数依赖矩阵表，计算出
系数矩阵的最终结果。&lt;/p&gt;

&lt;p&gt;主函数，就是用来拿到第八关最终 key 的调用过程。&lt;/p&gt;

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;

&lt;p&gt;这里附上过程中的两个代码文件，供读者自行参阅:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/rootkiter/rootkiter.github.io/tree/master/files/level8&quot;&gt;level8_codes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;虽然这是一道解谜的题目，但它的本质却是一道数学题。数学是工具，工具就是生产力。&lt;/p&gt;

&lt;p&gt;想深入下去做技术，其实永远也离不开数学。我们每天都在使用数学推演结果带来的便利，却抱怨
学数学无用，数学会觉得冤的。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>武汉肺炎的一些思考</title>
        <link href="/2020/02/04/%E6%AD%A6%E6%B1%89%E8%82%BA%E7%82%8E%E7%9A%84%E4%B8%80%E4%BA%9B%E6%80%9D%E8%80%83.html"/>
	<updated>2020-02-04T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2020/02/04/武汉肺炎的一些思考</id>
	<content type="html">&lt;h2 id=&quot;疫情&quot;&gt;疫情&lt;/h2&gt;

&lt;p&gt;截止目前，全国确诊病例已经超过2万人，实际的真实情况可能要更加糟糕，单从公开的信息来看，
武汉的医疗资源至少超负荷运转两个多星期了。&lt;/p&gt;

&lt;p&gt;全国从1月24日开始陆续进入居家隔离状态，连偏远山区都进入隔离状态了，本周起大量在职员工开始居家办公。可以
预见在数月之内，国内所有餐饮旅游相关行业将全部受到影响。国际上，各国家陆续终止互飞航班。在疫情得不到缓解
之前，相信这个状态会一直持续下去。&lt;/p&gt;

&lt;h2 id=&quot;自然选择&quot;&gt;自然选择&lt;/h2&gt;

&lt;p&gt;打从地球形成，自然界的一切就面临着适者生存的考验。每天都有无数的物种从地球上消失，又有新的物种在孕育。
自然灾难就像一个过滤器，把运气不好的那一部分剔除掉，留下运气好的。生物学家说，人类的DNA上有很多无效的片段，
这些片段很可能是曾经某些病毒留下的印记。还有专家说，他们从冰川中发现了一个上亿年前的陨石，这个陨石里有细菌。
还推测这可能是地球上能出现生命的根本原因。&lt;/p&gt;

&lt;p&gt;所以，人类之所以存在，只有一个原因，那就是运气好。碰巧一批陨石砸到了
地球的海洋里，又碰巧人类的始祖生物没有被病毒弄死。这次的疫情，可能就是一次“普通的”自然选择，地球上的人太多了，到了该
筛一筛的时候了。&lt;/p&gt;

&lt;h2 id=&quot;国家&quot;&gt;国家&lt;/h2&gt;

&lt;p&gt;这次疫情，再一次让我重新认识了“国家机器”的“力量”，一天之内就可以让全国所有城市进入居家隔离状态，两天之内就
可以让各村县也进入隔离状态。一个星期就可以盖起两座大型传染病专科医院，一夜之间就可以建起三个野战性质的“方舱医院”。
这些都让我重新认识了国家的强大，还让我产生了莫名其妙的优越感。但另一方面，国家的问题仍然很多，比如：在科技的时代，
还用双黄连可以治病毒的谣言愚弄大众，更让人匪夷所思的是，还真有人选择相信。&lt;/p&gt;

&lt;h2 id=&quot;p民&quot;&gt;P民&lt;/h2&gt;

&lt;p&gt;海外的自媒体忙着借机“解放”中国，海内的自媒体则忙着传播阴谋论。无论这些自媒体说的多么奇思妙想/漏洞百出，
还是有一大堆 P民会相信。P民们只选择那些符合自己口味的言论，而对另外那些更合理而不对胃口的言论视而不见/冷嘲热讽。
P民永远是P民，骂不醒。&lt;/p&gt;

&lt;h2 id=&quot;网友&quot;&gt;网友&lt;/h2&gt;

&lt;p&gt;疫情爆发后，全国人民进入居家隔离状态，有劲无处使的网友们，开始挖掘这个社会的各种阴暗面。从翻相关论文paper，
到指责湖北政府不作为；从云监工“火神山/雷神山”建造医院，到扒出“红十字”腐烂透顶的现状。&lt;/p&gt;

&lt;p&gt;还有很多网友在用千奇百怪的行为，证明：人类是一种群居动物，关几天后真的会疯。&lt;/p&gt;

&lt;h2 id=&quot;紧急物资&quot;&gt;紧急物资&lt;/h2&gt;

&lt;p&gt;这次疫情，暴露了人类的脆弱。“武汉独特的地理位置”和“中国春节这个特殊的节假日”联合组成了一个放大器，
疫情被瞬间传到了大江南北。全国的“口罩/酒精”都被平民抢光。全世界的医疗物资都陆续流入中国湖北。
好在前段北京发现鼠疫患者时准备了口罩，不然恐怕这回就真抓瞎了。&lt;/p&gt;

&lt;h2 id=&quot;应急包&quot;&gt;应急包&lt;/h2&gt;

&lt;p&gt;等本次疫情度过之后，计划准备一批应急包，遇到突发事件背上就能跑的那种。&lt;/p&gt;

&lt;p&gt;构思应急包匹配场景：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1. 优先匹配：火灾/核辐射/瘟疫/生化威胁/地震；  
2. 次级匹配：战争/野外生存。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;未来&quot;&gt;未来&lt;/h2&gt;

&lt;p&gt;疫情是灾难，更是契机，灾难终将过去，人类还会继续延续下去。SARS 期间创建了网购和物流的体系，这次疫情可能会让
远程办公的进程加速。它让我们看到了社会的阴暗面，也给了我们一个反思和完善的机会。过去的几十年里我们一直忙着发展经济，
却忽略了其他短板。其实只有强大的经济，是没法成为真正的强国的，我们还要有与之匹配的“教育”/“医疗”和“社会保障”，
只有把所有的短板都补上，中国才会真正的成为一个强国，人类也才会有未来。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>分享一个 Hex 编辑插件，顺便聊一聊VI/VIM</title>
        <link href="/2019/11/16/VIM%E4%B8%8B%E7%9A%84Hex%E7%BC%96%E8%BE%91%E6%8F%92%E4%BB%B6.html"/>
	<updated>2019-11-16T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2019/11/16/VIM下的Hex编辑插件</id>
	<content type="html">&lt;h2 id=&quot;构思很久了&quot;&gt;构思很久了&lt;/h2&gt;

&lt;p&gt;一直想给 VIM 写个方便 Hex 编辑的插件，总是不确定能否实现，
所以想了好几年，前阵子恶补了一下 VIMScript 的帮助，
发现这个引擎自身语法还是挺完备的，虽然提供的接口很零散，
直觉上绕几个圈还是有机会的。&lt;/p&gt;

&lt;p&gt;一鼓作气完成后，发个开源项目
&lt;a href=&quot;http://rootkiter.com/vim-hexedit/&quot;&gt;vim-HexEdit&lt;/a&gt;给感兴趣的筒子们用着玩吧。&lt;/p&gt;

&lt;p&gt;不过呢，本文却不是为了介绍插件的，而是聊一下我对 VIM 和 VIMScript 的理解。&lt;/p&gt;

&lt;h2 id=&quot;如何理解-vivim&quot;&gt;如何理解 VI/VIM&lt;/h2&gt;

&lt;p&gt;在程序员的圈子里一直流传着把 VIM 变成 IDE 的各种绝学，越传越神，越看越帅。
萌新们照猫画虎的塞了一大堆插件，塞完后才发现，关文件找不到按钮，开文件慢的要死，
新鲜劲一过，留了一句这玩意学习曲线太陡，又回去拥抱 IDE 了。&lt;/p&gt;

&lt;p&gt;其实是一些故作高深的人把 VIM 神话了，它就是个文本编辑器，
如果它真能完美替代 IDE，那就不会出现那么多现代 IDE 了。&lt;/p&gt;

&lt;p&gt;其实 VIM 的历史想必大家都听过，它是从 VI 继承过来的。项目在
&lt;a href=&quot;https://github.com/vim/vim&quot;&gt;VIM&lt;/a&gt; 本以为是个很大的项目，结果主程序员只有一个人。
代码发过去后，由他亲自测试提交。&lt;/p&gt;

&lt;p&gt;VIM 真正的优势其实是大部分操作系统都会内置它，而且具有超强跨平台能力，
比如你家里的智能路由器上都可能有它的影子，这样的能力是 Eclipse/VS 等 IDE 无法超越的。&lt;/p&gt;

&lt;p&gt;相当于你学会了使用 VIM 后，可以在任何环境下写代码，所以作为一个靠技术吃饭的
攻城狮，VIM 其实是非常值得学习的技能，虽然学习起来慢一些，但掌握它确实可以获益。&lt;/p&gt;

&lt;p&gt;使用 VIM 的时候要注意，现代的工程目录越来越复杂，已经复杂到 VIM 插件也很难
完全兼顾的状态。对于这种情况去找专业的 IDE 吧，时间是有限的，少跳一个坑是一个坑。&lt;/p&gt;

&lt;p&gt;如果你有一天想认真的学习 VIM 的时候，我私藏的配置项目
&lt;a href=&quot;https://github.com/rootkiter/vimhome/&quot;&gt;Vimhone&lt;/a&gt;可能会是一个不错的开始。
这套基础配置我用了好多年了，期间微调很多次，近两年才逐步固定下来。
在它的帮助下我写过 C/Python/Go/Shell/VIMScript 等等不同类型语言的代码。
可以说是很耐用的基础配置，最近简单装修了一下，加了个帮助文档，祝萌新们上手愉快。&lt;/p&gt;

&lt;h2 id=&quot;如何理解-vimscript&quot;&gt;如何理解 VIMScript&lt;/h2&gt;

&lt;p&gt;掌握 VIMScript 是开发 VIM 插件的基础，它能够同 VIM 无缝联动。当熟练使用 VIM 后，
对 VIM 产生新要求后，就是到了该掌握 VIMScript 的时候了，想要快速掌握 VIMScript,
要抓住三个关键点：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1. 正则表达式。在VIM中，很多操作都是基于正则表达式来提速的。好在这东西是
    程序员经常用到的知识，应该还好。记得经常查阅 `:help pattern-overview\&amp;lt;CR&amp;gt;`
2. 理解 VIM 的事件触发机制。VIMScript 的很多逻辑是基于事件触发来实现的。
    VIMScript 本身不具有入口函数的概念，它更像是由很多回调函数组成的，
    VIM 在切换到某一状态之前或之后，会发出一个事件，而这个事件会触发调用 
    VIMScript 中的相关函数。多多测试 `:help autocmd-events\&amp;lt;CR&amp;gt;` 
    里面的各种事件，总会找到一款适合你。
3. 了解内置函数。VIM 提供了丰富的内置函数支持，界面交互，光标控制，缓冲区控制，
    进制转换等等一系列的函数。`:help functions\&amp;lt;CR&amp;gt;` 多去逛逛没坏处。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;嘻嘻&quot;&gt;嘻嘻&lt;/h1&gt;

&lt;p&gt;本博客停更了 2 年多，是因为伤心了。有些小伙伴应该知道，这域名在 Google 安全情报
中被标黑了两年，浏览器打开时会被警告为恶意页面，本以为无救了，近期偶然发现似乎
解封了，可能是我之前做的一些抢救机制终于生效了吧。No matter what, it’s clean, 
I’m happy. 一种 “我胡汉三又回来了” 的兴奋感。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>新写的几个Python模块</title>
        <link href="/2017/05/02/Python_modules.html"/>
	<updated>2017-05-02T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2017/05/02/Python_modules</id>
	<content type="html">&lt;h2 id=&quot;模块功能&quot;&gt;模块功能&lt;/h2&gt;

&lt;p&gt;最近工作中经常遇到&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;数据比对&lt;br /&gt;
hex 数值输出&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;这些功能很简单，但已有的解决方案普遍很笨重，不适合快速验证结论的场景。&lt;/p&gt;

&lt;p&gt;所以简单整理了一下近期的需求，写了几个基础模块，并放在&lt;a href=&quot;https://github.com/rootkiter/easycode&quot;&gt;github上&lt;/a&gt;，用的时候 curl/wget 一下即可直接用了，这样会舒服一些。&lt;/p&gt;

&lt;h2 id=&quot;制表模块&quot;&gt;制表模块&lt;/h2&gt;

&lt;h3 id=&quot;为了续命&quot;&gt;为了续命&lt;/h3&gt;
&lt;p&gt;很多时刻，我只想得到一个这样的表格，以便找到程序中的 Bug 或者对比一坨新数据：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;+-------+-----------------+-----------------+--------+
|       |      title1     |      title2     | title3 |
+-------+-----------------+-----------------+--------+
| item1 |       Hello 1*1 | Hello 1*2 AAAAA |     20 |
| item2 | Hello 2*1 BBBBB |       Hello 2*2 |    500 |
+-------+-----------------+-----------------+--------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;原始的重量级做法是配置一个简单的 Django 服务器，写一段配套代码，去展示。
而轻量一些的做法是将每一次的处理结果拷贝到 excel 表格中用表格去做统计分析。&lt;/p&gt;

&lt;p&gt;如果每天都面对不同纬度的数据，每一次分析都要用无数次实验才能得到合理结果，你就会有想死的冲动了（不开玩笑，最近一直在研读《死亡美学》这本书，收获颇丰）。&lt;/p&gt;

&lt;p&gt;最终我只好写个模块为自己续命，tablemap 肩上的重担很重呀。&lt;/p&gt;

&lt;h3 id=&quot;如何获取&quot;&gt;如何获取&lt;/h3&gt;

&lt;p&gt;输入以下命令即可获得到最新版的模块。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wget https://raw.githubusercontent.com/rootkiter/easycode/master/tablemap.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在文件的 __main__ 函数中有使用样例，方便记忆，也可以参考下面的说明来使用。&lt;/p&gt;

&lt;h3 id=&quot;一个简单的样例&quot;&gt;一个简单的样例&lt;/h3&gt;

&lt;p&gt;同把“大象装冰箱”一样简单的三步，创建一个表格 / 把内容装进去 / 输出表格，完活。&lt;/p&gt;

&lt;p&gt;代码样例：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;##  创建一个表格
from tablemap import *
tbmap = tablemap()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;##  添加元素
tbmap.additem(&quot;title1&quot;,'item1',&quot;Hello 1*1&quot;)
tbmap.additem(&quot;title2&quot;,'item1',&quot;Hello 1*2 AAAAA&quot;)
tbmap.additem(&quot;title3&quot;,'item1','20')
tbmap.additem(&quot;title1&quot;,'item2',&quot;Hello 2*1 BBBBB&quot;)
tbmap.additem(&quot;title2&quot;,'item2',&quot;Hello 2*2&quot;)
tbmap.additem(&quot;title3&quot;,'item2','500')
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;##  表格输出
print tbmap.printMap()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;通常来讲，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;步骤1&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;步骤3&lt;/code&gt; 是死代码， 拿过来直接用即可，无需更改，只需要把精力放在填表即可，以上代码的运行结果效果图如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ python test.py 
+-------+-----------------+-----------------+--------+
|       |      title1     |      title2     | title3 |
+-------+-----------------+-----------------+--------+
| item1 |       Hello 1*1 | Hello 1*2 AAAAA |     20 |
| item2 | Hello 2*1 BBBBB |       Hello 2*2 |    500 |
+-------+-----------------+-----------------+--------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;“列名部分”居中，“内容部分”右对齐，每一列的大小也由模块自动计算调整。
在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;第2步&lt;/code&gt;中，每一次指定了表格的一个内容元素，以及其对应的行名和列名，模块自动完成填表过程，对于未定义过的行列名，模块也可以自动处理，无需人为干预。&lt;/p&gt;

&lt;h3 id=&quot;指定列展示&quot;&gt;指定列展示&lt;/h3&gt;

&lt;p&gt;如果只想挑选某几列的内容进行内容展示，可以通过向 printMap() 传参的方式来控制。当我只需要对比  title1,title3 两列的结果时，调用方法如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;##  Only title1, title3
print tbmap.printMap( ['title1','title3'] )
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;此时即可得到如下忽略 title2 的输出结果：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ python test.py 
+-------+-----------------+--------+
|       |      title1     | title3 |
+-------+-----------------+--------+
| item1 |       Hello 1*1 |     20 |
| item2 | Hello 2*1 BBBBB |    500 |
+-------+-----------------+--------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;指定列展示顺序&quot;&gt;指定列展示顺序&lt;/h3&gt;

&lt;p&gt;列顺序还可以通过调整参数顺序来指定：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;##  调整列顺序
print tbmap.printMap( ['title2','title3','title1'] )
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;+-------+-----------------+--------+-----------------+
|       |      title2     | title3 |      title1     |
+-------+-----------------+--------+-----------------+
| item1 | Hello 1*2 AAAAA |     20 |       Hello 1*1 |
| item2 |       Hello 2*2 |    500 | Hello 2*1 BBBBB |
+-------+-----------------+--------+-----------------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;对齐样式&quot;&gt;对齐样式&lt;/h3&gt;

&lt;p&gt;观察列表内容不难发现，title3 这一列在右对齐下有比较好的展示效果，
而余下的两列展示效果欠佳，调整为右对齐会获得比较直观的结果，左对齐可以通过添加减号的方式来指定，样例如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;##  将title1 列设置为左对齐，其他列不变
print tbmap.printMap( ['title2','title3','-title1'] )
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ python test.py 
+-------+-----------------+--------+-----------------+
|       |      title2     | title3 |     title1      |
+-------+-----------------+--------+-----------------+
| item1 | Hello 1*2 AAAAA |     20 | Hello 1*1       |
| item2 |       Hello 2*2 |    500 | Hello 2*1 BBBBB |
+-------+-----------------+--------+-----------------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;为表格命名&quot;&gt;为表格命名&lt;/h3&gt;

&lt;p&gt;当表格数量过多时，需要对表格进行一个命名，以便区分表格，
在输出前为表格指定一个名字即可完成这一目标，代码样例如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;##  为表格指定名字
tbmap.setTitle(&quot;Test Table&quot;)
print tbmap.printMap()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ python test.py 
+----------------------------------------------------+
|                    *Test Table*                    |
+-------+-----------------+-----------------+--------+
|       |      title1     |      title2     | title3 |
+-------+-----------------+-----------------+--------+
| item1 |       Hello 1*1 | Hello 1*2 AAAAA |     20 |
| item2 | Hello 2*1 BBBBB |       Hello 2*2 |    500 |
+-------+-----------------+-----------------+--------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;十六进制输出&quot;&gt;十六进制输出&lt;/h2&gt;

&lt;p&gt;在逆向统计中，要经常验证提取出的数据内容，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hexdump&lt;/code&gt;可以在大部分情况获得比较好的执行结果， 但总有一些情况，我希望能从代码中直接展示出来，hexmap就是这样一个模块，用法如下：&lt;/p&gt;

&lt;h3 id=&quot;模块获取&quot;&gt;模块获取&lt;/h3&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wget https://raw.githubusercontent.com/rootkiter/easycode/master/hexmap.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;模块使用&quot;&gt;模块使用&lt;/h3&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;from hexmap import *
Adata = &quot;ABCDEFGHIJK\x11\x22\x33\x44\x55\x66&quot;
print str(hexmap(Adata))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;执行结果&quot;&gt;执行结果&lt;/h3&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ python test.py
0x0000    41 42 43 44 45 46 47 48  49 4a 4b 11 22 33 44 55    ABCDEFGHIJK*&quot;3DU
0x0010    66                                                  f               
-----&amp;gt; packet size :hex(0x11),ord(17) &amp;lt;-------
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;其他&quot;&gt;其他&lt;/h2&gt;
&lt;p&gt;在项目库中还有一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;多线程参数更新&lt;/code&gt;的小模块，模块很小，只完成了随时更新线程的功能，感兴趣可以去看一下主函数中的样例，这里就不再细说了。&lt;/p&gt;

&lt;h2 id=&quot;结&quot;&gt;结&lt;/h2&gt;

&lt;p&gt;春暖花开，又到了博客长草的季节，今天碰巧是“国际除草日”，例行除草（&lt;strong&gt;没错，就是在一本正经地胡说八道&lt;/strong&gt;）。&lt;/p&gt;

&lt;p&gt;上周刚刚取得工具链搭建的阶段性胜利，目前 IoT 样本逆向工具链中的几个关键点都成功占坑，在后面的工作中要实际测试效果了。&lt;/p&gt;

&lt;p&gt;如果碰巧效果比较符合预期，可能还会挑选几个低耦合的模块在这里介绍下。从已知资料来看这套工具的设计思路大概是前无古人的，其整体目标性很明确，且模块间功能互补，希望它们能辅助一波 IoT 的僵尸网络追踪。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>PPC学习笔记</title>
        <link href="/2017/03/08/PowerPC_Study.html"/>
	<updated>2017-03-08T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2017/03/08/PowerPC_Study</id>
	<content type="html">&lt;h2 id=&quot;powerpc指令&quot;&gt;PowerPC指令&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;内容参考&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;《&lt;a href=&quot;http://101.96.8.165/moss.csc.ncsu.edu/~mueller/cluster/ps3/SDK3.0/docs/arch/PPC_Vers202_Book1_public.pdf&quot;&gt;PPC Vers202 Book1 public.pdf&lt;/a&gt;》&lt;/p&gt;

&lt;h2 id=&quot;基础内容&quot;&gt;基础内容&lt;/h2&gt;

&lt;h3 id=&quot;基础数据结构&quot;&gt;基础数据结构&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;基础结构&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;汉语名&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;长度&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Quadword&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;四字&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;128bits&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Doubleword&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;双字&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;64bits&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Word&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;字&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;32bits&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Halfword&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;半字&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;16bits&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Byte&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;字节&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;8bits&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;数字表示&quot;&gt;数字表示&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;二进制  ：0bnnnn&lt;/em&gt;&lt;br /&gt;
&lt;em&gt;十六进制：0xnnnn&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;通用寄存器&quot;&gt;通用寄存器&lt;/h3&gt;

&lt;p&gt;PPC中通用寄存器供32个，编号为 r0-r31,分别如下：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;寄存器名&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;r0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;函数开始时使用？&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;r1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;堆栈指针，IDA中标识为 $sp&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;r2&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;内容表指针，IDA中标识为 rtoc&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;r3&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;函数调用中作为第一参数，以及返回值&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;r4-r10&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;函数或系统调用开始的参数&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;r11&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;用在指针的调用和当做一些语言的环境指针&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;r12&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;用于异常处理和glink代码&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;r13&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;保留作为系统线程ID&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;r14-r31&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;作为本地变量,非易失性&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;专用寄存器&quot;&gt;专用寄存器&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;寄存器名&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;lr&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;链接寄存器，它用来存放函数调用结束处的返回地址。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ctr&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;计数寄存器,循环计数器，随特定转移操作而递减。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;xer&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;定点异常寄存器，存放整数运算操作的进位以及溢出信息。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;msr&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;机器状态寄存器，用来配置微处理器的设定。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;cr&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;条件寄存器，它分成8个4位字段，cr0-cr7,它反映了某个算法操作的结果并且提供条件分支的机制。&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;浮点寄存器&quot;&gt;浮点寄存器&lt;/h3&gt;

&lt;p&gt;由于样本逆向过程中未涉及浮点寄存器，所以这里不总结了。&lt;/p&gt;

&lt;h3 id=&quot;指令格式&quot;&gt;指令格式&lt;/h3&gt;

&lt;p&gt;四字节定长指令系统，字（4字节）对齐，因此，当在指令中要表达指令地址时，低两位二进制位是无效的，对于任意合法的指令地址，低二位二进制都必然是0。&lt;/p&gt;

&lt;p&gt;PPC全部指令集，被分为15种不同的指令格式，每种指令格式的解码方法各不相同。&lt;/p&gt;

&lt;h2 id=&quot;常见指令列表&quot;&gt;常见指令列表：&lt;/h2&gt;

&lt;h3 id=&quot;基础运算&quot;&gt;基础运算&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;指令&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;指令格式&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;指令功能&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;divw&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;divw rd,rs1,rs2&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;rd=rs1/rs2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;add&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;add r11, r11, r9&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;r11 = r11+r9&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;addi&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;addi rd,rs,xxx&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;rd = rs + xxx 立即数加&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;mullw&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;mullw r0, r0, r3&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;r0 = r0*r3&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;srawi&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;srawi r0, r11, 8&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;r0 = r11 » 8&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;slwi&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;slwi r0, r0, 8&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;r0 = r0 « 8&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;subf&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;subf r0, r0, r8&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;r0 = r8-r0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;addze&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;addze r0, r0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;　推测是数值扩充指令。 0xf -&amp;gt; 0x0f 这种含义　｜&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;clrlwi&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;clrlwi rd,rs,imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;rd=rs &amp;amp; ((1«(32-imm)) -1) 将 rs 的高imm 位清零，结果放置于 rd寄存器&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;寄存器操作指令&quot;&gt;寄存器操作指令&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;指令&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;指令格式&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;指令功能&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;mflr&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;mflr r0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;r0=lr 函数调用起始使用，一般用于保存函数返回地址&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;mtlr&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;mtlr r0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;lr=r0 函数结尾使用，还原函数返回地址，常和blr指令配合使用&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;stwu&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;stwu rs,imm(rd)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;保存rs寄存器内容到内存&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;stbx&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;　stbx rs,rd1,rd2&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;mem[rd1+rd2] = rs 内存赋值&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;li&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;li rd,imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;rd = imm 寄存器赋值&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;lbzx&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;lbzx rd,rs1,rs2&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;rd = [rs1+rs2] 内存取值&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;lis&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;lis rd,imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;寄存器高位赋值 r9=xxx « 16 常和 addi 配合使用&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;lbz&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;lbz rd,imm(rs)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;rd=mem[rs+imm] 按字节取&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;lhz&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;lhz rd, imm(rs)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;rd=mem[rs+imm] 按半字取值&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;lwz&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;lwz rd, imm(rs)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;rd=mem[rs+imm] 按字取值&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;程序流控制相关指令&quot;&gt;程序流控制相关指令&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;指令&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;指令格式&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;指令功能&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;mtctr&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;mtctr rs&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;用rs寄存器的值更新计数器ctr，一般用于循环判断&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;bdnz&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;　bdnz imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if (ctr!=0) goto pc+imm 检查ctr寄存器，并按偏移跳转&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;cmpwi&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;cmpwi rd, rs, imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;rd=rs-imm 比较指令,结果放rd寄存器，常和跳转指令连用&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ble&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ble rs, imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if (rs &amp;lt;=0 ) goto pc+imm 按偏移跳转&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;cmpw&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;cmpw rd, rs1, rs2&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;rd=rs1-rs2 比较指令，结果放rd寄存器，常和跳转指令连用&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;bgt&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;bgt rs,imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if(rs&amp;gt;0) goto pc+imm   按偏移跳转&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;bl&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;bl imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;以imm 地址为目标地址，跳转。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;blr&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;blr&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;以lr寄存器的值为目标地址。常用在函数退出位置&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;

&lt;p&gt;PowerPC(PPC)指令体系，为RISC指令集，同时也是32位定长指令，从已掌握的指令结构体系来看，除 Motorola 那个嵌入式指令集为变长指令集外，其他嵌入式CPU均为定长指令体系，定长指令的优点在于取指方便，更方便CPU从硬件层面实现流水线指令处理，从逆向结果来看，PowerPC同样具有延时指令的特点（流水线型嵌入式指令体系均有这一特点）。&lt;/p&gt;

&lt;p&gt;PowerPC对基础数据结构的定义同其他体系不同。这是一个在算法逆向中需要注意的点。&lt;/p&gt;

&lt;p&gt;由于指令体系为32位定长指令，而寄存器也为32位，所以在寄存器赋值时，无法在一条指令中完成32位立即数的操作，这也是所有嵌入式CPU的共性问题。&lt;/p&gt;

</content>
</entry>

<entry>
	<title>Python元类(小李很悲剧)</title>
        <link href="/2017/02/25/Python_ClassBuilder.html"/>
	<updated>2017-02-25T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2017/02/25/Python_ClassBuilder</id>
	<content type="html">&lt;h2 id=&quot;python元类&quot;&gt;Python元类&lt;/h2&gt;

&lt;p&gt;最近一直在写Python代码，但是每创建一个类，都要重新写一套set和get方法，麻烦的要死，而且每加一个新成员都要配套一堆相关方法，真的很浪费时间，如果能把这些时间统统节省下来，那必是极好的。&lt;/p&gt;

&lt;p&gt;在Python中有“元类”的概念，其作用就是动态创建一个类，包括其成员以及相应方法。基于元类，可以快速生成一个新类，并自动生成一些常用的工具方法，以节省时间。&lt;/p&gt;

&lt;p&gt;下面就用小李的悲剧，来看一下这个类的使用情况。&lt;/p&gt;

&lt;h2 id=&quot;小李的悲剧&quot;&gt;小李的悲剧&lt;/h2&gt;

&lt;h3 id=&quot;小李的初始化&quot;&gt;小李的初始化&lt;/h3&gt;

&lt;p&gt;大概用了一天时间写了一个工具类&lt;a href=&quot;/files/ClassBuilder.py&quot;&gt;ClassBuilder&lt;/a&gt;，有了这个类，我们可以很快速的定义一个学生类来描述小李同学。他是个学生，今年20岁了：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2017_02_25_19_56/1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;由于Student继承了ClassBuilder这个类，那么ClassBuilder就会为类中的Name和Age两个成员自动创建出相应的set方法和get方法，所以在 main 函数中就可以直接使用set_Name,set_Age,get_Name,get_Age四个方法了,以上代码的运行效果如下：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2017_02_25_19_56/2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;值得注意的是由于ClassBuilder自动创建了__str__ 方法，所以在主函数的 22 行才可以直接将小李的所有信息print出来。&lt;/p&gt;

&lt;h3 id=&quot;小李出名了值传递&quot;&gt;小李出名了(值传递)&lt;/h3&gt;

&lt;p&gt;小李因为一些不可告人的原因，竟然出名了，想知道他详细信息的人多如牛毛，为了方便他人认识小李，我们需要将小李的详细信息以某种方式打包起来，再以某种方式还原出来，在ClassBuilder的帮助下，可以通过json数据格式完成这一过程。&lt;/p&gt;

&lt;p&gt;任何类继承了ClassBuilder后还会自动生成buildJSON和loadJSON两个方法，以便快速的将一个类的值转化成json数据，或从json反向恢复一个类。样例代码如下:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2017_02_25_19_56/3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;在代码的22 行，使用 tt 对象的 buildJSON 方法将类中所有数值转存为 json 字符串，而第28 行则用loadJSON方法从这个json字符串还原一个 t2 对象，29-30两行代码则是验证还原结果。上述代码的执行效果如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2017_02_25_19_56/4.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;虽然目前还不知道小李出名的具体原因，但我们已经可以通过buildJSON和loadJSON两个方法分发小李的详细个人信息了，要注意我们并没有为Student类添加任何与之相关的代码，想想还真有些小激动呢。&lt;/p&gt;

&lt;h3 id=&quot;列表成员&quot;&gt;列表成员&lt;/h3&gt;

&lt;p&gt;每一个正常的学生，应该都有数量不等的标签，小李作为一个正常的学生，也要适应这一情况，学生类中需要一个新的列表成员来描述这一变化。如下所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2017_02_25_19_56/5.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;从23-24行不难看出，小李不光是个学霸，而且还是个帅哥，很有前途，其实代码的执行结果也印证了这一点：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2017_02_25_19_56/6.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;字典成员小李的成绩&quot;&gt;字典成员（小李的成绩）&lt;/h3&gt;

&lt;p&gt;当学生免不了要考试，小李作为资深学霸，自然应该门门功课都满分。又要给学生类加新成员了。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2017_02_25_19_56/7.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;小李果然是个“真·学霸”，仅有的两门功课都打了120分，但我很好奇，明明满分是100分，他怎么会多打20分，真是见鬼了，小李还真是个谜一样的人。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2017_02_25_19_56/8.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;移除列表成员东窗事发&quot;&gt;移除列表成员（东窗事发）&lt;/h3&gt;

&lt;p&gt;他的老师也同样对小李的成绩有些疑问，调查后发现，这小子真不是个省油的灯，他竟然敢伪造老师的笔记给自己卷子打分，要不是这次给自己多打了20分，可能大家还会继续把他当学霸。既然他不是个学霸，那自然应该把学霸的标签移除。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2017_02_25_19_56/9.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;小李的真实面目被曝光后，我们还要好好对比下出事前后小李个人信息的更新情况。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2017_02_25_19_56/10.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;尾记&quot;&gt;尾记&lt;/h2&gt;

&lt;p&gt;小李的故事讲完了，相信一定有人知道他出名的真实原因了。&lt;/p&gt;

&lt;p&gt;不知道是否有人注意到，在讲整个故事的过程中，我们并没有对Student类做过多的修改，甚至没有定义任何新的函数。其实这全都是ClassBuilder这个类的功劳。&lt;/p&gt;

&lt;p&gt;ClassBuilder这个类是从Python元类出发编写的，对其魔力感兴趣的小伙伴可以到&lt;a href=&quot;/files/ClassBuilder.py&quot;&gt;这里&lt;/a&gt;下载并阅读。&lt;/p&gt;

&lt;p&gt;虽然在本文中ClassBuilder被用来讲述小李的传奇故事，但ClassBuilder中内置的几个方法却会在工程中却经常用到，这个类未来一定会成为一个伟大的类，并出现在我的各种项目代码中。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>样本逆向中系统调用的识别方法</title>
        <link href="/2016/12/18/%E6%A0%B7%E6%9C%AC%E9%80%86%E5%90%91%E4%B8%AD%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8%E7%9A%84%E8%AF%86%E5%88%AB%E6%96%B9%E6%B3%95.html"/>
	<updated>2016-12-18T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2016/12/18/样本逆向中系统调用的识别方法</id>
	<content type="html">&lt;h3 id=&quot;无符号表情况下的逆向&quot;&gt;无符号表情况下的逆向&lt;/h3&gt;

&lt;p&gt;LINUX平台下的程序，可以通过strip程序进行精简，精简过的可执行文件会变小，同时又丝毫不影响执行效率。但这种情况会给程序逆向带来困扰。由于没有符号表的支持，所有函数在IDA中都会被显示为sub_xxx的形式，这会给逆向工程带来麻烦。&lt;/p&gt;

&lt;p&gt;这里简单记录一下各常见平台下的系统调用识别方法。&lt;/p&gt;

&lt;h3 id=&quot;常见平台的系统调用识别方法&quot;&gt;常见平台的系统调用识别方法&lt;/h3&gt;

&lt;p&gt;无论哪个平台的系统调用都有两个关键点，一个是调用指令，另一个是调用号。&lt;/p&gt;

&lt;p&gt;系统调用的具体功能由系统调用号制定，调用号和功能的对应关系要参考相关头文件。&lt;/p&gt;

&lt;p&gt;我把目前所有能找到的系统调用有关的头文件，都放在了&lt;a href=&quot;https://github.com/rootkiter/Reverse-bins/tree/master/syscall_header&quot;&gt;github 上的Reverse-bins项目&lt;/a&gt;中，供查阅。&lt;/p&gt;

&lt;h4 id=&quot;x86&quot;&gt;X86&lt;/h4&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;调用指令&lt;/td&gt;
      &lt;td&gt;INT 80h&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;寄存器&lt;/td&gt;
      &lt;td&gt;eax&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;参考表&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;https://github.com/rootkiter/Reverse-bins/blob/master/syscall_header/i586_unistd_32.h&quot;&gt;x86系统调用表&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_12_18_18_03/1.png&quot; alt=&quot;x86&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;arm&quot;&gt;ARM&lt;/h4&gt;

&lt;p&gt;ARM 下的系统调用，有两种，一种是带参数的，另一种是指令调用时参数指定，分别如下:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;寄存器指定&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;调用指令&lt;/td&gt;
      &lt;td&gt;SVC 0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;寄存器&lt;/td&gt;
      &lt;td&gt;r7&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;参考表&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;https://github.com/rootkiter/Reverse-bins/blob/master/syscall_header/armv5l_unistd.h&quot;&gt;ARM系统调用表&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_12_18_18_03/3.png&quot; alt=&quot;ARM2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;指令内指定&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;调用指令&lt;/td&gt;
      &lt;td&gt;SVC 0xXXXXX&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;寄存器&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;参考表&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;https://github.com/rootkiter/Reverse-bins/blob/master/syscall_header/armv5l_unistd.h&quot;&gt;ARM系统调用表&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_12_18_18_03/2.png&quot; alt=&quot;ARM1&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;mips&quot;&gt;MIPS&lt;/h4&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;调用指令&lt;/td&gt;
      &lt;td&gt;syscall 0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;寄存器&lt;/td&gt;
      &lt;td&gt;$v0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;参考表&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;https://github.com/rootkiter/Reverse-bins/blob/master/syscall_header/mips_unistd.h&quot;&gt;MIPS系统调用表&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_12_18_18_03/4.png&quot; alt=&quot;MIPS&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;ppc&quot;&gt;PPC&lt;/h4&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;调用指令&lt;/td&gt;
      &lt;td&gt;sc&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;寄存器&lt;/td&gt;
      &lt;td&gt;r0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;参考表&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;https://github.com/rootkiter/Reverse-bins/blob/master/syscall_header/powerpc-440fp_unistd.h&quot;&gt;PPC系统调用表&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_12_18_18_03/5.png&quot; alt=&quot;PPC&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;sh4&quot;&gt;SH4&lt;/h4&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;调用指令&lt;/td&gt;
      &lt;td&gt;trapa #h’10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;寄存器&lt;/td&gt;
      &lt;td&gt;r3&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;参考表&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;https://github.com/rootkiter/Reverse-bins/blob/master/syscall_header/sh4_unistd_32.h&quot;&gt;SH4系统调用表&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_12_18_18_03/6.png&quot; alt=&quot;SH4&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;spc&quot;&gt;SPC&lt;/h4&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;调用指令&lt;/td&gt;
      &lt;td&gt;ta 0x10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;寄存器&lt;/td&gt;
      &lt;td&gt;%g1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;参考表&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;https://github.com/rootkiter/Reverse-bins/blob/master/syscall_header/sparc_unistd.h&quot;&gt;SPC系统调用表&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_12_18_18_03/7.png&quot; alt=&quot;SPC&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;结&quot;&gt;结&lt;/h3&gt;

&lt;p&gt;这里记录了无符号表时，系统调用函数的识别方法，可用于LINUX下逆向参考。&lt;/p&gt;

&lt;p&gt;这种对照关系也可以在IDA脚本进行实现，以节省逆向时间，在分析MIRAI样本的工作中，大概能节约30%的分析时间。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>两种嵌入式CPU指令集</title>
        <link href="/2016/11/22/%E4%B8%A4%E7%A7%8D%E5%B5%8C%E5%85%A5%E5%BC%8F%E6%8C%87%E4%BB%A4%E9%9B%86.html"/>
	<updated>2016-11-22T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2016/11/22/两种嵌入式指令集</id>
	<content type="html">&lt;h3 id=&quot;前&quot;&gt;前&lt;/h3&gt;

&lt;p&gt;虽然一直对嵌入式设备相关的东西比较关注，除了开发工具外，也在这里写过相关的文档《&lt;a href=&quot;/2016/03/16/记一个组建僵尸网络的样本.html&quot;&gt;记一个组建僵尸网络的样本&lt;/a&gt;》。但一直没什么动力去花时间学习相关的汇编指令。由于近两个月一直在围绕着 Mirai 做事情，顺手就从中选两门汇编语言（MIPS、SuperH）简单学习一下，扩充下知识储备。&lt;/p&gt;

&lt;p&gt;目前市面上的智能设备中，最常见的CPU有两种，分别为 ARM 和 MIPS（或mipsel），ARM在接触移动端安全时已经接触过了，所以这回就从 MIPS 开始。至于SuperH的选择是由于之前碰到过这种CPU设备，拿来做比对学习。&lt;/p&gt;

&lt;p&gt;搞了两篇学习笔记，也同步更新到这个博客里，方便日后查阅。&lt;/p&gt;

&lt;p&gt;《&lt;a href=&quot;/2016/11/20/MIPS学习笔记.html&quot;&gt;MIPS 学习笔记&lt;/a&gt;》&lt;/p&gt;

&lt;p&gt;《&lt;a href=&quot;/2016/11/21/SuperH学习笔记.html&quot;&gt;SuperH 学习笔记&lt;/a&gt;》&lt;/p&gt;

&lt;p&gt;配合之前写过的ARM相关的学习笔记，目前这里已经涵盖了3个嵌入式CPU资料了:&lt;/p&gt;

&lt;p&gt;《&lt;a href=&quot;/goto_tags.html#ARM&quot;&gt;ARM相关的学习笔记&lt;/a&gt;》&lt;/p&gt;

&lt;h3 id=&quot;mips&quot;&gt;MIPS&lt;/h3&gt;

&lt;p&gt;该指令集在ARM普及前，在芯片领域具有相当大的影响力，甚至驰名中外的“龙芯”就是基于MIPS开发设计的，所以相关资料非常多，其中还有非常多的中文资料，学习成本相对较低。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;既然提到“龙芯”，我很想在这里插一句，“龙芯”其实从工业设计到运算性能，完全有实力站在世界前列。但它一直无法替代Intel，AMD这些CPU的根本原因在于，生态环境不如人家成熟。这就和Windows Phone系统没法抗衡Android、IOS的道理一样。你再牛逼，人家Windows系统就是不鸟你，你能怎么办。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;关于MIPS指令体系的特点，大概总结了以下几点:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;MIPS 和 mipsel 虽然拼写不同，但两者根本就是同一个东西，在汇编指令层毫无区别。在二进制层面上，每条指令对应的字节序是反过来的。感兴趣的同学可以到&lt;a href=&quot;&quot;&gt;这个&lt;/a&gt;工程里，下载各自的二进制文件进行比对分析。&lt;em&gt;该工程是为了学习嵌入式逆向特意创建的，把几段具有代表性的C代码交叉编译到不同的平台下，形成产品放在bin目录下，以供逆向学习时使用&lt;/em&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;另一个值得注意的情况是，在MIPS体系中，并没有见到与状态寄存器有关的鬼东西，这种状况很是少见。无论是在X86体系中，还是ARM体系中，状态寄存器都非常重要，溢出标志 / 操作数比较结果，等关键记录，都会在状态寄存器中做一个标识，而MIPS体系中竟然连个影子都没看到，它把原来需要两条指令做的事情在一条指令中完成，可以说是一种另辟蹊径的做法。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;在mips体系中，还会看到另外一种诡异的现象，那就是指令碎片化。这种感觉，就和Android系统的碎片化有些类似了。由于相比其他指令体系，MIPS的指令体系更为开放，任何公司都可以比较容易的拿到授权，并在其基础上添加适合自身业务的新指令。好在大部分公司都是添加新指令，而不是更改原来的指令，这一点，让我很欣慰。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;superh&quot;&gt;SuperH&lt;/h3&gt;

&lt;p&gt;该指令集来自岛国的日立公司。广泛应用于微型设备，指令集特点在于其每条指令只占两个字节长度，和ARM以及MIPS相比，相同功能的代码段，可以节约大约一半的存储空间。要知道，在微型设备中那可是寸土寸金，这样的优势相当明显的。&lt;/p&gt;

&lt;p&gt;关于 SuperH 指令体系的特点，大概总结了以下几点：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;SH代码有极强的生存能力：在SH指令系统中，从 SH-1 到 SH-4 二进制兼容，这意味着，能在 SH-1 上运行的代码拿到 SH-4 上照样能运行，这是一条带给嵌入式设备商的福利，当新片升级时， 完全不需要去考虑原始代码在新设备的兼容性。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;大量指令和间接取指有关。别看SH指令只有二字节（16 bits）长度，但SH体系却能够对 32 bits 的数字做运算。这依赖于SH完善的指令体系。其立即数相关指令最多只能处理8位二进制数，当有更大的计算需求时，就要通过间接寻址的方式来解决了，当然这要牺牲一部分计算性能。好在微型设备要做的事情一般也并怎么不复杂。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;想学习却无处着手，SuperH的缺点在于其资料严重匮乏，除芯片厂商给出的说明文档外，基本没有其他资料可用来学习，能找到的资料除了日文，就是英文，中文资料基本别想。好在，日本人非常严谨，产品资料写的那叫一个细，屁大点事都能啰里啰嗦写一页，没错我就是在夸他们呢，你没听出来么？&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;SH 是目前接触过的所有指令体系中，唯一具有延时指令机制的体系。延时指令的含义为，当指令执行到本条指令时，并会不立即产生指令效果，而是会等待下一条指令执行完毕后再产生效果。起初并不理解这么设计的意义，后来在读到《支撑处理器的技术:永无止境的追求速度的世界》这本书时，突然理解了。这是由于每条SH指令只占两个字节，在使用流水线式指令执行操作中，如果第一条指令的结果可能更改程序的执行顺序时（比如程序条转），那么第一条指令执行一半后，第二条指令已经开始进入取指阶段，当第一条指令完全执行完毕，第二条指令其实也已经执行了一半，此时如果放弃第二条指令的执行结果，无形中就浪费了CPU的时钟周期，索性不如让第二条指令完全执行完毕，再回头处理第一条指令的结果。虽然提高了CPU的时间利用率，但也把复杂的问题抛给了程序链接器。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;结&quot;&gt;结&lt;/h3&gt;

&lt;p&gt;这里算是对最近新学到的东西做了一些总结，以备日后查阅。&lt;/p&gt;

</content>
</entry>

<entry>
	<title>SuperH学习笔记</title>
        <link href="/2016/11/21/SuperH%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.html"/>
	<updated>2016-11-21T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2016/11/21/SuperH学习笔记</id>
	<content type="html">&lt;h2 id=&quot;superh指令&quot;&gt;SuperH指令&lt;/h2&gt;

&lt;p&gt;参考内容：&lt;/p&gt;

&lt;p&gt;《&lt;a href=&quot;http://www.shared-ptr.com/sh_insns.html&quot;&gt;Renesas SH Instruction Set Summary&lt;/a&gt;》&lt;/p&gt;

&lt;p&gt;《&lt;a href=&quot;www.st.com/resource/en/user_manual/cd00147165.pdf&quot;&gt;SH-4 CPU Core Architecture&lt;/a&gt;》&lt;/p&gt;

&lt;h3 id=&quot;基础内容&quot;&gt;基础内容&lt;/h3&gt;

&lt;p&gt;SH4 是 SuperH 系列CPU之中的一种指令集，该体系指令由日立公司最早开发。虽然在SuperH家族中，指令版本众多，但在SH1，SH2，SH3，SH4这一系列指令扩展过程中，始终保证了二进制级别的兼容的特性。&lt;/p&gt;

&lt;h4 id=&quot;数据类型和常量&quot;&gt;数据类型和常量&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;数据类型&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;SH4 指令是 16bit 定长指令，与 Thumb 指令集类似，比 MIPS，ARM 还要精简一半。&lt;/li&gt;
  &lt;li&gt;SH4 的数据格式有“字节”，“字”，“长字”三种。&lt;/li&gt;
  &lt;li&gt;1字节=8 bit，1字=2字节，1长字=2字。&lt;/li&gt;
  &lt;li&gt;受指令长度限制，单条指令中无法表达32位数字，当有需求时，会以多种间接寻址的方式出现。&lt;/li&gt;
  &lt;li&gt;同MIPS体系类似，SuperH系列指令也具有大端小端之分，这主要看CPU对两种体系的支持情况。&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;寄存器&quot;&gt;寄存器&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;16个32bit通用寄存器（此外还有8个隐藏的32位通用寄存器）&lt;/li&gt;
  &lt;li&gt;7个32bit控制寄存器&lt;/li&gt;
  &lt;li&gt;4个32bit系统寄存器&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;通用寄存器&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;寄存器名&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;R0_BANK0-R7_BANK0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;通用寄存器，SR.RB=0，也可表示为 r0-r7&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;R0_BANK1-R7_BANK1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;隐藏寄存器，SR.RB=1，用户态无法访问&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;r8-r15&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;通用寄存器&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;SH4 共有24个通用寄存器，分为三类，第一类是8个用户可直接使用的通用寄存器，编号为:R0_BANK0-R7_BANK0，在程序中一般用 r0-r7 来表示，相对应的有8个用户无法直接访问的寄存器，编号为：R0_BANK1-R7_BANK1，当执行出现异常时，这八个寄存器分别保存第一类寄存器的值状态。剩余的8个寄存器为r8-r15。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;系统寄存器&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;寄存器名&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;初始值&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MACH&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Undefined&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;乘加寄存器高位&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MACL&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Undefined&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;乘加寄存器低位&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;PR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Undefined&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;当使用了 BSR,BSRF,JSR 等程序控制指令时，该寄存器保存返回地址。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;PC&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;0xA0000000&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;程序计数器，指向将要执行的指令地址&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;控制寄存器&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;寄存器名&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;初始值&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;访问保护&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;SR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Undefine&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Yes&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;状态寄存器&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;SSR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Undefine&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Yes&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;出现异常时，保存 SR 寄存器的值&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;SPC&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Undefine&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Yes&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;出现异常时，保存 PC 寄存器的值&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;GBR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Undefine&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;No&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;间接寻址寄存器，配合寄存器内的值，进行寻址&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;VBR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Undefine&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Yes&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向量基址寄存器，表示一场向量区域的基地址&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;SGR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Undefine&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Yes&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;出现异常时，保存 r15 寄存器的值&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;DBR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Undefine&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Yes&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;当处于调试模式时，用该寄存器替代VBR&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;指令列表&quot;&gt;指令列表&lt;/h4&gt;

&lt;p&gt;SH4 包括协处理器指令一共200多条，全部整理出来不现实，这里只选取一部分记录一下，遇到陌生指令可以去参考《&lt;a href=&quot;www.st.com/resource/en/user_manual/cd00147165.pdf&quot;&gt;SH-4 CPU Core Architecture&lt;/a&gt;》这个文档。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;四则运算&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;指令&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;伪指令&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;含义描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ADD Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rn=Rm+Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;加指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ADD #imm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rn=Rn+#imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;加指令，imm最大表示8位二进制数&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ADDC Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rn=Rm+Rn+Tbit&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;带进位的加法指令，结果超过32位表示范围后设置 T-bit&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ADDV Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rn=Rm+Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;带溢出的加法，溢出后设置 T-bit为1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;AND Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rn=Rm&amp;amp;Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;与操作&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;AND #imm,R0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;R0=#imm &amp;amp; R0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;与操作，imm最大表示8位二进制数&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;AND.B #imm,@(R0,GBR)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;@(R0,GBR)=@(R0,GBR)&amp;amp;#imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;与操作，GBR间接寻址&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;BF label&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if(T_bit==0) jump label;else: jump(+4)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;以T-bit为条件，进行程序控制&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;BF/S label&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if(T_bit==0)  jump label;else: jump(+4)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;和BF指令相似，但该指令为延迟跳转指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;BRA label&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;　jump label ;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;无条件延时跳转指令，最大地址 -4096 到 +4096&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;BSR func&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;jump func ;&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向子程序转移指令，延迟指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;BSRF Rm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;jump Rm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向子程序转移指令，延迟指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;BT label&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if(T_bit==1) jump label&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;条件转移指令，无延迟&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;BT/S label&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if(T_bit==1) jump label&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;条件转移指令，延时指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;CLRMAC&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MACH = 0 ; MACL =0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MAC寄存器清零指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;CLRT&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;T_bit = 0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;T标志位清零&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;CLRS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;S_bit = 0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;S标志位清零&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;DIV0S Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rn[MSB] -&amp;gt; Q ;Rm[MSB] -&amp;gt; M ; M^Q -&amp;gt; T&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;带符号除法初始化&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;DIV0U&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;0 -&amp;gt;　M/Q/T&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;无符号除法的初始化&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;DIV1 Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rn÷Rm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;　除法&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;DMULS.L Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm*Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;带符号的双精度乘法&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;DMULU.L Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm*Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;无符号的双精度乘法&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;DT Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rn=Rn-1 ;if(Rn==0) T=1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;递减测试&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;EXTS.B Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm 按字节符号扩展到 Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;按字节符号扩展&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;EXTS.W Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm 按字  符号扩展到 Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;按字  符号扩展&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;EXTU.B Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm 按字节零扩展到 Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;按字节零扩展&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;EXTU.W Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm 按字  零扩展到 Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;按字  零扩展&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;JMP @Rm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;jump Rm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;无条件跳转，延迟指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;JSR @Rm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;call Rm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;子函数调用，返回地址保存在 PR 寄存器，延迟指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDC Rm,GBR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt; SR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;寄存器加载指令， 中断禁止&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDC    Rm,SR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;SR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;寄存器加载指令， 中断禁止&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDC    Rm,VBR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;VBR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;寄存器加载指令， 中断禁止&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDC    Rm,MOD&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;MOD&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;寄存器加载指令， 中断禁止&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDC    Rm,RE&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;RE&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;寄存器加载指令， 中断禁止&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDC    Rm,RS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;RS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;寄存器加载指令， 中断禁止&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDC.L  @Rm+,SR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;[Rm]-&amp;gt;SR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;寄存器加载指令， 中断禁止&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDC.L  @Rm+,GBR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;[Rm]-&amp;gt;GBR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;寄存器加载指令， 中断禁止&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDC.L  @Rm+,VBR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;[Rm]-&amp;gt;VBR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;寄存器加载指令， 中断禁止&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDC.L  @Rm+,MOD&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;[Rm]-&amp;gt;MOD&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;寄存器加载指令， 中断禁止&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDC.L  @Rm+,RE&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;[Rm]-&amp;gt;RE&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;寄存器加载指令， 中断禁止&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDC.L  @Rm+,RS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;[Rm]-&amp;gt;RS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;寄存器加载指令， 中断禁止&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDRE @(disp,PC)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;disp*2+PC -&amp;gt; RE&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向重复结束寄存器加载&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDRS @(disp,PC)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;disp*2+PC -&amp;gt; RS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向重复起始寄存器加载&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDS    Rm,MACH&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;MACH&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向系统寄存器加载，中断禁止指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDS    Rm,MACL&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;MACL&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向系统寄存器加载，中断禁止指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDS    Rm,PR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;PR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向系统寄存器加载，中断禁止指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDS    Rm,DSR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;DSR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向系统寄存器加载，中断禁止指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDS    Rm,A0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;A0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向系统寄存器加载，中断禁止指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDS    Rm,X0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;X0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向系统寄存器加载，中断禁止指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDS    Rm,X1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;X1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向系统寄存器加载，中断禁止指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDS    Rm,Y0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;Y0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向系统寄存器加载，中断禁止指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDS    Rm,Y1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;Y1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向系统寄存器加载，中断禁止指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDS.L  @Rm+,MACH&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(Rm)-&amp;gt;MACH ; Rm+4-&amp;gt;Rm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向系统寄存器加载，中断禁止指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDS.L  @Rm+,MACL&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(Rm)-&amp;gt;MACL ; Rm+4-&amp;gt;Rm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向系统寄存器加载，中断禁止指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDS.L  @Rm+,PR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(Rm)-&amp;gt;PR -&amp;gt; Rm+4-&amp;gt;Rm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向系统寄存器加载，中断禁止指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDS.L  @Rm+,DSR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(Rm)-&amp;gt;DSR ; Rm+4-&amp;gt;Rm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向系统寄存器加载，中断禁止指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDS.L  @Rm+,A0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(Rm)-&amp;gt;A0 ; Rm+4-&amp;gt;Rm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向系统寄存器加载，中断禁止指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDS.L  @Rm+,X0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(Rm)-&amp;gt;X0 ; Rm+4-&amp;gt;Rm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向系统寄存器加载，中断禁止指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDS.L  @Rm+,X1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(Rm)-&amp;gt;X1 ; Rm+4-&amp;gt;Rm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向系统寄存器加载，中断禁止指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDS.L  @Rm+,Y0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(Rm)-&amp;gt;Y0 ; Rm+4-&amp;gt;Rm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向系统寄存器加载，中断禁止指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LDS.L  @Rm+,Y1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(Rm)-&amp;gt;Y1 ; Rm+4-&amp;gt;Rm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向系统寄存器加载，中断禁止指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MAC.L @Rm+,@Rn+&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(Rn)*(Rm)+MAC -&amp;gt; MAC&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;乘法累加,32位*32位-&amp;gt;64位，带符号&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MAC.W @Rm+,@Rn+&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(Rn)*(Rm)+MAC -&amp;gt; MAC&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;乘法累加,16位*16位-&amp;gt;32位，带符号&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV    Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数据传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.B  Rm,@Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;(Rn)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数据传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.W  Rm,@Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;(Rn)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数据传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.L  Rm,@Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;(Rn)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数据传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.B  @Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(Rm)-&amp;gt;符号扩展-&amp;gt;Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数据传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.W  @Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(Rm)-&amp;gt;符号扩展-&amp;gt;Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数据传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.L  @Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(Rm)-&amp;gt;Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数据传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.B  Rm,@-Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rn-1-&amp;gt;Rn ;  Rm-&amp;gt;(Rn)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数据传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.W  Rm,@-Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rn-2-&amp;gt;Rn ;  Rm-&amp;gt;(Rn)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数据传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.L  Rm,@-Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rn-4-&amp;gt;Rn ;  Rm-&amp;gt;(Rn)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数据传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.B  @Rm+,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(Rm)-&amp;gt;符号扩展-&amp;gt;Rn ;  Rm+1-&amp;gt;Rm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数据传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.W  @Rm+,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(Rm)-&amp;gt;符号扩展-&amp;gt;Rn ;  Rm+2-&amp;gt;Rm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数据传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.L  @Rm+,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(Rm)-&amp;gt;Rn ;  Rm+4-&amp;gt;Rm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数据传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.B  Rm,@(R0,Rn)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;(R0+Rn)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数据传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.W  Rm,@(R0,Rn)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;(R0+Rn)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数据传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.L  Rm,@(R0,Rn)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;(R0+Rn)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数据传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.B  @(R0,Rm),Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(R0+Rm) -&amp;gt;符号扩展-&amp;gt;Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数据传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.W  @(R0,Rm),Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(R0+Rm)-&amp;gt;符号扩展-&amp;gt;Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数据传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.L  @(R0,Rm),Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(R0+Rm)-&amp;gt;Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;数据传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV #imm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;#imm-&amp;gt; 符号扩展 -&amp;gt; Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;8位二进制数&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.W @(disp,PC),Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(disp*2+PC) -&amp;gt; 符号扩展 -&amp;gt; Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;立即数传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.L @(disp,PC),Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(disp*4+PC) -&amp;gt; Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;立即数传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.B   @(disp,GBR),R0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(disp+GBR)-&amp;gt;符号扩展-&amp;gt;R0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;外围模块数据的传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.W   @(disp,GBR),R0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(disp*2+GBR)-&amp;gt;符号扩展-&amp;gt;R0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;外围模块数据的传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.L   @(disp,GBR),R0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(disp*4+GBR)-&amp;gt;R0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;外围模块数据的传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.B   R0,@(disp,GBR)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;R0-&amp;gt;(disp+GBR)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;外围模块数据的传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.W   R0,@(disp,GBR)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;R0-&amp;gt;(disp*2+GBR)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;外围模块数据的传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.L   R0,@(disp,GBR)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;R0-&amp;gt;(disp*4+GBR)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;外围模块数据的传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.B R0,@(disp,Rn)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;R0-&amp;gt;(disp+Rn)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;结构体数据的传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.W R0,@(disp,Rn)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;R0-&amp;gt;(disp*2+Rn)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;结构体数据的传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.L Rm,@(disp,Rn)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm-&amp;gt;(disp*4+Rn)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;结构体数据的传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.B @(disp,Rm),R0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(disp+Rm)-&amp;gt;符号扩展-&amp;gt;R0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;结构体数据的传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.W @(disp,Rm),R0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(disp*2+Rm)-&amp;gt;符号扩展-&amp;gt;R0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;结构体数据的传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOV.L @(disp,Rm),Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(disp*4+Rm)-&amp;gt;Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;结构体数据的传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOVA @(disp,PC),R0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;disp*4+PC -&amp;gt; R0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;有效地址传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MOVT Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;T -&amp;gt; Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;T位的传送&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MUL.L Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rn*Rm -&amp;gt; MACL&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;双精度乘法运算 ,结果低32位放到 MACL，MACH内容不变&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MULS.W Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rn*Rm -&amp;gt; MACL&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;有符号的长发运算，16位运算，结果低32位放到 MACL，MACH 内容不变&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MULU.W Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rn*Rm -&amp;gt; MACL&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;16位乘法运算，结果低32位保存至MACL&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;NEG Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;0-Rm -&amp;gt; Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;符号取反&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;NEGC Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;0-Rm-T -&amp;gt; Rn ，借位-&amp;gt; T&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;带借位的符号取反&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;NOP&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;nop&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;空操作&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;NOT Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;~Rm -&amp;gt; Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;位取反&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;OR Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rn | Rm -&amp;gt; Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;或运算&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;OR #imm,R0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;R0 | #imm -&amp;gt; R0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;或运算&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;OR.B #imm,@(R0,GBR)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(R0+GBR) | #imm -&amp;gt; (R0+GBR)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;或运算&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ROTCL Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;T &amp;lt;- Rn &amp;lt;- T&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;带 T 位向左循环 1 位&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ROTCR Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;T -&amp;gt; Rn -&amp;gt; T&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;带T位向右循环1位&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ROTL Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;T &amp;lt;- Rn &amp;lt;-MSB&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向左循环 1 位&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ROTR Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;LSB -&amp;gt; Rn -&amp;gt; T&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;向右循环 1 位&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;RTE&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;堆栈区 -&amp;gt; PC/SR&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;异常处理返回 , 延迟转移&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;RTS&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;　PR -&amp;gt; PC&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;从 子程序 过程返回&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;SETRC Rm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Rm[11:0] -&amp;gt; RC、重复控制标志 -&amp;gt; RF1、RF0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;RC 计数器的设定及重复控制标志的设定&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;SETRC #imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;imm-&amp;gt;RC(SR[23:16]) zeros -&amp;gt; SR[27:24] 重复控制标志-&amp;gt; RF1 /RF0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;RC 计数器的设定及重复控制标志的设定&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;比较指令&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;指令&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;伪指令&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;含义描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;CMP/EQ  Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if(Rn==Rm) T=1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;寄存器比较&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;CMP/GE  Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if(Rn&amp;gt;=Rm) T=1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;有符号&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;CMP/GT  Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if(Rn&amp;gt; Rm) T=1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;有符号&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;CMP/HI  Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if(Rn&amp;gt; Rm) T=1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;无符号&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;CMP/HS  Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if(Rn&amp;gt;=Rm) T=1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;无符号&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;CMP/PL  Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if(Rn &amp;gt; 0) T=1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;CMP/PZ  Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if(Rn&amp;gt;=0 ) T=1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;CMP/STR Rm,Rn&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;任意字节相等 T=1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;任意字节？比较&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;CMP/EQ  #imm,R0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if(R0==#imm) T=1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;相等比较，最高8位二进制数&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;结尾&quot;&gt;结尾&lt;/h3&gt;

&lt;p&gt;这SH指令实在是忒多了，真心整理不动了。。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>MIPS学习笔记</title>
        <link href="/2016/11/20/MIPS%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.html"/>
	<updated>2016-11-20T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2016/11/20/MIPS学习笔记</id>
	<content type="html">&lt;h2 id=&quot;misp指令&quot;&gt;MISP指令&lt;/h2&gt;

&lt;p&gt;内容参考:&lt;/p&gt;

&lt;p&gt;《&lt;a href=&quot;http://logos.cs.uic.edu/366/notes/mips%20quick%20tutorial.htm#RegisterDescription&quot;&gt;MIPS Architecture and Assembly Language Overview&lt;/a&gt;》&lt;/p&gt;

&lt;p&gt;《&lt;a href=&quot;http://www.mrc.uidaho.edu/mrc/people/jff/digital/MIPSir.html&quot;&gt;MIPS Instruction Reference&lt;/a&gt;》&lt;/p&gt;

&lt;p&gt;《&lt;a href=&quot;http://web.cse.ohio-state.edu/~crawfis/cse675-02/Slides/MIPS%20Instruction%20Set.pdf&quot;&gt;MIPS Instructions&lt;/a&gt;》&lt;/p&gt;

&lt;h3 id=&quot;基础内容&quot;&gt;基础内容&lt;/h3&gt;

&lt;h4 id=&quot;数据类型和常量&quot;&gt;数据类型和常量&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;数据类型&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;MIPS是定长指令系统，所有指令长度均为 32 bit 位。&lt;/li&gt;
  &lt;li&gt;1 byte = 8 bits ; 1 halfword = 2 bytes ; 1 word = 4 bytes 。&lt;/li&gt;
  &lt;li&gt;每个字符，用 1 byte 表示。&lt;/li&gt;
  &lt;li&gt;一个整数，用 1 word（4 bytes）来表示。&lt;/li&gt;
  &lt;li&gt;mipsel 和 mips 是完全相同的指令集，区别只在于指令字节序不同。mips指令从左到右解析，而mipsel指令从右到左解析。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;常量&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;数字常量&lt;/em&gt;   直接键入数字 ，e.g. 4&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;字符常量&lt;/em&gt;   单引号括起   ，e.g.’b’&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;字符串常量&lt;/em&gt; 双引号括起   ，e.g.”Hello World”&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;寄存器&quot;&gt;寄存器&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;32个通用寄存器&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;MIPS规定了32个通用寄存器，分别对应为编号0到编号31，每个寄存器还配有一个别名，俗称“助记符”。对应表格如下：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;寄存器号&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;助记符&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;描述原文&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;译文&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;zero&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;the value 0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;该寄存器的值永为0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$at&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(assembler temporary) reserved by the assembler&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;汇编器的保留变量&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;2-3&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$v0,$v1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(values) from expression evaluation and function results&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;表达式求值结果，或函数调用的返回结果&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;4-7&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$a0-$a3&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(arguments) First four parameters for subroutine.Not preserved across procedure calls&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;子函数调用时的前4个参数&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;8-15&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$t0-$t7&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(temporaries) Caller saved if needed. Subroutines can use w/out saving.Not preserved across procedure calls&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;临时寄存器，供调用过程中使用。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;16-23&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$s0-$s7&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(saved values) - Caller saved.A subroutine using one of these must save original and restore it before exiting.Preserved across procedure calls.&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;函数调用时，调用方将当前寄存器状态依次保存起来，子函数退出时，依赖这些值进行寄存器还原。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;24-25&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$t8-$t9&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;(temporaries) Caller saved if needed. Subroutines can use w/out saving.These are in addition to $t0 - $t7 above.Not preserved across procedure calls.&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;临时寄存器，对$t0-$t7寄存器的补充。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;26-27&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$k0-$k1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;reserved for use by the interrupt/trap handler&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;中断信号的保留寄存器&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;28&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$gp&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;global pointer.Points to the middle of the 64K block of memory in the static data segment.&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;全局指针，指向静态数据区，方便全局变量的存取&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;29&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$sp&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;stack pointer.Points to last location on the stack.&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;堆栈指针，指向当前的堆顶&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;30&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$/s8/$fp&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;saved value / frame pointer.Preserved across procedure calls&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;第9个s寄存器，或帧指针。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;31&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$ra&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;return address&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;子函数返回地址&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;特殊寄存器&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;MIPS定义了两个特殊的寄存器（Lo和Hi）用于保存乘法和除法的结果。
这两个寄存器无法直接使用，只能通过两个独立的指令访问(mfhi–从Hi取值 , mflo–从Lo取值）&lt;/p&gt;

&lt;h4 id=&quot;栈生长方向&quot;&gt;栈生长方向&lt;/h4&gt;

&lt;p&gt;堆栈从高地址向低地址生长。&lt;/p&gt;

&lt;h4 id=&quot;指令表格&quot;&gt;指令表格&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;R类型指令&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;在所有被操作参数均为寄存器时，使用的指令类型。编码格式如下所示：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;OpCode&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Reg s&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Reg t&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;reg d&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;shift(shamt)&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;function&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;6 bits&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;5 bits&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;5 bits&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;5 bits&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;5 bits&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;6 bits&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;blockquote&gt;
  &lt;p&gt;在R型指令中，OpCode 永为0 ，指令的区分以 function 字段为主。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Reg s/ Reg t / Reg d “ 三个字段为寄存器编号，可参考寄存器表格进行对应。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;shift字段在移位操作时，会用到，其他情况永远为0&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;常见 R 型指令，及含义，见下表:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;指令格式&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Function&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;具体操作&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;附加描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;add $d,$s,$t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;100000&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$d = $s + $ t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;32位,加，有符号，可以捕获到溢出状态&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;addu $d,$s,$t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;100001&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$t = $s + $t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;32位，加，无符号，不捕获溢出&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;and $d, $s, $t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;100100&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$d = $s &amp;amp; $t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;按位与&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;break&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;001101&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;???&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;???&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;div  $s, $t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;011010&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;　$Lo= $s/$t ; $Hi = $s%$t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;除法操作，有符号&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;divu $s, $t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;011011&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$Lo= $s/$t ; $Hi = $s%$t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;除法操作，无符号&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;jalr $d,$s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;001001&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$d=PC+4 ;PC=$s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;跳转并备份返回地址&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;jr $s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;001000&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;jump $s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;　跳转指令，目标地址在 $s 寄存器中&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;mfhi $d&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;010000&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$d = $Hi&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;从特殊寄存器取值到 $s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;mflo $d&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;010010&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$d = $Lo&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;从特殊寄存器取值到 $s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;mthi $d&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt; &lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$Hi = $d&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;为特殊寄存器赋值&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;mtlo $d&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt; &lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$Lo = $d&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;为特殊寄存器赋值&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;mult $s, $t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;011000&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$Lo=$s*$t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;乘法指令，有符号&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;multu $s,$t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;011001&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$Lo=$s*$t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;乘法指令，无符号&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;nor $d,$s,$t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;100111&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;???&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;???&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;or $d, $s, $t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;100101&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$d =$s|$t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;按位或&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;sll $d, $t, h&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;000000&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$d =$t « h&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;逻辑左移&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;sllv $d, $t, $s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;000100&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$d=$t « $s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;逻辑左移&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;slt $d,$s,$t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;101010&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if($s&amp;lt;$t) $d=1 ; else $d=0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;有符号比较&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;sltu $d, $s, $t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;101011&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if($s&amp;lt;$t) $d=1 ; else $d=0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;无符号比较&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;sra $d, $t, h&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;000011&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$d=$t &amp;gt;&amp;gt; h&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;算数右移&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;srav $d,$s,$t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;000111&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$d=$s«$t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;算数右移&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;srl $d, $t, h&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;000010&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$d=$t » h&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;逻辑右移&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;srlv $d,$t,$s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;000110&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$d=$t » $s&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;逻辑右移&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;sub $d,$s,$t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;100010&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$d=$s-$t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;减法运算&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;subu $d,$s,$t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;100011&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$d=$s-$t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;减法，无符号&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;syscall&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;001100&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt; &lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;生成一个软件中断&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;xor $d, $s, $t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;100110&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$d=$s^$t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;异或运算&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;I类型指令&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;当操作数中有立即数时使用，立即数最高16位，编码格式如下：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;OpCode&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Reg s&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Reg t&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;imm&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;6 bits&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;5 bits&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;5 bits&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;16 bits&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;常见 I 型指令，及含义，如下表所示：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;指令格式&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;OpCode&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;具体操作&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;附加描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;addi $t,$s,imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;001000&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$t = $s + imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;32位,加，有符号，16位立即数，捕获溢出&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;addiu $t,$s,imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;001001&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$t = $s + imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;32位,加，无符号，16位立即数，不捕获溢出&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;andi $t,$s,imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;001100&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$t = $s &amp;amp; imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;按位与&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;beq $s,$t,offset&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;000100&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if($s==$t) jump (offset « 2)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;相等则跳转&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;bgez $s,offset&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;000001&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if($s&amp;gt;=0) jump(offset « 2)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;不小于（大于等于）0 则跳转&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;bgtz $s,offset&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;000111&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if($s&amp;gt; 0) jump(offset « 2)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;大于0 则跳转&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;blez $s,offset&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;000110&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if($s&amp;lt;=0) jump(offset « 2)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;不大于（小于等于) 0 则跳转&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;bltz $s,offset&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;000001&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if($s&amp;lt; 0) jump(offset « 2)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;小于0 则跳转&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;bne $s,$t, offset&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;000101&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if($s != $t) jump(offset « 2)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;不相等则跳转&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;lb $t,offset($s)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;100000&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$t=MEM[$s+offset]&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;从内存地址读取一个字节&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;lbu $t,offset($s)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;100100&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;???&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;???&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;lh $t,offset($s)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;100001&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;???&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;???&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;lhu $t,offset($s)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;100101&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;???&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;???&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;lui $t,imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;001111&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$t=(imm « 16)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;将立即数左移16位，低16位补零&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;lw $t,offset($s)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;100011&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$t=MEM[$s+offset]&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;从内存读取一个字&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;lwc1 $t,offset($s)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;110001&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;???&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;???&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ori $t,$s,imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;001101&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$t = $s | imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;带立即数的或&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;sb $t,offset($s)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;101000&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MEM[$s+offset]=(0xff &amp;amp; $t)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;将一个字节拷到内存&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;slti $t,$s,imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;001010&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if($s &amp;lt; imm) $t=1;else $t=0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;有符号比较&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;sltiu $t,$s,imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;001011&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;if($s &amp;lt; imm) $t=1;else $t=0&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;无符号比较&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;sh $t,offset($s)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;101001&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;???&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;???&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;sw $t,offset($s)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;101011&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;MEM[$s+offset] = $t&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;将一个字拷到内存&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;swc1 $t,offset($s)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;111001&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;???&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;???&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;xori $t, $s, imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;001110&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$t=$s^imm&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;带立即数的 异或&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;J类型指令&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;J-type是“跳转类型(jump type)”的缩写，有些类似于X86系指令的call指令，编码格式如下:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;OpCode&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Pseudo-Address&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;6 bits&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;26 bits&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;常见 J 型指令，及含义，如下表所示：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;指令格式&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;OpCode&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;具体操作&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;附加描述&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;j target&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;000010&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;PC = nPC; nPC = (PC &amp;amp; 0xf0000000) | (target « 2);&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;跳到一个计算过的地址，并执行&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;jal target&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;000011&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$31 = PC + 8 (or nPC + 4); PC = nPC; nPC = (PC &amp;amp; 0xf0000000) | (target « 2);&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;跳到一个计算过的地址，并把返回地址放在 $31 寄存器中&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

</content>
</entry>

<entry>
	<title>Mirai源码中的SYN弱口令扫描</title>
        <link href="/2016/11/05/Mirai%E6%BA%90%E7%A0%81%E4%B8%AD%E7%9A%84SYN%E5%BC%B1%E5%8F%A3%E4%BB%A4%E6%89%AB%E6%8F%8F.html"/>
	<updated>2016-11-05T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2016/11/05/Mirai源码中的SYN弱口令扫描</id>
	<content type="html">&lt;h2 id=&quot;syn口令扫描原理&quot;&gt;SYN口令扫描原理&lt;/h2&gt;

&lt;p&gt;最近在细读Mirai的源码，在它之中用到了若干有趣的技术，先把SYN扫描弱口令的代码过一下。其实这个技术本并不新鲜，早在有些扫描器中已经支持，但从代码层面分析的文档并不多见，所以在这里写一段，给日后留个念想。&lt;/p&gt;

&lt;p&gt;细细想来，我也从业许久，但就从没见过如此恶心的代码，作者竟然能把整个syn口令扫描的核心代码堆在了一个函数中，活生生把一个功能函数扩充到了583行（line.57 – line. 640）。代码缩进的最深处，可以达到9层（4*9=36个空格）之深，逐行品读时常常读一屏忘一屏。可以说这段代码磨练了我的意志，锻炼了我的耐心，是出家修行必备之良品。。。&lt;/p&gt;

&lt;p&gt;吐槽完闭，该上正文了。&lt;/p&gt;

&lt;p&gt;本文档用到的源码链接如下：
&lt;a href=&quot;https://github.com/jgamblin/Mirai-Source-Code/blob/master/mirai/bot/scanner.c&quot;&gt;https://github.com/jgamblin/Mirai-Source-Code/blob/master/mirai/bot/scanner.c&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;广撒网多捞鱼&quot;&gt;广撒网多捞鱼&lt;/h2&gt;

&lt;p&gt;SYN弱口令扫描，之所以能有极高的扫描速度，与其口令枚举速度无关，而是同其寻找爆破目标的速度有关。这依赖于其能够同时对多个IP进行端口探测（而且单线程即可）。&lt;/p&gt;

&lt;p&gt;想要在所有联网的主机中找到开放指定端口的主机，常规的思路，就是遍历IP，挨个调用connect函数去尝试连接，成功的便是开启了相应端口，反之则是没有开启端口。但connect函数调用后要经历TCP协议的三次握手，才会得到结果，在大批量扫描中，这是相当难以接受的。&lt;/p&gt;

&lt;p&gt;所以几乎在所有常见的“抓鸡扫描器”中都以SYN扫描的形式进行端口状态判断。&lt;/p&gt;

&lt;h3 id=&quot;套接字初始化&quot;&gt;套接字初始化&lt;/h3&gt;

&lt;p&gt;想要进行网络操作，socket套接字是无法避免的，SYN扫描的套接字初始化，和常见的TCP套接字有些区别，详情可参看源码第81行，如下图示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_11_05_12_12/1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;该套接字初始化代码长得有些独特，因为网上最常见的代码一般都长成下面的样子：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;sockfd = socket(PF_INET, SOCK_STREAM, 0);&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;当然也有长这个样子的：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;中间的参数SOCK_STREAM表明该套接字将以流的形式进行读写操作，但SOCK_RAW这个参数却表明该套接字是一个原始套接字，没有经过任何的封装，该种形式的套接字，除了能收发传统的TCP/UDP数据包外，还可以接受ICMP、IGMP等种类的数据包。这是SOCK_STREAM套接字无法做到的。当然，这也需要一定的权限才能做到，现代操作系统下，要求用户必须具有管理员权限才能使用该类功能。&lt;/p&gt;

&lt;p&gt;从这样一条简单的初始化代码就不难发现，该套接字的一生注定不凡。&lt;/p&gt;

&lt;h3 id=&quot;群发syn&quot;&gt;群发SYN&lt;/h3&gt;
&lt;p&gt;TCP三次握手中，第一个操作就是发送SYN信号，它代表发起者的连接意向，当服务端收到该信号后，如果连接条件允许就会回复ACK信号，并正式进入TCP会话协商阶段。这是TCP的基本原理，搞不懂的小伙伴出门左转去问Google。&lt;/p&gt;

&lt;p&gt;此时SOCK_RAW的套接字就可以发挥作用了，从这个创建好的套接字可以用最快的速度向所有目标IP发送数据包。而数据包的构造要完全参照TCP的SYN包格式去构造。详情可参见源码207到234行。如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_11_05_12_12/2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;205行是个for循环，遍历所有的目标IP。循环体中210至232行为数据包的构造代码，比较值得关注的是215行和227行，这两行代码是校验和计算函数，数据包的接收端会通过这个结果判断数据包是否在传输过程中发生错误，如果这个值算错的话，该数据包会被目标无情抛弃，因为数学不好的人没朋友。233行，就是发送函数了，发送的目标由paddr字段指定。&lt;/p&gt;

&lt;h3 id=&quot;地址筛选&quot;&gt;地址筛选&lt;/h3&gt;

&lt;p&gt;ACK请求发送后，无论对方指定端口是否开放，都会拿到一条回复数据包，通过对该数据包分析就能得知那些IP的端口开放了。代码从239行到282行，如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_11_05_12_12/3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;248行依次收取每个主机的回包，249行到271行则负责对收到的数据包进行过滤，将一切不符合端口开放要求的IP进行跳过，能够执行到273行代码就表明，目标的端口是开放的，有必要记录下来等待后续的口令破解。&lt;/p&gt;

&lt;h3 id=&quot;依次建立tcp会话&quot;&gt;依次建立TCP会话&lt;/h3&gt;
&lt;p&gt;将所有开放目标端口的IP地址集中起来后，依次建立TCP会话，为后续破解做准备，此处代码无甚亮点，忽略即可，代码行号299至336行。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_11_05_12_12/4.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;口令枚举&quot;&gt;口令枚举&lt;/h3&gt;
&lt;p&gt;从394开始的while循环，是口令枚举的全部过程，该循环体占地极大，一直持续到整个函数结尾，Yeah你没算错，这个循环体一共有240多行，没法完整截图了，一段一段慢慢看吧。&lt;/p&gt;

&lt;p&gt;396到441行，是从服务端收取数据的代码，如果第一次连接收取到的就是telnet的banner信息，如果非第一次连接收到的就是交互数据。当数据收取失败时，意味着socket中断，还需要重新连接（详见434行）&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_11_05_12_12/5.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;在这个大循环的内部，竟然还存在另一个while循环，使用这种编码方式的同学，都被编程老师骂死了，但种种迹象表明，作者目前还尚在人世，由此推测，Mirai的开发者一定是学校除名，无师自通，自学成才。&lt;/p&gt;

&lt;p&gt;该循环起始于445行，这个while循环一直延续到634行，该while循环用于详细处理爆破过程的交互，它会从服务端发过来的数据分析中，推测当前爆破状态：是需要提供账号，还是要提供密码，再或者已经找到了账号密码，要检查下目标环境是否可用，是否能具有种植bot的必要。这里只选择一个和账号名有关的函数（consume_user_prompt，在788行）来分析，其他函数类似。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_11_05_12_12/6.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;793行到801行，是对输入提示符的测试，常见的输入提示符基本也就这几种，枚举一轮就可以了。802行到810行，是对当前输入要求的检查，“ogin”是“Login”或“login”单词的尾字符，而“enter”则是“回车”的英文单词。检查无误后，基本可以断定当前状态是等待本地输入账户名的状态了。通过这样几行代码来判定账号名输入状态，还是挺好玩的。&lt;/p&gt;

&lt;h2 id=&quot;结束&quot;&gt;结束&lt;/h2&gt;

&lt;p&gt;Mirai的源代码从编码质量上看，基本处在没老师教的状态，但其中用到的一些基础技术，却很值得细细玩味。比如，和跨平台有关的编译技巧，以及跨平台开发技巧，本文提到的SYN扫描技巧，还有未提到的“看门狗喂狗代码”等。这些东西从理论上了解是一种滋味，但被代码实现后，又发酵出另一番滋味。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>万圣节快乐</title>
        <link href="/2016/10/31/%E4%B8%87%E5%9C%A3%E8%8A%82%E5%BF%AB%E4%B9%90.html"/>
	<updated>2016-10-31T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2016/10/31/万圣节快乐</id>
	<content type="html">&lt;h2 id=&quot;happy-halloween&quot;&gt;Happy Halloween&lt;/h2&gt;

&lt;p&gt;相信在不久的将来，万圣节会比儿童节更有趣！！！&lt;/p&gt;

&lt;p&gt;万圣节能实现全球同乐，跨越国界／跨越年龄／跨越性别，而儿童节受众群体相比就要单一的多了。&lt;/p&gt;

&lt;h2 id=&quot;trick-or-treat&quot;&gt;trick or treat&lt;/h2&gt;

&lt;p&gt;西方的万圣节，小朋友们会穿上鬼的装扮，挨家挨户要糖果。俗称“trick or treat”，翻译成中文叫“不给糖果，就捣蛋”，据说，邻里们很乐于拿出一些东西来保平安，以免小孩子们在门口乱涂乱画，调皮捣蛋。&lt;/p&gt;

&lt;h2 id=&quot;结束&quot;&gt;结束&lt;/h2&gt;

&lt;p&gt;这确实是篇没啥营养的博文。洗洗睡了。【laststudy.rar】&lt;/p&gt;
</content>
</entry>

<entry>
	<title>可以租赁的僵尸网络</title>
        <link href="/2016/10/17/%E5%8F%AF%E4%BB%A5%E7%A7%9F%E8%B5%81%E7%9A%84%E5%83%B5%E5%B0%B8%E7%BD%91%E7%BB%9C.html"/>
	<updated>2016-10-17T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2016/10/17/可以租赁的僵尸网络</id>
	<content type="html">&lt;h2 id=&quot;可以租赁的僵尸网络&quot;&gt;可以租赁的僵尸网络&lt;/h2&gt;

&lt;p&gt;近期看到一部分具有“僵尸网络租赁功能”的样本(业内叫“分控”,听起来更文雅了)。&lt;/p&gt;

&lt;p&gt;挑一个样本（162a9a13a734c757bb71b34d19558889）在这里简单记录一下。
那反正这个样本也不太普及，而且样本中bug超多。。分享一下也无甚大碍。。&lt;/p&gt;

&lt;h2 id=&quot;分析过程&quot;&gt;分析过程&lt;/h2&gt;

&lt;h3 id=&quot;控制处理逻辑对比&quot;&gt;控制处理逻辑对比&lt;/h3&gt;

&lt;p&gt;在服务端中可以明显看到两组不同的控制指令处理流程（sub_402ED0，sub_4034E0）。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_10_17_21_15/1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_10_17_21_15/2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;对比两张图不难发现，sub_402ED0 的处理逻辑比sub_4034E0处理逻辑稍显复杂。&lt;/p&gt;

&lt;h3 id=&quot;租赁服务&quot;&gt;租赁服务&lt;/h3&gt;

&lt;p&gt;其中，sub_402ED0函数为租赁服务提供函数，其上线地址为：hr-sky.com:7878。在该函数的case 9 分支中提供了租赁功能，这段功能逻辑中，配置好被租用的上线地址，以及租用时间后即可启动sub_4034E0对应的服务指令，如下所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_10_17_21_15/3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;指令集比对&quot;&gt;指令集比对&lt;/h3&gt;

&lt;p&gt;租赁服务提供方：&lt;/p&gt;

&lt;p&gt;拥有的控制权限较为复杂（sub_402ED0）&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_10_17_21_15/4.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;租赁服务使用方：&lt;/p&gt;

&lt;p&gt;拥有的控制权限较少（sub_4034E0），且当租赁时间到期后，该控制线程会被动关闭。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_10_17_21_15/5.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;功能复现&quot;&gt;功能复现&lt;/h2&gt;

&lt;p&gt;在&lt;a href=&quot;https://github.com/rootkiter/cc_simulator&quot;&gt;“CC模拟器”&lt;/a&gt;的帮助下，可以完美复现以上租赁过程，对应该样本的配置文件为&lt;a href=&quot;/files/l1304v1.py&quot;&gt;l1304v1.py&lt;/a&gt;。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;在可控主机上运行CC模拟器，模拟租赁提供方，并等待样本服务端回连。&lt;br /&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ python simulator.py l1304v1 7878
&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;在虚拟机中，通过修改host文件，接管hr-sky.com的解析地址。&lt;/li&gt;
  &lt;li&gt;在虚拟机中启动样本，“CC模拟器”成功收取上线包，并弹出控制台。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_10_17_21_15/6.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;在一个新的端口上启动模拟器，来模拟租赁使用方。
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ python simulator.py l1304v1 909
&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;从租赁提供方，配置租赁对应参数，如下所示：&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_10_17_21_15/7.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;启动brrow服务，此时可在“租赁服务使用方”获得上线包，并接管控制服务。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_10_17_21_15/8.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_10_17_21_15/9.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;使用租赁服务&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;在配置脚本中提供了dnsflood功能，以便进行dns攻击，配置好攻击目标后，可直接使用。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_10_17_21_15/10.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;攻击指令发出后，wireshark中可抓取到大量的攻击数据包，如下所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_10_17_21_15/11.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;样本bug&quot;&gt;样本BUG&lt;/h2&gt;

&lt;p&gt;样本的实现，具有一定问题，很多功能并不能完美复现，大概遇到这样几个问题：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;以IEFlood为例，在虽然配置的参数无误，但样本在进行参数拼接时，忽略了IE路径中有空格这个状况，导致拼接出的指令无法成功执行，如下图所示：&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_10_17_21_15/12.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;在租赁服务中，stop指令无法生效，原因在于，其对stop指令的处理有误，“停止标志”被误设置为“保持攻击标志”。进而导致攻击一旦发起，就无法终止（除非租赁时间到期）的情况。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_10_17_21_15/13.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
</content>
</entry>

<entry>
	<title>IDAPython的列表选择器</title>
        <link href="/2016/09/01/IDAPython%E7%9A%84%E5%88%97%E8%A1%A8%E9%80%89%E6%8B%A9%E5%99%A8.html"/>
	<updated>2016-09-01T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2016/09/01/IDAPython的列表选择器</id>
	<content type="html">&lt;h3 id=&quot;idapython&quot;&gt;IDAPython&lt;/h3&gt;

&lt;p&gt;最近在研究IDAPython，在做选择器相关的学习的时候，发现书上和网上大部分都是idc脚本的知识，而IDAPython的资料相对较少。搞了一天，才把选择器相关的东西搞清楚，这里记录一下。&lt;/p&gt;

&lt;h3 id=&quot;弹出式选择框&quot;&gt;弹出式选择框&lt;/h3&gt;

&lt;h4 id=&quot;执行效果&quot;&gt;执行效果&lt;/h4&gt;

&lt;p&gt;弹出展示对话框，当双击相应选项时，得到选择结果并销毁该对话框。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_09_01_23_08/1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_09_01_23_08/2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;对应代码&quot;&gt;对应代码&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_09_01_23_08/3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;嵌入式选择框&quot;&gt;嵌入式选择框&lt;/h3&gt;

&lt;h4 id=&quot;执行效果-1&quot;&gt;执行效果&lt;/h4&gt;

&lt;p&gt;在最上层窗口新建一个tab标签，并展示该选择框，这种选择框会一直存在直到用户主动关闭。当用户进行选择时，输出窗口会以默认格式输出选择结果：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_09_01_23_08/4.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_09_01_23_08/5.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_09_01_23_08/6.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;对应代码-1&quot;&gt;对应代码&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_09_01_23_08/7.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;自定义选择框&quot;&gt;自定义选择框&lt;/h3&gt;

&lt;p&gt;在嵌入式选择框中，输出结果为默认格式，且窗口为异步交互，开发者完全无法进行选择结果的捕获，此时如果开发者想要捕获选择结果，则需要通过类继承的方式实现。&lt;/p&gt;

&lt;h4 id=&quot;执行效果-2&quot;&gt;执行效果&lt;/h4&gt;

&lt;p&gt;在嵌入式对话框中，以自定义格式输出选择结果。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_09_01_23_08/8.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;对应代码-2&quot;&gt;对应代码&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_09_01_23_08/9.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;嵌入式多列选择框&quot;&gt;嵌入式多列选择框&lt;/h3&gt;

&lt;p&gt;在之前的选择框中，均为单列选择框（每一选项只有一列内容），当需要对该选项进行更详细的描述时，便无法展示了。此时使用多列的选择框，便可以展示更多的细节信息。&lt;/p&gt;

&lt;h4 id=&quot;执行效果-3&quot;&gt;执行效果&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_09_01_23_08/10.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;对应代码-3&quot;&gt;对应代码&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_09_01_23_08/11.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;弹出式多列选择框&quot;&gt;弹出式多列选择框&lt;/h3&gt;

&lt;p&gt;主体代码同“嵌入式多列选择框”相同。仅有Show函数调用时要指定一个参数。&lt;/p&gt;

&lt;h4 id=&quot;执行效果-4&quot;&gt;执行效果&lt;/h4&gt;

&lt;p&gt;弹出展示对话框，当双击相应选项时，得到选择结果并销毁该对话框。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_09_01_23_08/12.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_09_01_23_08/13.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;对应代码-4&quot;&gt;对应代码&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_09_01_23_08/14.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

</content>
</entry>

<entry>
	<title>分享一个CC模拟器</title>
        <link href="/2016/08/16/%E5%88%86%E4%BA%AB%E4%B8%80%E4%B8%AACC%E6%A8%A1%E6%8B%9F%E5%99%A8.html"/>
	<updated>2016-08-16T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2016/08/16/分享一个CC模拟器</id>
	<content type="html">&lt;h3 id=&quot;空&quot;&gt;空&lt;/h3&gt;

&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;h3 id=&quot;cc模拟器&quot;&gt;C&amp;amp;C模拟器&lt;/h3&gt;

&lt;p&gt;由于最近的工作内容同样本家族的通讯协议关联度很大，为了验证逆向分析的结果，就实现了一个C&amp;amp;C模拟器，来模拟恶意样本的主控端，这个主控端，除了能辅助样本的动态调试，还可以用来验证跟踪程序实现的正确性，可以说对本人工作还是很有帮助的。&lt;/p&gt;

&lt;p&gt;用了一段时间突然意识到，有了这类工具的辅助，就可以迅速将已经抓到的样本为己所用，如果能开发出服务端生成器类型的工具，同样可以很有效的降低攻击成本。&lt;/p&gt;

&lt;h3 id=&quot;地址&quot;&gt;地址&lt;/h3&gt;
&lt;p&gt;python实现的，已经托管到github上了，感兴趣的去下载吧。仅用于模型验证，如果想要用于实战，还有很多细节需要注意。&lt;/p&gt;

&lt;p&gt;https://github.com/rootkiter/cc_simulator&lt;/p&gt;

</content>
</entry>

<entry>
	<title>白蚁上线</title>
        <link href="/2016/07/06/%E7%99%BD%E8%9A%81%E4%B8%8A%E7%BA%BF.html"/>
	<updated>2016-07-06T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2016/07/06/白蚁上线</id>
	<content type="html">&lt;h3 id=&quot;先写点流水账&quot;&gt;先写点流水账&lt;/h3&gt;

&lt;p&gt;这个月是博客断更最久的一段了，我相信，未来一定还可以更久。&lt;/p&gt;

&lt;p&gt;新工作目前基本开始上手了，现阶段主要工作内容有这样几部分吧。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;ol&gt;
    &lt;li&gt;样本yara规则提取：这部分最近几个星期在写一个辅助工具，实现思路基本是，将同家族样本的固定位置的函数人肉圈定出来，再通过交叉比对的方式生成对应的yara规则，样本越多，最终得到的yara规则就会越稳定。&lt;/li&gt;
    &lt;li&gt;自动化C&amp;amp;C地址识别提取，利用yara辅助工具，对同家族各不同样本中的C&amp;amp;C连接相关的函数进行特征提取，随后根据不同的特征规则，编写C&amp;amp;C地址定位程序，进而读取出当前样本对应的C&amp;amp;C主机信息。目前看，有了yara提取工具的辅助，第二部分工作反而相对容易了许多。今天在编写提取程序中发现，对yara规则的提取工具又有了新的要求，估计相当长的一段时间内，应该就是维护这两个工具，让它们相互更好的配合起来吧。&lt;/li&gt;
    &lt;li&gt;未来准备结合日常工作将以上两部分，整理为一个样本分析工作台，这样未来只需要关注样本分析结果，并在工作台上填空，就可以辅助生成yara规则，C&amp;amp;C提取，以及C&amp;amp;C跟踪程序等。构思很宏伟，路途很遥远。&lt;/li&gt;
  &lt;/ol&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;白蚁&quot;&gt;白蚁&lt;/h3&gt;

&lt;p&gt;换新工作后，个人工具的开发进度明显下降了。&lt;/p&gt;

&lt;p&gt;在牺牲了无数休息时间之后，终于修复了几个重大BUG，将白蚁发布出来了，目前该工具可以在 &lt;a href=&quot;http://www.rootkiter.com/Termite/&quot;&gt;白蚁&lt;/a&gt; 获得，欢迎各位白帽子大牛在基于内网的“后渗透测试”时试用。&lt;/p&gt;

&lt;p&gt;在新版本的工具实现过程中，我个人又学到了非常多的技术细节，虽然工具还是一身BUG，不过就我个人而言，还是非常有技术成就感的。&lt;/p&gt;

&lt;h3 id=&quot;白蚁技术概览&quot;&gt;白蚁技术概览&lt;/h3&gt;

&lt;p&gt;关于“跨平台的技术”实现，就不再啰嗦了，在原公司的技术大会上做过技术分享。其实，那份PPT已经被传的满大街都是了。感兴趣又没见过的小伙伴去网上搜吧。&lt;/p&gt;

&lt;p&gt;其余的技术概述，将在下方以文字的方式慢慢介绍，感兴趣的朋友可以详细阅读：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;ol&gt;
    &lt;li&gt;资源锁：由于工具中有一部分网络服务器的属性，所以实现中需要对“异步socket通讯／异步多线程／线程间资源共享”等属性进行融合。这就涉及到“资源竞争访问”的问题，如果多个线程同时写一个位置的资源，就会造成数据不同步，或数据错误的问题。这时就需要实现资源锁了。工具早期的做法是用代码实现了一个假的资源锁，这种锁能够解决大多数的问题，但当访问的并发数量激增时，还是会导致程序出现异常并终止。近期在阅读gcc相关资料时，发现gcc内置了一套原子操作方法，可用于实现资源锁，目前正在测试其稳定性，以及跨平台的特性，如果问题不大，会在工具中统一使用。&lt;/li&gt;
    &lt;li&gt;远程多平台管控是如何做到的：当代码对多平台进行统一接口抽象后，同样的代码在所有平台产生的效果就是相同的，此后，只要定义好通讯协议，就自然可对多平台间进行远程管控。&lt;/li&gt;
    &lt;li&gt;如何做到节点间网络控制：在“蚯蚓”实现过程中，我就发现了“反向新隧道建立”的妙用，将该种方式进行一次“正反向隧道统一抽象”后，就可以实现“隧道转接及透传”。为了做到能够对任意跳板节点进行管理，我还参考了路由器对“IP数据报文”的路由处理方式，在被控节点中实现了一个“私有路由”协议。进而实现了管控数据在节点间转发这一效果。&lt;/li&gt;
  &lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;“白蚁”相对“蚯蚓”新增加的核心技术大概也就这些了，相信思考过相关问题的小伙伴一定能读懂，没思考过的小伙伴估计理解起来会很吃力。然而，我也只能说到这个程度，时间是有限的，我还有更多更有意义的事要去做。&lt;/p&gt;

&lt;h3 id=&quot;版本规划情况&quot;&gt;版本规划情况&lt;/h3&gt;

&lt;p&gt;当前版本，由于架构遗留问题还存在一些无法修复的BUG，而目标架构和下一版本的需求极为吻合，所以这些BUG要留在下一版本进行实现。下面简单说一下规划情况：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;第一版&lt;/strong&gt;：蚯蚓&lt;br /&gt;
&lt;strong&gt;第二版&lt;/strong&gt;：白蚁&lt;br /&gt;
&lt;strong&gt;第三版&lt;/strong&gt;：未定名：主要解决通讯层面的问题，节点间可基于UDP／TCP等多种协议(ICMP协议的可行性正在测试中)进行数据转发，用于越过不同种类的防火墙。&lt;br /&gt;
&lt;strong&gt;第四版&lt;/strong&gt;：未定名：主要解决二次开发的问题，在管理节点端提供多种语言的API接口，供二次开发使用，以方便第三方工具的支持。&lt;br /&gt;
&lt;strong&gt;第五版&lt;/strong&gt;：未定名：添加插件支持，将管理节点转型成一个跳板机管理平台，通过完善插件，实现更多的跳板机控制及管理功能。&lt;br /&gt;
&lt;strong&gt;第N版&lt;/strong&gt;：未定名：这是一个终极YY的版本，可能永远只能停留在幻想中，我希望它未来能够是一个“APT渗透测试平台”，集合“自动化主机探测”，“自动化渗透测试”，“自动化组网传播”，“自动化变种隐身”，“通讯协议自适应”等众多优秀功能，总的来说是希望它是一个能融合众多前沿技术的大平台，能够做到“精尖/精简/惊见”。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;好了，牛逼吹完了，该继续苦逼的生活了。晚安。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>NewWorld</title>
        <link href="/2016/05/28/NewWorld.html"/>
	<updated>2016-05-28T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2016/05/28/NewWorld</id>
	<content type="html">&lt;h3 id=&quot;新世界&quot;&gt;新世界&lt;/h3&gt;
&lt;p&gt;又近一个月没有更新博客了，大体上，这个月做了两件事：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;1.去泰国玩了一个星期（真的是玩，不是做手术，想歪的小伙伴可以面壁去了）。&lt;br /&gt;
 2.新公司入职，并上了一个星期班。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;所以我觉得，这个月过的很充实。对我个人来说无论是泰国，还是新公司都是新世界。姑且把这个月定为一个人生转折点吧，来一个振奋人心的海报纪念一下。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_05_28_10_46/1.png&quot; alt=&quot;图图图&quot; /&gt;&lt;/p&gt;

&lt;p&gt;不喜欢拍照，所以也没怎么拍照，就不贴图了，文字记录吧。&lt;/p&gt;

&lt;h3 id=&quot;泰国&quot;&gt;泰国&lt;/h3&gt;

&lt;p&gt;由于和另一个小伙伴离职时间大体相同，所以结伴去了趟泰国玩了几天。&lt;/p&gt;

&lt;p&gt;按照已有的认知，这里是个很神奇的国度，它是个佛教深入人心的国家，按理说应该对欲望有所节制，但却在“性”这个问题上大做文章。由于觉得在某些角落部署“红灯区”不够过瘾，又想尽办法创造出了人妖，这一人类新物种。&lt;/p&gt;

&lt;p&gt;泰国本地的食物，有一部分口味独特到想吐，这其中比较有代表性的就是那个“冬阴功汤”。不过美食也还是有的，比如“菠萝饭”就超级好吃，其实期间吃到了一个走街串巷的小吃，不过语言不通，根本不知道那是个什么吃食。简单来说，就是把各种水果蔬菜和调料放到一个缸子里砸碎出汁，搅拌后配合类似米线一类的主食去吃，一种特殊的好吃。&lt;/p&gt;

&lt;p&gt;对于国人来说，泰国的物价还是蛮便宜的，汇率基本维持在1比5.3以上。在一个普通的饭馆，不到20人民币，两个人就可以吃到炒饭，而且吃的还相当满足。&lt;/p&gt;

&lt;p&gt;去芭提雅的路上，遇到一个马来西亚人，他说自己要在芭提雅试着找工作，然后边赚钱边游玩。攒够下一站路费后，再继续去下一个地方边赚钱边玩。看起来应该有40-50岁了，去过了四个国家，泰国是第五站。&lt;/p&gt;

&lt;p&gt;在泰国期间，我最常做的事：就是指着一个东西，口中念着“How much”。。。好在，做生意的人都很老道，每人手头都有计算器，所以，他不需要说泰语，你也能知道你想要的答案。:-P&lt;/p&gt;

&lt;p&gt;其他的嘛，英文交流就完全马马虎虎了，每当听到一个熟悉的词汇，都兴奋好久，然后自然就错过了语句中其他单词。。。&lt;/p&gt;

&lt;p&gt;能上台的人妖，确实都很漂亮，让人有一种人妖比女人好看的错觉。事实上，台下的那些ladyboy，通常都长的很着急。&lt;/p&gt;

&lt;p&gt;回程的那天白天，还去射击场打了一些实弹，左轮／普通手枪／散弹枪／M16，都体验了一遍，感觉还是挺爽的，其中M16比较沉，持枪很累。没打到狙击步枪还是挺遗憾的。&lt;/p&gt;

&lt;p&gt;gogobar 是什么鬼，我真的没听过，完全没听过，不要问我呀[害羞ing]。。。&lt;/p&gt;

&lt;h3 id=&quot;公司的新世界&quot;&gt;公司的新世界&lt;/h3&gt;
&lt;p&gt;目前为止，已经入职一周了，新公司完全是另一个世界。在传统厂商呆惯了，新到互联网公司，就各种新奇。&lt;/p&gt;

&lt;p&gt;其实新公司的口碑不算好，本人也多次说过它坏话，但这并不会影响我在这里工作。因为，我讨厌的是公司的对外形象，而不是公司本身，对于用户来说，一些行为确实让人不爽；但对于员工来说，最重要的是公司对员工是否负责，公司的同事是否有人情味，干的活是否够有趣，在这里工作是否能够成长。好在现阶段，我觉得这几项已经合格了。部门的新伙伴们都很和谐，领导也够亲民，就连HR妹纸们也很nice。&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;/p&gt;

&lt;p&gt;新工作要接触的新知识非常之多，除了样本分类技能外，还需要有一些数据挖掘和处理的能力，上一份工作让我持续学习了接近四年，不知道这一份工作能让我学多久呢，从这里出去后，又会是一个什么状态呢，还是让时间来给出答案吧。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>不会忘记</title>
        <link href="/2016/05/03/NeverForget.html"/>
	<updated>2016-05-03T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2016/05/03/NeverForget</id>
	<content type="html">&lt;h3 id=&quot;难忘今宵&quot;&gt;难忘今宵&lt;/h3&gt;

&lt;p&gt;这是个相当有滋味的梗，每当圈内有人离职，这个梗都会被重提。它原是每年春晚的经典曲目，但给这个词赋予新含义的，是安全圈的一位教主级人物。在这里&lt;a href=&quot;https://www.zhihu.com/question/20835089&quot;&gt;强行膜拜一波教主&lt;/a&gt;。&lt;/p&gt;

&lt;h3 id=&quot;之前&quot;&gt;之前&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_05_03_22_43/1.jpg&quot; alt=&quot;书籍照片&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这是第一份工作，本科毕业就入职工作。四年来，技术上的增进可观，学的越多，反而意识到蓝海越大。不同的线索交织在一起，学科间相生相克。在完成项目的同时，还可畅游在无数的书海中。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_05_03_22_43/2.jpg&quot; alt=&quot;牌子照片&quot; /&gt;&lt;/p&gt;

&lt;p&gt;领到公司纪念牌的一刻，心情其实是极为复杂的，上次出现这种复杂心情，还是大学领毕业证的时候。&lt;/p&gt;

&lt;p&gt;四年中经历了三届直接领导，每位领导也都对我关爱有加。从某种角度讲，我是个不好管理的员工，随性工作，随性学习，总挑些有挑战的事情做，重复性的工作又常会心生排斥，面对这样刁钻的员工，没有领导的包容，真的无法工作这么久。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_05_03_22_43/3.png&quot; alt=&quot;海贼王小伙伴截图&quot; /&gt;&lt;/p&gt;

&lt;p&gt;其实提起工作以来最大的收获，还是结识了一大批志同道合的小伙伴，一起吐槽，一起工作，没有争名逐利，没有勾心斗角；坦荡做人，安心做事；没有套路，尽是真诚。我想，人生中能遇到这样一批小伙伴，足以。&lt;/p&gt;

&lt;h3 id=&quot;之后&quot;&gt;之后&lt;/h3&gt;

&lt;p&gt;两年前，我喜欢看一个脱口秀节目叫《罗辑思维》，在那个年月，这个节目还不像现在这样功利，是一个很有含金量的节目。其中有过这样一句话：成功就是，20岁有人愿意带，30岁有人愿意用，40岁有人跟，50岁桃李满天下。这是段非常有趣的话，我一直觉得这比孔老夫子的那句“三十而立,四十不惑”牛逼大了。&lt;/p&gt;

</content>
</entry>

<entry>
	<title>记一个组建僵尸网络的样本</title>
        <link href="/2016/03/16/%E8%AE%B0%E4%B8%80%E4%B8%AA%E7%BB%84%E5%BB%BA%E5%83%B5%E5%B0%B8%E7%BD%91%E7%BB%9C%E7%9A%84%E6%A0%B7%E6%9C%AC.html"/>
	<updated>2016-03-16T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2016/03/16/记一个组建僵尸网络的样本</id>
	<content type="html">&lt;h3 id=&quot;多平台支持&quot;&gt;多平台支持&lt;/h3&gt;

&lt;p&gt;僵尸网络已经从传统的PC端向智能设备过度，最近抓到了一个被安置于“硬盘录像机”的BotNet僵尸样本。该样本家族（它真的是个家族）可以运行在mips/powerPC/superh /sparc 等多种CPU下，可支持所有以Linux为基础的操作系统。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_03_16_22_59/1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;基本结构&quot;&gt;基本结构&lt;/h3&gt;

&lt;p&gt;多种僵尸终端可以通过一个共同的“C&amp;amp;C服务器”进行控制，如此使用既可以增加僵尸网络的受控端，又可以降低操控成本。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_03_16_22_59/2.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;此家族样本，受控能力偏弱，可以说只具有DDos攻击的能力，如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_03_16_22_59/3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;特点&quot;&gt;特点&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_03_16_22_59/4.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;ol&gt;
    &lt;li&gt;&lt;strong&gt;隐蔽性&lt;/strong&gt; 管理员一般都对PC主机（X86/X64）的管理比较熟练，当PC主机发生异常时，从中提取样本的概率很大。此时通常很难发现并抓到样本，提高了攻击的隐蔽性。&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;扩展性&lt;/strong&gt; 无论僵尸机是哪种设备，服务端都相同，如此既可以降低攻击成本，又可以增加僵尸机潜在群体。&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;难于分析&lt;/strong&gt; 要分析相应样本要先熟悉对应的CPU汇编指令集，提高了技能门槛。另一方面，程序调试要在一个完整的调试环境下进行，而智能设备通常经过阉割，很难构建一个完整的调试环境，这也无形中提高了分析门槛。&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;易于构建&lt;/strong&gt; 攻击者只要能够编写出某一Linux系统下的受控端，就可以很容易的将源码转化为其他设备平台下的受控端，投入成本很小，收益却很大。&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;躲避虚拟执行&lt;/strong&gt; 目前虚拟执行是样本自动化分析的一个重要手段，而智能设备下的样本通常无法找到对应的虚拟执行环境，所以自动分析引擎大部分时刻都会失效。&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;易于传播&lt;/strong&gt; 智能设备的漏洞具有足够的稳定性，一旦被发现很难被修复。另一方面，目前非常多的智能设备都被爆出后台默认口令的问题，这也在一定程度下降低了攻击成本。&lt;/li&gt;
  &lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;综上所述，这是一种极易操作的DDOS攻击方式，攻击成本提升一小步，攻击收益提高一大步，另一方面，目前已知的防御手段却很少，基本没有安全厂商在专注这方案的防御。可以说，这是一种很有趣的僵尸网络组建方法。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>从孙悟空开始</title>
        <link href="/2016/03/11/%E4%BB%8E%E5%AD%99%E6%82%9F%E7%A9%BA%E5%BC%80%E5%A7%8B.html"/>
	<updated>2016-03-11T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2016/03/11/从孙悟空开始</id>
	<content type="html">&lt;h3 id=&quot;引&quot;&gt;引&lt;/h3&gt;

&lt;p&gt;今年是猴年，“孙悟空”是猴子的一种象征，年假回家便围绕“孙悟空”思考了很多。我从来没有像那时那样认真的思考过“孙悟空”的一生，一顿考虑过后，猛然发觉小时崇拜的孙悟空，就好像是一部分技术人员的缩影，纵使你有经天纬地之才，也只是他人手中的工具而已。&lt;/p&gt;

&lt;p&gt;刚刚撸代码撸累了，回味了一下，便写在这里，没事时自己回顾一下也是好的。&lt;br /&gt;
事先声明：这就是一篇“流水账”，完全没有“逻辑和章法”，看点就是我的脑洞够不够大，哇哈哈。&lt;/p&gt;

&lt;h3 id=&quot;孙猴子的职业生涯&quot;&gt;孙猴子的职业生涯&lt;/h3&gt;

&lt;p&gt;从拜师开始，孙悟空便不再是它自己（准确来说，其实是从它出生）。他被菩提老祖植入了固定的行事逻辑，掌握一身本领的同时，却没有教其做人的品德。他之所以被培养出山，仅是被用来捣乱的。他是佛教“争权的工具”，是“佛道相争”的“炮灰”。最终的“斗战胜佛”究竟是他本人，还是“六耳猕猴”，也成了一个永远的谜。&lt;/p&gt;

&lt;p&gt;他有72般变化，能使得筋斗云。这是何等嚣张，但在取经途中却发现，本领再高强也不如给自己找个后台。慢慢的，他不再争强斗狠，懂得了处理佛/道/天庭三者间的关系，最终成了一名合格的取经人。&lt;/p&gt;

&lt;p&gt;这就是“孙悟空”的职业生涯。磨平了棱角，不再争斗。我开始疑惑这样的“孙悟空”究竟还是不是“孙悟空”。&lt;/p&gt;

&lt;h3 id=&quot;止不住的思绪&quot;&gt;止不住的思绪&lt;/h3&gt;

&lt;p&gt;一直有句奇怪的话：“技术”最终要转向“管理”。这似乎成了一项成功的指标。似乎磨平棱角，不再争斗，才能取得成功一样。。。&lt;/p&gt;

&lt;p&gt;小时家里有一些老制的木制家具，年久变形，便会在四角加上“固定三角铁”以起到支撑作用。“固定三角铁”在保证家具不变形的同时，又要确定每一个螺丝钉的摆放位置。它是一个合格的管理者，而螺钉就是它的助手。&lt;/p&gt;

&lt;p&gt;每位“技术人”都可以被理解为一个螺丝钉。平时日常使用，一般都根据“三角铁”孔洞的大小去找螺丝钉，家里没有，便去邻居家找，便去“五金商店”买。没有哪个螺丝钉是不可替换的，他们长得都差不多，尺寸样式都是固定的，总能找到合适的，并不费力气。这些螺钉们为了提高自己的身价，想到了一条箴言：“技术”最终要转向“管理”。这条箴言还有个近似的版本：“你不能干一辈子技术。”&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;这些话对么？对。&lt;br /&gt;
这些话真对么？ (划魂)&lt;br /&gt;
这些话有普适性么？（好像缺那么点意思）&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;对于一个满大街都有的螺丝钉来说，这些话确实是至理名言。但对于某些特殊功能的螺丝钉来说，就未必了。它们使用领域很小，但当有人想要完成一个特殊任务时，缺了那种螺丝钉，它就是不行。
比如有这样一个例子《&lt;a href=&quot;http://www.nippon.com/cn/features/c00602/&quot;&gt;Hard Lock工业 永不松动的螺钉&lt;/a&gt;》。这是一种不可思议的螺钉。&lt;/p&gt;

&lt;h3 id=&quot;结&quot;&gt;结&lt;/h3&gt;
&lt;p&gt;既没有主题也没有中心，有开头，却又没有结尾。&lt;/p&gt;

&lt;p&gt;唯一符合的，是它在我脑中的思维顺序。&lt;/p&gt;

&lt;p&gt;所以别纠结啦。原汁原味也挺好。。。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>验证码生成新思路</title>
        <link href="/2016/02/20/%E9%AA%8C%E8%AF%81%E7%A0%81%E7%94%9F%E6%88%90%E6%96%B0%E6%80%9D%E8%B7%AF.html"/>
	<updated>2016-02-20T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2016/02/20/验证码生成新思路</id>
	<content type="html">&lt;p&gt;白天在果壳看到这样一篇文章：《&lt;a href=&quot;http://www.guokr.com/article/441154/?page=2&quot;&gt;这也许将是围棋AI的最后死穴&lt;/a&gt;》，这文章原本是以围棋AI为引子，试图提出如何对抗计算机AI，但是它里面提到了一个“对抗样本”的东西，蛮有趣的。&lt;/p&gt;

&lt;p&gt;其实，验证码的目的就是分清楚，当前用户是“自然人”，还是“计算机”。目前主流的验证码识别技术，还是以“图片识别”为主，虽然依赖互联网技术也有“人力打码”的案例，但那种成本还是很高的。文中提到的“对抗样本”，其实是利用了“图片识别”的弱点，在“人眼”和“计算机眼”中间制造了一些混乱，这很符合“验证码”的设计需求。怎么看也比12306的那个愚蠢的思路要靠谱。。。况且现在基本所有网站的验证码都是“人看不懂，机器也看不懂”，每次打验证码都是一种煎熬。这堆垃好好优化下了。&lt;/p&gt;

&lt;p&gt;过年回家就没维护博客，现在年早已经过去了，班也都上了一周了。再次认证了一条真理：“假期永远不够用”。。。自由职业，一直是咱的梦想，希望有一天能实现。如果无法实现自由职业，财富自由也是好的嘛。。。哇擦！口水流了一嘴丫，又做美梦啦。。。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>无所不能的SHELL脚本</title>
        <link href="/2016/01/29/%E6%97%A0%E6%89%80%E4%B8%8D%E8%83%BD%E7%9A%84SHELL%E8%84%9A%E6%9C%AC.html"/>
	<updated>2016-01-29T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2016/01/29/无所不能的SHELL脚本</id>
	<content type="html">&lt;h2 id=&quot;起因&quot;&gt;起因&lt;/h2&gt;

&lt;p&gt;最近同事接到一个应急，客户的局域网服务器被中病毒了，影响规模有数千台主机，服务器均为Linux，但均属于不同的发行版，多半为Ubuntu和SuSE，为了能够节省检测和查杀的人力成本，有必要通过工具予以实现。&lt;/p&gt;

&lt;p&gt;在选择实现语言的过程中出现了麻烦的事。如果用C语言开发，开发周期过长，而且细粒度语言可能碰到的坑会非常多。如果用Python开发，Ubuntu问题不大，系统一般都会内置，但是SuSE系统就悲剧了，人家默认就没这东西，写出的代码完全无法运行，如果查杀前再需要先装Python运行环境，那还不如手工查杀来的快呢。&lt;/p&gt;

&lt;p&gt;经过慎重选择，决定使用“SHELL脚本”来实现，这东西基本每台Linux都会有，不会出现无法运行的情况。碰巧，今天心情不错，就把“SHELL脚本”的一些用法做个汇总，以打消外人对SHELL脚本的误解。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;从不只一个人的口中听说过：SHELL只能做些无脑的文件和命令操作，我今天要告诉他们SHELL脚本连病毒的检查及清理都可以实现，还有什么东西能难住它？&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;shell脚本中的技巧和坑&quot;&gt;SHELL脚本中的技巧和坑&lt;/h2&gt;
&lt;h3 id=&quot;文件特征检测&quot;&gt;文件特征检测&lt;/h3&gt;
&lt;p&gt;要查病毒，特征检测是绕不过的，通常思维下Shell脚本对文件内容的处理是比较难搞的，经过一段时间的思考，找到了一条相对稳定的实现方案，如下所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_01_28_23_34/1.png&quot; alt=&quot;图1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;整个逻辑的关键代码为 14 行，它涉及到4个命令的使用:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;xxd指令可以将文件内容以16进制编码格式进行输出，此时输出的内容中存在换行符;&lt;/li&gt;
  &lt;li&gt;将上一个结果中的换行符过滤掉，变成一行;&lt;/li&gt;
  &lt;li&gt;使用grep对文件内容进行过滤，过滤规则为41414141特征，这个特征对应的ASCII编码为4个A；&lt;/li&gt;
  &lt;li&gt;用wc指令进行行数统计，如果文件中存在特征，则经过grep过滤后，会有内容输出，即行数不为0。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;测试可以用两个文件file1 和file2，其中file2文件有AAAA特征file1无该特征，如下所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_01_28_23_34/2.png&quot; alt=&quot;图2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;然后运行脚本将file2文件检测出来，测试结果如下：
&lt;img src=&quot;/images/2016_01_28_23_34/3.png&quot; alt=&quot;图3&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;变量展开&quot;&gt;变量展开&lt;/h3&gt;

&lt;p&gt;在“SHELL脚本”编写中，函数定义是一定会经常用到的。对函数进行参数传递时，也经常会遇到变量传递，如下所示:
&lt;img src=&quot;/images/2016_01_28_23_34/4.png&quot; alt=&quot;图4&quot; /&gt;
&lt;img src=&quot;/images/2016_01_28_23_34/5.png&quot; alt=&quot;图5&quot; /&gt;&lt;/p&gt;

&lt;p&gt;从func函数的执行效果可知，该函数传入的参数有两个，且第一个参数的值为value1 虽然在函数调用中，是以&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;func $valueList&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;这样的方式进行参数传递，但在函数执行的过程中参数内容被展开了，变成了下面的样子&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;func value1 value2&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;这和C语言中的宏很像，这个问题我在脚本编写中遇到了多次，每次都会导致极为隐蔽的BUG。其实规避方法很简单，那就是将变量以双引号扩起来即可，如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_01_28_23_34/6.png&quot; alt=&quot;图6&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/images/2016_01_28_23_34/7.png&quot; alt=&quot;图7&quot; /&gt;&lt;/p&gt;

&lt;p&gt;可以看到双引号扩起来后，函数执行时就仅有一个参数了，而且参数内容也是完整的valueList内容了。&lt;/p&gt;

&lt;h3 id=&quot;shell四则运算&quot;&gt;SHELL四则运算&lt;/h3&gt;

&lt;p&gt;没做过SHELL开发的人，经常会忽略SHELL能做四则运算这一事实，让SHELL能做四则运算的关键在于let这个关键字，用法如下所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_01_28_23_34/8.png&quot; alt=&quot;图8&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/images/2016_01_28_23_34/9.png&quot; alt=&quot;图9&quot; /&gt;&lt;/p&gt;

&lt;p&gt;然而能让 shell 中的四则运算正常工作，却需要规避几个重要的坑才行，&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;切忌等号&lt;strong&gt;前后均&lt;/strong&gt;不应有空格，否则你会遇到这样的错误&lt;br /&gt;
&lt;img src=&quot;/images/2016_01_28_23_34/10.png&quot; alt=&quot;图10&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/images/2016_01_28_23_34/11.png&quot; alt=&quot;图11&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;切忌书写let关键字，否则你会遇到这样的错误
&lt;img src=&quot;/images/2016_01_28_23_34/12.png&quot; alt=&quot;图12&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/images/2016_01_28_23_34/13.png&quot; alt=&quot;图13&quot; /&gt;&lt;br /&gt;
可以看到它试图将第9行的 2+3 当作命令去执行，结果就报错了。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;运算符&lt;strong&gt;前后均&lt;/strong&gt;不应有空格，否则你会遇到这样的错误
&lt;img src=&quot;/images/2016_01_28_23_34/14.png&quot; alt=&quot;图14&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/images/2016_01_28_23_34/15.png&quot; alt=&quot;图15&quot; /&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;函数返回值&quot;&gt;函数返回值&lt;/h3&gt;
&lt;p&gt;准确来说shell脚本的返回值有两种，一种结果代表执行状态，另一种是执行结果。样例代码如下所示：
&lt;img src=&quot;/images/2016_01_28_23_34/16.png&quot; alt=&quot;图16&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/images/2016_01_28_23_34/17.png&quot; alt=&quot;图17&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;字符串转数组&quot;&gt;字符串转数组&lt;/h3&gt;

&lt;p&gt;在SHELL脚本中是有数组概念的，虽然只有一维数组，但也完全足够日常使用了，如果想要多维数组，只有自己去实现了，相信小伙伴们能够想到些办法，我就不解释了。下面展示一个将列表转为数组的代码，以便大家熟练数组的转换。&lt;br /&gt;
&lt;img src=&quot;/images/2016_01_28_23_34/18.png&quot; alt=&quot;图18&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/images/2016_01_28_23_34/19.png&quot; alt=&quot;图19&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;循环&quot;&gt;循环&lt;/h3&gt;
&lt;p&gt;除了常见的通过if语句判断循环条件外，shell 中提供了 for…in… 语法糖。代码样例如下所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016_01_28_23_34/20.png&quot; alt=&quot;图20&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/images/2016_01_28_23_34/21.png&quot; alt=&quot;图21&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;结尾来个小公告&quot;&gt;结尾来个小公告&lt;/h2&gt;

&lt;p&gt;好久没来更新博客了，因为在忙各种总结，同时“蚯蚓2.0(暂定这么个名字吧，我决定给它换个名字)”终于进入最后的集成测试阶段了，上午写完了最后一行功能代码，那一刻我觉得自己又“如来附体”“无所不能”了。&lt;/p&gt;

&lt;p&gt;正式公布前，它还需要经历几个步骤，分别有：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;交互强化，主要解决帮助文本的措辞，以及提高容错能力。&lt;/li&gt;
  &lt;li&gt;平台通配测试，要对各主要系统平台进行通配测试。&lt;/li&gt;
  &lt;li&gt;小范围分发测试，主要是BUG修复，以及不合理的逻辑修改。&lt;/li&gt;
  &lt;li&gt;重定名以及主页开发，每个大版本都要重新命名，并为其配一个主页，2.0当然不会例外。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;所以距离正式上线可能还需要2个月左右的时间吧，要做的事情还有很多，要加把劲了。&lt;/p&gt;

</content>
</entry>

<entry>
	<title>元旦快乐</title>
        <link href="/2015/12/31/%E5%85%83%E6%97%A6%E5%BF%AB%E4%B9%90.html"/>
	<updated>2015-12-31T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/12/31/元旦快乐</id>
	<content type="html">&lt;h2 id=&quot;2015&quot;&gt;2015&lt;/h2&gt;

&lt;p&gt;这一年技术成长比较缓慢，一直都是一个瓶颈期，而且还没见到突破的前兆。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;今年公司的服务类项目做的比较少，主要是做了两个内部项目，虽然对这两个项目的前景并不看好，但对我写代码的能力有很大提升，也算是一种收货吧。&lt;/li&gt;
  &lt;li&gt;7月初，租的房子到期了，期间换了一次房子。也算是和之前的3年告别了。也开始了新的生活状态。&lt;/li&gt;
  &lt;li&gt;把蚯蚓1.0 写完并发布出来了，算是迈出了第一步吧，其实2.0版本也快写完了，不过看来是明年的事了。&lt;/li&gt;
  &lt;li&gt;把博客维护了起来，添了能有20篇左右的文章，也算是留给未来的一个回忆吧。&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;h2 id=&quot;2016&quot;&gt;2016&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;现在好像除了计算机技术以外，对其他事情的兴趣都下降了，这貌似不是什么好状态，有必要改改了，多出去走走，认识些不一样的人也挺好的。&lt;/li&gt;
  &lt;li&gt;把蚯蚓2.0写完，如果时间允许也要尝试把3.0写完，到那时应该就能在圈内有些小名气了。同时也能学到非常多的基础知识。能为突破瓶颈做好准备。&lt;/li&gt;
  &lt;li&gt;领完公司的3年牌，也要考虑些该考虑的事情了，希望能找个实验室学3年，如果可以的话，再积累些原始资本，该为未来打些基础了。&lt;/li&gt;
  &lt;li&gt;好像也是时候该积累些圈内的人脉了，之前一直不怎么关注这方面，是希望自己能专心打好基础，目前感觉基础已经差不多了，想要突破其实还需要一些外力，人脉是能得到外力的比较容易实现的途径。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;就这样吧&quot;&gt;就这样吧&lt;/h2&gt;

&lt;p&gt;如果有人连这篇博文都看了，那证明你是真粉。既然如此，就祝你元旦快乐，在新年里心想事成吧。&lt;/p&gt;

&lt;p&gt;另外，今天在网上看到了一个有趣的人，&lt;a href=&quot;http://www.dandyweng.com&quot;&gt;翁天信&lt;/a&gt;，挺羡慕的，原来还可以有这样的人生。。。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>好久没来更新博客了</title>
        <link href="/2015/12/20/%E5%A5%BD%E4%B9%85%E6%B2%A1%E6%9D%A5%E6%9B%B4%E6%96%B0%E5%8D%9A%E5%AE%A2%E4%BA%86.html"/>
	<updated>2015-12-20T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/12/20/好久没来更新博客了</id>
	<content type="html">&lt;h2 id=&quot;最近好忙&quot;&gt;最近好忙&lt;/h2&gt;
&lt;p&gt;连续一个多月了，一直比较忙，也没空来写博客，今天抽空就简单写写最近在做的事情吧，以免博客长了草。&lt;/p&gt;

&lt;h2 id=&quot;都忙了啥&quot;&gt;都忙了啥&lt;/h2&gt;
&lt;ol&gt;
  &lt;li&gt;公司正常的服务类项目。作为安全服务类的工程师，当然得干活啊，要不为嘛发你工资呢。。&lt;/li&gt;
  &lt;li&gt;备课。前段时间公司要参加大比武，我们部门牵头搞公司内部培训，从备课到筛选忙成了狗。&lt;/li&gt;
  &lt;li&gt;当了几天师傅。某事业单位的朋友人要参加他们内部的竞赛，想要临时抱佛脚，所以我凑巧当了两天师傅。&lt;/li&gt;
  &lt;li&gt;膜拜几个同事。最近在应急时碰上个标准的APT应急，我个人觉得这个APT已经标准到可以写进教科书了，据说请了几个公司都没抓到，最后被我们部门同事“@吃水的蚊子”抓到了，然后我和部门的另一个同事 @goabout2 一起分析样本，我个人是以赏析的角度在分析样本，因为它对我蚯蚓未来的升级有很多帮助。在样本分析的过程中也意识到公司研究院有一位真神“@TeLeMan”,他把样本的整个控制逻辑以及配置文件的加密算法都完全逆出来了，达到了可以追踪这个APT近况的效果。让人打心底佩服。于是我就有了新的奋斗目标。。哈哈。&lt;/li&gt;
  &lt;li&gt;蚯蚓升级。最近几个月一直再做的另一个长期任务是“蚯蚓2.0”的编码任务，现在编码已经进行了大半，预计明年2－3月份应该能有新版本发布。2.0将在1.0的数据转发基础上添加文件传输和SHELL命令支持。并且以Agent管理的思路，对多层次主机进行实时管理控制。届时，蚯蚓将完成一次脱胎换骨的改变（所以我最近也在忙着为它起名字），成为真正的网络穿梭利刃。目前蚯蚓的未来会有4个新的版本规划。其中，从第2个新版本开始将会进行产品线拆分，分别针对“内网安全”方向，和“万物互联”方向，其中“内网安全”方向将以“APT渗透测试平台”为最终发展目标。而“万物互联”方向将以核心通讯库为发展目标，未来准备将它做成所有操作系统都默认支持的普适性基础库，它的优点之一是可以继续扩充 IPv4 的服役时间，同时还能将网络中所有的智能设备从网络层进行整合，无论两台设备之间有多少道防火墙，或距离多少个网段，只要它们之间存在可达路径，就能实现相互通信。这么牛逼的东西，想想就让人兴奋到睡不着啊。哇咔咔。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;完&quot;&gt;完&lt;/h2&gt;
&lt;p&gt;起初蚯蚓是我练手的项目，但越构思越发现它价值巨大，所以我把蚯蚓又变成了一个长期项目，准备用它贯穿我整个的技术生涯（10年打底）。一方面要加的功能实在太多，另一方面在加功能的过程中还要补充新的技术知识，来支撑功能实现。比如3.0版本中的多种通讯协议支持，APT测试平台方向时多平台rootkit技术等都是很少有公开资料的小众技术，所以定期充电的情况也会越来越频繁。等到我把现在要实现的功能都实现了，我觉得自己就能是真正的大神了吧。。。想想就有些小激动呢。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>ShellCode也是一门学问</title>
        <link href="/2015/11/07/ShellCode%E4%B9%9F%E6%98%AF%E4%B8%80%E9%97%A8%E5%AD%A6%E9%97%AE.html"/>
	<updated>2015-11-07T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/11/07/ShellCode也是一门学问</id>
	<content type="html">&lt;h2 id=&quot;开个头&quot;&gt;开个头&lt;/h2&gt;
&lt;p&gt;最近拿到一道题，推测应该是西电的CTF题，来源很模糊，我也道不清原委，反正几经辗转到了我手里。&lt;br /&gt;
这道题非常好，即考察了逆向能力，又考察了shellcode变形的一些知识。&lt;/p&gt;

&lt;p&gt;如果有机会再参与CTF出题，这道题绝对是一个值得花心思借鉴的题目。&lt;/p&gt;

&lt;h2 id=&quot;题目概述&quot;&gt;题目概述&lt;/h2&gt;
&lt;p&gt;这里不准备把题目说的太细，就贴两张IDA逆向的结果图。简单描述一下题目的要求。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_11_07_18_29/1.png&quot; alt=&quot;rootkiter&quot; /&gt;
&lt;img src=&quot;/images/2015_11_07_18_29/2.png&quot; alt=&quot;rootkiter&quot; /&gt;&lt;/p&gt;

&lt;p&gt;从这两张图可以提取出以下几个关键条件。&lt;/p&gt;
&lt;blockquote&gt;
  &lt;ol&gt;
    &lt;li&gt;用户输入的内容要在内存中进行一次异或解码;&lt;/li&gt;
    &lt;li&gt;解码后的内容必须为可视字符串，即只能为大小写字母，数字以及少部分标点字符，其他ascii中的无法显示的字符不能存在于ShellCode中;&lt;/li&gt;
    &lt;li&gt;当解码后的字符有“Bigtang”锚点子串时，则将解码的字符串当作代码进行执行;&lt;/li&gt;
    &lt;li&gt;在 图2 中可以看出，当解密数据被执行时，eax正好指向ShellCode基地址。&lt;/li&gt;
  &lt;/ol&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;纯字符shellcode&quot;&gt;纯字符ShellCode&lt;/h2&gt;
&lt;p&gt;从题目描述可以得知，实际上这个题目的考点并不是软件类漏洞的利用，反而是对shellcode有一些极端的要求限制，当你通过了这些限制之后，自然就得到了执行条件。在这些限制条件中最难达到的其实就是纯字符的ShellCode了。&lt;/p&gt;

&lt;p&gt;对于纯可视字符类ShellCode的探索，网上也有过非常多的文章，国内比较好的文章有这样几篇：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;http://bbs.pediy.com/showthread.php?t=113177&quot;&gt;«纯字母shellcode揭秘»&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://blog.csdn.net/instruder/article/details/6050048&quot;&gt;«纯字符数字的shllcode及Alpha2.c使用»&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://blog.csdn.net/v_ling_v/article/details/42824007&quot;&gt;«纯ascii的shellcode编写»&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;以上三篇都是国内安全圈人对可视化ShellCode的经典论述。然而最吸引我的却是一篇却是圈外人的博文。
&lt;a href=&quot;http://demon.tw/programming/ascii-assembly.html&quot;&gt;« ASCII Assembly技术简介»&lt;/a&gt;  这足以说明：对“可视化字符ShellCode”的探索是部分极客的一种追求。&lt;/p&gt;

&lt;p&gt;在这些文章中也多次出现了一个域名 http://skypher.com/ ，在我写这篇博文时，该链接中是一片空白，只留得无尽遐想。想必他就是这种极客技术的领路人吧，不知他最近还好嘛。&lt;/p&gt;

&lt;h2 id=&quot;shellcode编码变形&quot;&gt;ShellCode编码变形&lt;/h2&gt;
&lt;blockquote&gt;
  &lt;p&gt;悄悄的skypher走了，
正如他轻轻的来，
他挥一挥衣袖，
不带走一片云彩。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;在他没带走的云彩中，有这样一个工具托管
&lt;a href=&quot;https://code.google.com/p/alpha3/&quot;&gt;https://code.google.com/p/alpha3/&lt;/a&gt;
是一个可以对ShellCode进行字符编码的工具，该工具由python编写，不过我在Linux下竟然没运行起来，只在Windows下运行成功。&lt;/p&gt;

&lt;p&gt;在做这道题时我用到了一个执行/bin/sh的ShellCode，来源地址：
&lt;a href=&quot;http://shell-storm.org/shellcode/files/shellcode-752.php&quot;&gt;http://shell-storm.org/shellcode/files/shellcode-752.php&lt;/a&gt;,这个网站中有非常多种ShellCode适用各种姿势。不过该部分内容已经停止更新了，原因在于现代漏洞利用技术已经很少再集中精力写shellcode，而是更注意ROP的开发以及编写了。&lt;/p&gt;

&lt;p&gt;使用 ALPHA3 工具之前，需要将 ShellCode 以二进制形式写到一个文件中，效果如下所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_11_07_18_29/3.png&quot; alt=&quot;rootkiter&quot; /&gt;&lt;/p&gt;

&lt;p&gt;然后就可以使用如下指令进行 ShellCode 编码了，我编码的目标为“X86 平台下、大写字符”，ShellCode开始执行那一刻，EAX寄存器保存了ShellCode的基地址。
所以指令如下所示：&lt;/p&gt;

&lt;cmd&gt;
	python ALPHA3.py x86 ascii uppercase EAX --input=&quot;shellcode&quot;
&lt;/cmd&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_11_07_18_29/4.png&quot; alt=&quot;rootkiter&quot; /&gt;&lt;/p&gt;

&lt;p&gt;得到的结果如下：&lt;br /&gt;
&lt;code&gt;
PYVTX10X41PZ41H4A4I1TA71TADVTZ32PZNBFZDQC02DQD0D13DJE1D485C3E1YKM6L7L0  
60Y011T2OKO2B5NJO90MM9M3I00
&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&quot;字符型-shellcode-样例&quot;&gt;字符型 ShellCode 样例&lt;/h2&gt;
&lt;p&gt;这里有两段从他人博客找到的 ShellCode 样例：&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/files/shellcode.txt&quot;&gt;/files/shellcode.txt&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;结个尾&quot;&gt;结个尾&lt;/h2&gt;
&lt;p&gt;事实上对 ShellCode 的探索一直就没有停止过， ShellCode 免杀，字符型 ShellCode，JIT下ShellCode，DVE中的虚拟执行层 ShellCode，正如« ASCII Assembly技术简介»中所说的：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;没有什么神秘可言&lt;br /&gt;
可执行程序是二进制文件&lt;br /&gt;
文本文件也是二进制文件&lt;br /&gt;
它们本质上没有什么区别&lt;br /&gt;
in.com 程序的特殊性在于 &lt;br /&gt;
所有的代码全部分布于ASCII码表的可显示字符范围中&lt;br /&gt;
当然这样的程序不是碰巧得到的&lt;br /&gt;
而是人为的构造出来的&lt;br /&gt;
其中需要用到许多技巧&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;再附上一篇关于Unicode的ShellCode编写的文章，作为结尾。&lt;br /&gt;
&lt;a href=&quot;http://huaidan.org/archives/1214.html&quot;&gt;«编写Unicode有效的Shellcode»&lt;/a&gt;&lt;/p&gt;
</content>
</entry>

<entry>
	<title>哥们儿今儿受伤了</title>
        <link href="/2015/10/29/%E5%93%A5%E4%BB%AC%E5%84%BF%E4%BB%8A%E5%84%BF%E5%8F%97%E4%BC%A4%E4%BA%86.html"/>
	<updated>2015-10-29T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/10/29/哥们儿今儿受伤了</id>
	<content type="html">&lt;h2 id=&quot;路飞镇楼&quot;&gt;路飞镇楼&lt;/h2&gt;
&lt;p&gt;哥们儿今儿受伤了，内伤。万点魔法伤害，华丽丽的砸在心头。&lt;/p&gt;

&lt;p&gt;先借用路飞的霸气镇个贴，以免心碎和屏幕发生共振，“卒瓦”了我的电脑就不美丽了。&lt;br /&gt;
顺带还能给我补充点正能量。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_29_22_21/1.png&quot; alt=&quot;rootkiter&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;伤&quot;&gt;伤&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_29_22_21/2.png&quot; alt=&quot;rootkiter&quot; /&gt;&lt;/p&gt;

&lt;p&gt;在这地球上，人确实是一种奇怪的生物，有着丰富的情感，所以极容易受伤。&lt;/p&gt;

&lt;p&gt;追不到女神会受伤，工资不高会受伤，甚至忘记上厕所都会憋出内伤。&lt;/p&gt;

&lt;p&gt;想在这样的世界上存活，有两条路可走：&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;1.内心强大，纵使泰山压境，我自岿然不动。&lt;br /&gt;
2.独居深山，不闻尘缘之事。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;然而时代在发展，世界在进步。社会的分工越来越细，一旦你脱离了这个社会，真就活不下去。还别不信邪，不会耕地，不会打猎，给你一株草，你都不知道能不能吃。于是乎，在这样动乱的年代，只能刻苦修炼内心。&lt;/p&gt;

&lt;h3 id=&quot;脆&quot;&gt;脆&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_29_22_21/3.png&quot; alt=&quot;rootkiter&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这个字常见有三层含义：&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;1.（脆弱）易碎；&lt;br /&gt;
2.（干脆）干净利落，不托泥带水；&lt;br /&gt;
3.（脆亮）声音清爽；&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;不但把行为／状态描述出来，而且连声音都带出来了。可以说是“妙不可言”，真是造字史上的丰碑。&lt;/p&gt;

&lt;p&gt;更不可思议的是：它竟然还掺有一丝思辨的味道，“有一定硬度，强度又不够格”。它描述了一种最容易受伤的状态，那就是“人在最自信的时候其实是最脆弱的”。&lt;/p&gt;

&lt;p&gt;是呀，这真是一种有趣的逻辑，“自信”和“脆弱”竟然是正比例关系。用数学描述大概是这个样子滴：&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;脆弱 = a * 自信 （其中，a ∈｛0，＋∞｝）&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;压&quot;&gt;压&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_29_22_21/4.png&quot; alt=&quot;rootkiter&quot; /&gt;&lt;/p&gt;

&lt;p&gt;奇特的力学词汇。它描述了一种不对等的状态，强势的一方很自然的会向弱势一方持续性用力。上对下，大对小，外对内。这些常见的强弱关系都会存在自然的压力，习惯了也就不怪了。&lt;/p&gt;

&lt;p&gt;然而有一种奇妙的场景，对双方都会有些许陌生－－面试。一方索求，一方给予，天然的不平等，让面试官可以俯察一切。一般情况下，遇到应聘者，面试官只需碾压过去既可，遇到极个别强力的应聘者，也只是刚好保证双方对等而已。互不受伤，倒也其乐融融。&lt;/p&gt;

&lt;h3 id=&quot;反&quot;&gt;反&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_29_22_21/5.png&quot; alt=&quot;rootkiter&quot; /&gt;&lt;/p&gt;

&lt;p&gt;极具戏剧性色彩的词汇，任何事物，只要有了这一特性，定会让人回味无穷。美剧强调“反面人物”，赛车强调“反超”，Dota强调“反杀” and so on…&lt;/p&gt;

&lt;p&gt;当一天即将结束，满心欢喜的准备收割最后一颗胜利果实时，突然发现最后一个竟然极其反常，比你年龄小，比你眼缘好，原以为厚厚的简历中尽是臭皮囊，事实却字字真金。更让人伤感的是，那一刻，他在你自以为优势的领域完全战胜了你。短短的20分钟之内，让你体验了一种来自心灵的过山车。&lt;/p&gt;

&lt;h3 id=&quot;复&quot;&gt;复&lt;/h3&gt;
&lt;p&gt;循环往复，千锤百炼才能锻出好钢，受过的伤也必将恢复。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_29_22_21/6.png&quot; alt=&quot;rootkiter&quot; /&gt;&lt;/p&gt;

&lt;p&gt;“复”本是周易的第二十四卦，下震上坤，可以理解为“雷埋于地下”，是一种不够稳定的卦象。“不稳定”代表着“变化”，“变化”一般寓意着吉利。六一到六五均无碍，仅有上六为凶，这表明，只要不是最坏情况都没什么关系。&lt;/p&gt;

&lt;p&gt;所以，到了这里，我也就痊愈了。&lt;/p&gt;

&lt;h2 id=&quot;路飞结尾&quot;&gt;路飞结尾&lt;/h2&gt;
&lt;p&gt;虽然没有路飞那样远大的理想，也不曾有过梦想。&lt;/p&gt;

&lt;p&gt;不过我仍然坚信，明天的那个我一定比今天这个我知道的更多，也懂得更多。&lt;/p&gt;

&lt;p&gt;旁人只是人生路上的标示牌，唯有比昨天的自己有进步，才不会白活了今天这一天。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_29_22_21/7.png&quot; alt=&quot;rootkiter&quot; /&gt;&lt;/p&gt;
</content>
</entry>

<entry>
	<title>《冰雪暴》第一季的东西</title>
        <link href="/2015/10/17/%E5%86%B0%E9%9B%AA%E6%9A%B4-%E7%AC%AC%E4%B8%80%E5%AD%A3%E7%9A%84%E4%B8%9C%E8%A5%BF.html"/>
	<updated>2015-10-17T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/10/17/《冰雪暴》第一季的东西</id>
	<content type="html">&lt;h2 id=&quot;前言&quot;&gt;前言&lt;/h2&gt;
&lt;p&gt;当年科恩兄弟以一部同名电影斩获“ 奥斯卡－最佳改编剧本奖”，如今，这部同名美剧也开始了第二季的更新。为了纪念这历史性的一刻，我决定在这里写一些第一季的东西。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_17_20_39/1.jpg&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;剧集内容&quot;&gt;剧集内容&lt;/h2&gt;
&lt;p&gt;第一季共10集，在剧慌时也算是刷了无数遍，但每一遍都像看第一遍一样的过瘾。相比其他美剧来说，《冰雪暴》更像一个实验，一个在偏僻小镇进行的人性实验。&lt;/p&gt;

&lt;h3 id=&quot;实验目的&quot;&gt;实验目的&lt;/h3&gt;

&lt;p&gt;一个杀手会对世界造成什么样的影响。&lt;br /&gt;
生物是多样性的，不同的人都会共存在相同的社会中，那么一个杀手究竟会对社会造成什么影响呢，谁也不会知道，为了得到问题答案，需要一个实验来获得。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_17_20_39/2.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;实验方法&quot;&gt;实验方法：&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;控制变量法&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;这是一个放之四海皆有效的实验方法，为了考量杀手的影响，镇子要足够宁静，镇中每个人要各司其职，各自生活。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_17_20_39/3.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;实验环境&quot;&gt;实验环境&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;下雪，一直的下雪，不停的下雪&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;雪是白的，厚厚一层覆盖在小镇的每一个角落，任何脏的东西从上面划过都会留下痕迹;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_17_20_39/4.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;同时它又是一个完美的隔离层，把小镇原本不光彩的事情统统掩盖起来，昔日的校园恶霸山姆·赫斯，现在已经是一个镇内光鲜亮丽的小老板了。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_17_20_39/5.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;拥有黑暗面的人（莱斯特弟弟），都混的人模狗样；而软弱无助的正派君子（莱斯特），却只能过着窘迫的生活。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_17_20_39/6.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_17_20_39/61.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;实验地点&quot;&gt;实验地点&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;宁静的小镇&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;小镇有警署，是一个职能部门，但终日却无事可做，杀手到来前，最常做的事情就是“扫雪”。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_17_20_39/7.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;唯一见过世面的是警长，不过杀手出现后很快领了盒饭。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_17_20_39/8.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;安逸的生活，让新上任的警长晕血，手下警员的上次射击，还是在警校的日子。枪本来是用来打敌人的，结果却误伤了自己人。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_17_20_39/9.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;杀手来到这个镇子，就好像“狼到了羊圈”，只有这样的环境才能得到最真实的实验结果。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_17_20_39/10.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;杀手性格&quot;&gt;杀手性格&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;冷血&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;杀手在执行杀人任务过程中开车路过小镇，却被一只鹿挡住去路，&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_17_20_39/11.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;失控的车子飞了起来。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_17_20_39/12.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;后备箱有个裸体男子，逃脱后向树林深处跑去，要说这天气真是冷透了，杀手都不用费心去追，他自己就被冻死在一棵树下，死时只剩一条内裤。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_17_20_39/13.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;爱戏弄人&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;住旅馆时，会先怂恿临时工向老板的汽车油箱中撒尿。然后再电话通知老板。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_17_20_39/14.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;不慎被抓后，能马上变身神父，蒙混过关。小警员看着他的一脸坏笑，却无可奈何。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_10_17_20_39/15.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;实验结果&quot;&gt;实验结果&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;杀死一个人的酬劳只需一听可乐。&lt;br /&gt;
&lt;img src=&quot;/images/2015_10_17_20_39/16.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;软弱之人尝到暴力带来的甜头后，会迅速成长，成为杀妻恶魔。&lt;br /&gt;
&lt;img src=&quot;/images/2015_10_17_20_39/17.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;按部就班的软弱会让生活变的窘迫，突破底线的觉醒却会让人变的自信，进而改变生活。
&lt;img src=&quot;/images/2015_10_17_20_39/18.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;暴发户最终会演化为自大，去挑战不该挑战的人，结果还是家破人亡，妻离子散。&lt;br /&gt;
&lt;img src=&quot;/images/2015_10_17_20_39/19.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;雪白的大地让杀手也无处遁形，杀手最终死于非命。&lt;br /&gt;
&lt;img src=&quot;/images/2015_10_17_20_39/20.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;白雪仍然在下，不久之后，小镇恢复了宁静，没人还会记得雪下究竟发生过什么。俗语称之为：“好了伤疤忘了疼”。&lt;br /&gt;
&lt;img src=&quot;/images/2015_10_17_20_39/21.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
</entry>

<entry>
	<title>OpenSSL中的其他内容（五）</title>
        <link href="/2015/09/16/OpenSSL%E4%B8%AD%E7%9A%84%E5%85%B6%E4%BB%96%E5%86%85%E5%AE%B9.html"/>
	<updated>2015-09-16T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/09/16/OpenSSL中的其他内容</id>
	<content type="html">&lt;h2 id=&quot;前言&quot;&gt;前言&lt;/h2&gt;
&lt;p&gt;最近在读OpenSSL的命令参数，在这个学习过程中发现OpenSSL之中，架构了一个非常庞大的理论系统，结果原以为学习一两天就能学完的基础知识，却学了将近一个月，才学到一些皮毛。&lt;/p&gt;

&lt;p&gt;之前整理了一些学习笔记，这篇将涉及一些OpenSSL中乱七八糟的一些知识。&lt;/p&gt;

&lt;h2 id=&quot;常见的信息摘要算法&quot;&gt;常见的信息摘要算法&lt;/h2&gt;

&lt;p&gt;在OpenSSL中提供的信息摘要算法有很多，有SHA1、SHA、MD5、DSS和RIPEMD160这样几种。这些指令既可以通过单独的同名指令进行使用，也可以在dgst指令中用参数指定方式使用。&lt;/p&gt;

&lt;p&gt;摘要算法是对一段数据进行特征提取的方法，理论上讲，一个摘要算法的输出长度一般是固定的，当输入的数据发生很小的改变时，输出的摘要结果变化应该很明显。同时从摘要算法的结果要很难反推出原数据。&lt;/p&gt;

&lt;p&gt;数字签名则是采用非对称加密的方法，对一段数据进行私钥加密，数据验签时，首先用公钥解密出数据再和被验签数据进行比对，如果相同，则验签成功，否则验签失败。摘要算法和数字签名结合在一起可以解决大量数据的验签问题，即对摘要算法的结果进行验签，以保证原数据的合法性。&lt;/p&gt;

&lt;p&gt;下面分别针对不同的摘要算法提几个使用实例：&lt;/p&gt;

&lt;h3 id=&quot;md5&quot;&gt;MD5&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;rootkiter@PC:~$ echo “Hello World” &amp;gt; bedgst.txt&lt;br /&gt;
rootkiter@PC:~$ openssl md5 -c -hex bedgst.txt &lt;br /&gt;
MD5(bedgst.txt)= e5:9f:f9:79:41:04:4f:85:df:52:97:e1:c3:02:d2:60&lt;br /&gt;
rootkiter@PC:~$ openssl dgst -md5 -c -hex bedgst.txt &lt;br /&gt;
MD5(bedgst.txt)= e5:9f:f9:79:41:04:4f:85:df:52:97:e1:c3:02:d2:60&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_09_19_01_46/1.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;sha1&quot;&gt;SHA1&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;rootkiter@PC:~$ echo “Hello World” &amp;gt; bedgst.txt&lt;br /&gt;
rootkiter@PC:~$ openssl sha1 -c -hex bedgst.txt &lt;br /&gt;
SHA1(bedgst.txt)= 64:8a:6a:6f:ff:fd:aa:0b:ad:b2:3b:8b:af:90:b6:16:8d:d1:6b:3a&lt;br /&gt;
rootkiter@PC:~$ openssl dgst -sha1 -c -hex bedgst.txt &lt;br /&gt;
SHA1(bedgst.txt)= 64:8a:6a:6f:ff:fd:aa:0b:ad:b2:3b:8b:af:90:b6:16:8d:d1:6b:3a&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_09_19_01_46/2.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;dss1&quot;&gt;DSS1&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;rootkiter@PC:~$ echo “Hello World” &amp;gt; bedgst.txt&lt;br /&gt;
rootkiter@PC:~$ openssl dss1 -c -hex bedgst.txt &lt;br /&gt;
DSA(bedgst.txt)= 64:8a:6a:6f:ff:fd:aa:0b:ad:b2:3b:8b:af:90:b6:16:8d:d1:6b:3a&lt;br /&gt;
rootkiter@PC:~$ openssl dgst -dss1 -c -hex bedgst.txt &lt;br /&gt;
DSA(bedgst.txt)= 64:8a:6a:6f:ff:fd:aa:0b:ad:b2:3b:8b:af:90:b6:16:8d:d1:6b:3a&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_09_19_01_46/3.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;openssl指令整体结构&quot;&gt;OpenSSL指令整体结构&lt;/h2&gt;

&lt;p&gt;OpenSSL提供了非常庞大的算法库，然而又很少有资料介绍OpenSSL每条指令功能，和所属体系，导致初次接触无从下手，这里就把所有的指令进行一个基本分类，以帮助使用OpenSSL时，快速找到对应的指令，找到之后就可以通过-h参数依次确定指令的参数内容了。&lt;/p&gt;

&lt;h3 id=&quot;对称算法加解密相关&quot;&gt;对称算法加解密相关&lt;/h3&gt;

&lt;p&gt;更多详细内容，可参阅《OPENSSL 与网络信息安全-基础、结构和指令》的第128页。&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;指令&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;功能介绍&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;enc&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;对称加密算法的统一入口指令，可通过进一步配置参数选择加密算法，如 -des&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;aes*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;使用aes算法对文件进行加解密操作，-e参数为加密，-d参数为解密&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;bf*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;bf算法对文件进行加解密操作，-e参数为加密， -d参数为解密&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;camellia*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;使用camellia算法对文件进行加解密操作， -e参数为加密，-d参数为解密&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;cast*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;使用cast算法对文件进行加解密操作， -e参数为加密，-d参数为解密&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;des*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;使用des算法对文件进行加解密操作， -e参数为加密，-d参数为解密&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;des-ede-*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;使用3des算法对文件进行加解密操作， -e参数为加密，-d参数为解密，需要注意的是ede算法的输入中k1 和 k3 相同。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;des-ede3-*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;使用3des算法对文件进行加解密操作， -e参数为加密，-d参数为解密，需要注意的是ede3相关算法的输入中有三个不同的密码。所以强度会高于des-ede-*&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;des3&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;使用des3算法对文件进行加解密操作， -e参数为加密，-d参数为解密，从字面理解应该是3次的des加密。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;rc2*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;使用rc算法对文件进行加解密操作， -e参数为加密，-d参数为解密&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;seed*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;使用seed算法对文件进行加解密操作， -e参数为加密，-d参数为解密&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;base64&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;使用base64对文件进行转码，-e参数为编码，-d参数为解码，但该算法不是对称加密算法，而是编码指令。&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;信息摘要算法&quot;&gt;信息摘要算法&lt;/h3&gt;

&lt;p&gt;更多详细内容，可参阅《OPENSSL 与网络信息安全-基础、结构和指令》的第164页。&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;指令&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;功能介绍&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;dgst&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;信息摘要算法指令的统一入口，可通过参数进一步指定被选择的摘要算法，如 -md5 。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;md4&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;使用md4摘要算法对文件进行摘要计算。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;md5&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;使用md5摘要算法对文件进行摘要计算。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;rmd160&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;使用rmd160摘要算法对文件进行摘要计算。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;sha&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;使用sha摘要算法对文件进行摘要计算。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;sha1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;使用sha1摘要算法对文件进行摘要计算。&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;非对称算法相关指令&quot;&gt;非对称算法相关指令&lt;/h3&gt;

&lt;p&gt;更多详细内容，可参阅《OPENSSL 与网络信息安全-基础、结构和指令》的第136页。&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;算法名称&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;指令&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;功能介绍&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;DSA&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;dsaparam&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;用于生成dsa密钥参数的指令。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;gendsa&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;用于生成dsa密钥对的指令。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;dsa&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;dsa密钥文件维护的指令，一般包括（加密存储、更换保护密码、更换加密算法、编码转换、阅读内容等操作）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;RSA&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;genrsa&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;用于生成dsa密钥的指令&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;rsa&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;rsa密钥文件维护的指令，一般包括（加密存储、更换保护密码、更换加密算法、编码转换、阅读内容等操作）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;rsautl&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;使用rsa密钥对文件进行加解密操作。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;DH&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;gendh&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;生成dh密钥&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;dh&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;对dh密钥文件格式进行编辑的指令，一般包括（编码转换、阅读内容、检查安全性、输出C格式代码等操作）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;dhparam&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;dh算法的入口指令，包含dh和gendh的所有功能。&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;证书操作相关指令&quot;&gt;证书操作相关指令&lt;/h2&gt;

&lt;p&gt;更多详细内容，可参阅《OPENSSL 与网络信息安全-基础、结构和指令》的第167页。&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;所属证书操作过程&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;操作指令&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;功能介绍&lt;/th&gt;
      &lt;th&gt; &lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;生成证书请求&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;req&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;生成证书请求指令，同时可以查看证书文件内容。&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;CA 机构的操作&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ca&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;CA机构的维护指令，包括证书签发，证书吊销，生成新吊销列表，为其他CA签发证书等操作。&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-revoke&lt;/td&gt;
      &lt;td&gt;吊销证书&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-gencrl&lt;/td&gt;
      &lt;td&gt;生成新的吊销列表&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;证书验证过程&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;x509&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;证书格式维护指令（证书内容查看，编码格式转换，根据已有证书生成新的证书请求等）&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;crl&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;crl文件维护指令（crl文件内容查看，编码格式转换等操作）&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;verify&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;根据已有的CA证书，校验当前证书是否合法。&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;*&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ocsp&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;创建一个在线的证书状态查询服务，或在已有的证书查询服务上查询一个证书状态。&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;文件格式转化指令&quot;&gt;文件格式转化指令&lt;/h3&gt;

&lt;p&gt;通常情况的文件编码都可以使用分类中的指令进行转化（比如X509、rsa、dsa指令等），然而总有些证书使用场景（软件版本太老，只能识别个别的证书文件）是无法直接转化的，于是OpenSSL提供了更多的转化指令以适应不同的场景。&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;操作指令&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;功能介绍&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;crl2pkcs7&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;可将多个证书以及crl文件封装在相同的PKCS#7标准的文件中（当不想封装crl文件时，可通过 -nocrl 选项指定）。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;pkcs7&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;证书编码转换（PEM-&amp;gt;DER），输出文件中个整数内容&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;证书编码转换（PEM-&amp;gt;DER），输出文件中个整数内容&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;对私钥的格式进行转化：1.生产一种非标准格式的RSA私钥，以兼容一些软件；2.生产一种非标准格式的DSA密钥，此时的DSA参数会内嵌至PrivateKey结构中。3.生产一种兼容Netscape私钥数据库格式的DSA密钥。4.将已有密钥转化为pkcs8文件格式的密钥，同时可选择加密保存方式。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;pkcs12&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;将多个证书及crl文件封装为一个PKCS#12标准的文件中，并支持对PKCS#12文件内容的查询和编辑，可针对其中封装的某一证书进行针对性操作（更换加密算法、更换密码等）&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;更多详细内容，可参阅《OPENSSL 与网络信息安全-基础、结构和指令》的第230/213/217页。&lt;/p&gt;

&lt;h3 id=&quot;其他指令&quot;&gt;其他指令&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;指令&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;指令功能&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;备注&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;asn1parse&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;是一种用来诊断ASN.1结构的工具，也能用于从ASN1.1数据中提取数据。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;http://blog.csdn.net/as3luyuan123/article/details/13339803&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ciphers&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;可用于查看OpenSSL支持的ciphers，或指定一个ssl的算法版本。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;$ openssl ciphers -v&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;cms&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;该命令处理S/MIME v3.1邮件。可以用它对S/MIME消息进行加密、解密、签名、验证签名、压缩以及解压缩等操作。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;http://blog.csdn.net/as3luyuan123/article/details/13612917&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ec&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;椭圆曲线密钥处理工具。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;http://blog.csdn.net/as3luyuan123/article/details/14138983&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ecparam&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;椭圆曲线密钥参数生成及操作。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;http://blog.csdn.net/as3luyuan123/article/details/14406429&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;engine&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;查询OpenSSL支持的engine设备列表。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;帮助指令：&lt;br /&gt;$ openssl engine -h&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;errstr&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;本命令用于查询错误代码。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;http://blog.csdn.net/as3luyuan123/article/details/14413745&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;genpkey&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;用于产生各种密钥（RSA、DSA、DH、EC等）的私钥值。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;http://blog.csdn.net/as3luyuan123/article/details/14498339&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;nseq&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;本命令用于多个证书与netscape证书序列间相互转化。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;http://blog.csdn.net/as3luyuan123/article/details/14901077&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;passwd&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;passwd命令计算一个密钥的哈希值或者计算列表中的每个密钥的hash值。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;http://blog.csdn.net/as3luyuan123/article/details/14917959&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;pkey&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt; &lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;pkeyparam&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;公共密钥算法参数处理工具。它能够处理公钥或私钥文件。它能够转换组件信息并将它们打印出来。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;http://blog.csdn.net/as3luyuan123/article/details/16330979&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;pkeyutl&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;本命令能够测试所支持的密钥算法的性能。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;http://blog.csdn.net/as3luyuan123/article/details/16331003&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;prime&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;产生并检查一个数是否为素数。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;http://blog.csdn.net/as3luyuan123/article/details/16331073&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;rand&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;用来产生伪随机字节。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;http://blog.csdn.net/as3luyuan123/article/details/16811693&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;s_client&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;s_client为一个SSL/TLS客户端程序，与s_server对应，它不仅能与s_server进行通信，也能与任何使用ssl协议的其他服务程序进行通信。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;http://blog.csdn.net/as3luyuan123/article/details/16812071&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;s_server&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;s_server是openssl提供的一个SSL服务程序。使用此程序前，需要生成各种证书。本命令可以用来测试ssl客户端，比如各种浏览器的https协议支持。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;http://blog.csdn.net/as3luyuan123/article/details/16850727&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;s_time&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;s_time是openss提供的SSL/TLS性能测试工具，用于测试SSL/TSL服务。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;http://blog.csdn.net/as3luyuan123/article/details/16850825&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;sess_id&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;本指令是处理SSL_SESSION结构的，可以打印出其中的细节。这也是一个调试工具。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;http://blog.csdn.net/as3luyuan123/article/details/16850893&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;smime&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;S/MIME工具，用于处理S/MIME邮件，它能加密、解密、签名和验证S/MIME消息。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;http://blog.csdn.net/as3luyuan123/article/details/16850953&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;speed&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;speed命令用于测试库的性能。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;http://blog.csdn.net/as3luyuan123/article/details/16851125&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;spkac&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;SPKAC打印和产生工具。它能够处理Netscape格式的签名公钥。它可以打印它们的上下文，验证签名值和根据提供的私钥产生自己的SPKACs。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;http://blog.csdn.net/as3luyuan123/article/details/16851173&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;srp&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Xxxxx 这个指令我一顿乱翻也不知道是干什么用的。。。貌似是个叫TLS-SRP的算法可惜呀。没看到指令样例和文档。&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ts&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;时间戳处理工具&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;http://blog.csdn.net/as3luyuan123/article/details/16867849&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;
&lt;p&gt;这篇学习笔记记录了OpenSSL中的信息摘要算法和OpenSSL工具的指令整体脚骨，以及背景知识。&lt;/p&gt;

&lt;p&gt;在第三章节大量引用VitalityShow的博客内容，是因为google结果只有他配有中文解释。感谢他的无私奉献吧。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>OpenSSL中的对称算法（四）</title>
        <link href="/2015/09/12/OpenSSL%E4%B8%AD%E7%9A%84%E5%AF%B9%E7%A7%B0%E7%AE%97%E6%B3%95.html"/>
	<updated>2015-09-12T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/09/12/OpenSSL中的对称算法</id>
	<content type="html">&lt;h2 id=&quot;前言&quot;&gt;前言&lt;/h2&gt;
&lt;p&gt;最近在读OpenSSL的命令参数，在这个学习过程中发现OpenSSL之中，架构了一个非常庞大的理论系统，结果原以为学习一两天就能学完的基础知识，却学了将近一个月，才学到一些皮毛。&lt;/p&gt;

&lt;p&gt;之前整理了一些OpenSSL相关的学习笔记，这篇将涉及一些OpenSSL中对称算法的一些知识。&lt;/p&gt;

&lt;h2 id=&quot;常见的对称算法&quot;&gt;常见的对称算法&lt;/h2&gt;

&lt;p&gt;在OpenSSL中提供了多种对称算法（其中多数都为分组加密算法），以供用户使用，常用的对称算法有以下几种：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;AES算法：在OpenSSL中提供了AES的多种位数支持，常见的有128位，192位，256位。&lt;/li&gt;
  &lt;li&gt;Blowfish算法：OpenSSL提供了bf指令，以支持Blowfish算法的各种加解密操作。&lt;/li&gt;
  &lt;li&gt;CAST5算法：OpenSSL提供了cast指令，以支持CAST5算法的各种加解密操作。&lt;/li&gt;
  &lt;li&gt;DES算法：OpenSSL提供了des指令，以支持DES算法的各种加解密操作。&lt;/li&gt;
  &lt;li&gt;IDEA算法：IDEA是一种国际数据加密算法，由DES算法演化而来，目的是为解决DES算法密&lt;/li&gt;
  &lt;li&gt;钥太短的缺点，其算法密钥为128位长度。&lt;/li&gt;
  &lt;li&gt;RC2算法：也是一种分组加密算法，可作为DES算法的替代算法，输入输出均为64位。&lt;/li&gt;
  &lt;li&gt;RC4算法：这是一种老旧的验证和加密算法，易于受到黑客攻击。&lt;/li&gt;
  &lt;li&gt;RC5算法：这是一种相对较新的算法。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;常用分组加密模式&quot;&gt;常用分组加密模式&lt;/h2&gt;
&lt;p&gt;由于分组加密算法的输入输出均有位数限制，导致无法加密较大的数据，所以日常使用中，会将被加密文件按照算法特性进行分组，每组加密后再拼接在一起形成最终密文。按照分组后的处理方式，将分组算法进行了模式分类，在OpenSSL中有4种常见的分组加密模式，复用于分组加密算法中。以本节介绍中，所有示意图均选自《密码学》，这些图实在太难画了，就用手机照下来的，看不清也凑合看把。。。&lt;/p&gt;

&lt;h3 id=&quot;ecb&quot;&gt;ECB&lt;/h3&gt;
&lt;p&gt;电子密码本模式（Electronic Codebook Mode）。将被加密数据分段，最后一段不足时按照预定模式（补0或补F）补足。将每一段进行加密，加密后的各个段之间互不影响，将各段按顺序连在一起就是加密结果。每一段参与计算的只有”密钥K”，示意图如下所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_09_12_00_23/1.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;cbc&quot;&gt;CBC&lt;/h3&gt;
&lt;p&gt;密文块链接模式（Cipher Block Chaining Mode）。将被加密数据分段，每一段数据先与前一段数据加密后的密文进行按位模加（XOR：异或），如果当前段为首段数据（即不存在前一段数据）则与初始化向量（iv）进行模加。模加结果同”密钥K”共同进行加密计算得到当前段的密文。每一段参与计算的都有”密钥K”以及”前一段密文/初始化向量”。示意图如下所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_09_12_00_23/2.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;cfb&quot;&gt;CFB&lt;/h3&gt;
&lt;p&gt;密文反馈模式（Cipher Feedback Mode）。将被加密数据分块（r比特一块），将每一块的加密结果作为下一块的初始化向量IV，将该向量先同 密钥K 做加密计算，计算结果同与下一块的明文进行按位模加（XOR：异或），从而得到当前块的加密结果。下图是一张示意图：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_09_12_00_23/3.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;ofb&quot;&gt;OFB&lt;/h3&gt;
&lt;p&gt;输出反馈模式（Output Feedback Mode）。将被加密数据分块（r比特一块），每一块明文只同向量表的左侧r位进行按位模加（XOR：异或）得到密文。每一块密文不对后续计算造成影响，“密钥K”仅对向量表变形发生作用。这也是OFB模式 相对 CFB模式的区别。下图是一张示意图：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_09_12_00_23/4.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;ede&quot;&gt;EDE&lt;/h3&gt;
&lt;p&gt;三重分组加密模式（Encrypt-Decrypt-Encrypt）。将一段数据通过 “加密-解密-加密” 进而生成密文。且这种模式所需密钥可以不止一个（二个不同密钥或三个不同密钥），以提高加密强度。常见的两种加密公式如下:
其中,E( k,P ) 代表: 用密钥 k 对 P 进行加密操作。D( k,C ) 代表: 用密钥 k 对 C 进行解密操作。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;二密钥加解密公式如下—-可以看到 1/3 密钥是相同的：&lt;/p&gt;

  &lt;blockquote&gt;
    &lt;p&gt;C = E( k1,D( k2,E( k1,P )))&lt;br /&gt;
P = D( k1,E( k2,D( k1,C )))&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;三密钥加解密公式如下—-可以看到3个密钥 各不相同：&lt;/p&gt;

  &lt;blockquote&gt;
    &lt;p&gt;C = E( k3,D( k2,E( k1,P ))) &lt;br /&gt;
P = D( k1,E( k2,D( k3,C )))&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;参数指令体系对称算法相关&quot;&gt;参数指令体系（对称算法相关）&lt;/h2&gt;
&lt;p&gt;OpenSSL支持8种对称加密算法，将这8中对称加密算法同5种加密模式进行糅合，最终形成了OpenSSL中强大的对称加密算法被选选项，下面在命令行下，看一下enc这条指令下支持多少种加密方法，如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_09_12_00_23/5.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;从des加密开始&quot;&gt;从DES加密开始&lt;/h3&gt;

&lt;p&gt;在OpenSSL中，所有的对称加密指令的格式均是想通的，掌握其中一种即可掌握其他种类的对称加密算法指令，下面先以DES指令作为入门指令，进行介绍。&lt;br /&gt;
首先新建一个文件名为beenc.txt 内容为Hello World：&lt;/p&gt;
&lt;cmd&gt;
rootkiter@PC:~$ echo &quot;Hello World&quot; &amp;gt; beenc.txt
&lt;/cmd&gt;

&lt;p&gt;随后用DES对该文件进行加密（密码为1234）：&lt;/p&gt;
&lt;cmd&gt;
rootkiter@PC:~$ openssl des -e -in beenc.txt -out bedec  -pass pass:1234 
&lt;/cmd&gt;

&lt;p&gt;加密后使用常用的文件查看指令进行查看可以得到密文的一些特征：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_09_12_00_23/6.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;从cat结果可以看出，加密后的文件，不是可视字符，且以Salted作为文件开头，这意味着密文是加盐的加密结果。而在我们执行的命令中，没有加盐参数，这也表明，加盐操作是默认的。
解密操作是加密的逆操作，在des指令中有另一个名为d的参数设置，由于加密时密码为1234，所以解密时密码同样为1234，指令格式如下所示：&lt;/p&gt;
&lt;cmd&gt;
$ openssl des -d -in bedec -out final.txt -pass pass:1234
&lt;/cmd&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_09_12_00_23/7.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;可以看到在解密指令中同样没有提到盐值，这证明盐值对于加解密操作是透明的。那么盐值在哪里呢，通过在指令中添加-p参数可以获得加密时的盐值结果：&lt;/p&gt;
&lt;cmd&gt;
$ openssl des -e -in beenc.txt -out bedec -pass pass:1234 -p
&lt;/cmd&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_09_12_00_23/8.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;从上图可以发现，盐值其实是保存在密文的8-16字节的。这也证明，盐值并不是一个需要保密的值。为什么会这样呢，这是盐值本身的特性决定的。盐值是一个随机数，他会对每次加密后的结果产生影响，导致相同密文下每两次加密产生的密文均不同，这可以在一定程度下对抗彩虹表的分析。&lt;/p&gt;

&lt;p&gt;在-p参数下，和盐值被共同输出的两个内容为 key 和 iv，这两个参数的功能又什么呢？&lt;/p&gt;

&lt;p&gt;在“分组加密模式”章节中可以发现，很多模式均有“初始化密钥”和“初始化向量”，这两个值与之是相对应的。当我们通过-pass 参数来输入密码时，OpenSSL会将“密码”和“系统随机数”进行一些操作，并从操作结果中提取出“盐值”、“初始化密钥”和“初始化向量”用于后续的加密。这样就让对称算法的密码输入变得简单起来了。&lt;/p&gt;

&lt;p&gt;事实上当我们不想主动输入密码时，也可以通过人为指定Key/iv/salt三个参数的值，实现加密，指令格式如下所示：&lt;/p&gt;
&lt;cmd&gt;
$ openssl [被选算法名] -e -in beenc.txt -out bedec -S 0x1234 -K AAAAAAAAAAAAAAAA -iv BBBBBBBBBBBBBBBB -p
&lt;/cmd&gt;

&lt;p&gt;不过需要注意的是，具体指定的参数是否生效还要看所选择的“分组加密模式”是否支持对应参数。比如初始向量在“电子密码本（ECB）”模式下就没有用到，此时虽然指定了-K和 -iv 的值，但是由于没有使用，同样不会有效果。&lt;/p&gt;

&lt;h3 id=&quot;指令格式讲解&quot;&gt;指令格式讲解&lt;/h3&gt;

&lt;h4 id=&quot;基本指令格式&quot;&gt;基本指令格式&lt;/h4&gt;

&lt;p&gt;在OpenSSL中提供两种交互模式，一种为脚本交互，一种为控制台交互。两种方式的执行效果完全相同只是交互方式略有区别，下面是两种交互模式的样例，它们是完全等价的：&lt;br /&gt;
&lt;em&gt;脚本交互&lt;/em&gt;&lt;/p&gt;
&lt;cmd&gt;
&amp;gt; $ openssl des -e -in beenc.txt -out bedec  -pass pass:1234
&lt;/cmd&gt;

&lt;p&gt;&lt;em&gt;控制台交互&lt;/em&gt;&lt;/p&gt;
&lt;cmd&gt;
&amp;gt; $ openssl  
&amp;gt; OpenSSL&amp;gt; des -e -in beenc.txt -out bedec -pass pass:1234
&lt;/cmd&gt;

&lt;p&gt;两者的唯一区别在于：脚本交互方式可以由shell脚本直接调用，而人工操作时，控制台交互模式可以在每一次指令测试时少输入一个openssl程序名。&lt;/p&gt;

&lt;h4 id=&quot;输入输出说明&quot;&gt;输入输出说明&lt;/h4&gt;

&lt;p&gt;OpenSSL的输入输出参数种类很多，下面分别介绍。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;直接由参数指定输入，比如-K/-iv 这种，再配置命令参数时直接输入即可。&lt;/li&gt;
  &lt;li&gt;从文件输入输出，比如in/out 这两个参数，就可以用来控制程序的输入输出路径。&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;控制台交互输入，在调用指令时由于没有指定输入密码，以及初始密钥等参数，指令就会在执行过程中提示用户输入口令，如下图所示：&lt;br /&gt;
&lt;img src=&quot;/images/2015_09_12_00_23/9.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;编码后输出，有时我们希望out选项输出的文件为可读字符内容，即可用cat直接查看的结果，这时就要用到-base64/a 选项，下图是个示例：&lt;br /&gt;
&lt;img src=&quot;/images/2015_09_12_00_23/10.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;pass选项可以支持5中密码输入方式，他们分别为：&lt;/li&gt;
&lt;/ol&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;支持的方式&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;含义&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-pass stdin&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;从控制台读入密码&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-pass pass:xxxx&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;从参数中读入密码密码为xxxx字段的内容&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-pass env:passwdvar&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;从环境变量中读取密码&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-pass file:filename&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;从文件中读入密码&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-pass fd:number&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;number是一个文件描述句柄的编号，比如Unix系统中的管道就可以通过这种方式作为命令的输入。&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;外部加密库的支持&quot;&gt;外部加密库的支持&lt;/h4&gt;
&lt;p&gt;现实使用中，总有人需要外接加密设备（加密机、Ukey等）或软件加密库，为了支持这些设备的加解密模块，OpenSSL提供了engine参数，该参数以设备名称（一般是一个字符串）为输入。如果不知道自己的设备名称可以先通过 engine 的-t参数进行查询。&lt;/p&gt;

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;
&lt;p&gt;这篇学习笔记记录了OpenSSL中和对称算法相关的一些操作指令，以及背景知识。&lt;/p&gt;

</content>
</entry>

<entry>
	<title>OpenSSL中的CA周边（三）</title>
        <link href="/2015/08/29/OpenSSL%E4%B8%AD%E7%9A%84CA%E5%91%A8%E8%BE%B9.html"/>
	<updated>2015-08-29T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/08/29/OpenSSL中的CA周边</id>
	<content type="html">&lt;h2 id=&quot;前言&quot;&gt;前言&lt;/h2&gt;
&lt;p&gt;最近在读OpenSSL的命令参数，在这个学习过程中发现OpenSSL之中，架构了一个非常庞大的理论系统，结果原以为学习一两天就能学完的基础知识，整整学了两个星期，才学到一些皮毛。&lt;/p&gt;

&lt;p&gt;之前整理了一些OpenSSL相关的学习笔记，这篇将涉及一些OpenSSL中和CA有关的知识。&lt;/p&gt;

&lt;h2 id=&quot;架设ca服务器&quot;&gt;架设CA服务器&lt;/h2&gt;

&lt;p&gt;OpenSSL提供了CA指令用于CA服务器的模拟，这个模拟环境能够可以模拟证书的签发吊销等常见CA的操作。CA服务器的目录结构相对复杂，如下所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_30_00_02/1.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;为便于测试人员使用，OpenSSL提供了一个perl脚本（/usr/lib/ssl/misc/CA.pl），以便自动生成CA的环境目录，命令序列如下所示：&lt;/p&gt;
&lt;cmd&gt;
$ mkdir CA/ &amp;amp;&amp;amp; cd CA/  
$ cp /usr/lib/ssl/misc/CA.pl ./  
$ ./CA.pl -newca  
&lt;/cmd&gt;

&lt;p&gt;命令执行后，环境中会自动生成一个自签名的CA根证书(demoCA/cacert.pem)，以及对应的私钥文件(demoCA/private/cakey.pem)。&lt;br /&gt;
可以使用x509和rsa 两个指令查看相应文件的内容。指令如下所示：&lt;/p&gt;
&lt;cmd&gt;
$ openssl x509 -in demoCA/cacert.pem -text -noout  
$ openssl rsa -in demoCA/private/cakey.pem -passin pass:12345678 -text –noout  
&lt;/cmd&gt;

&lt;p&gt;相关字段的具体含义请参考《&lt;a href=&quot;/2015/08/25/从百度证书开始.html&quot;&gt;从百度证书开始&lt;/a&gt;》和《&lt;a href=&quot;/2015/08/27/OpenSSL中的非对称算法.html&quot;&gt;OpenSSL中的非对称算法&lt;/a&gt;》两篇学习笔记中的介绍。&lt;/p&gt;

&lt;h2 id=&quot;生成证书请求&quot;&gt;生成证书请求&lt;/h2&gt;

&lt;p&gt;CA签发证书前，要对客户的证书请求进行验证（除了对文件的内容进行验证以外，更多的其实是申请流程的认证，提交各种不同种类的证明材料），当验证无误后才会进行证书的颁发。所以证书请求一般由客户方提出，下面分别介绍下不同种类的证书请求生成方法.&lt;/p&gt;

&lt;h3 id=&quot;生成rsa证书请求&quot;&gt;生成RSA证书请求&lt;/h3&gt;

&lt;h4 id=&quot;直接生成&quot;&gt;直接生成&lt;/h4&gt;

&lt;p&gt;在创建rsa密钥的同时生成证书请求，指令格式如下：&lt;/p&gt;
&lt;cmd&gt;
$ openssl req -new -newkey rsa:1024 -keyout privkey.pem -passout pass:12345678 -out req.pem
&lt;/cmd&gt;

&lt;p&gt;查看证书请求中的内容，指令格式如下：&lt;/p&gt;
&lt;cmd&gt;
$ openssl req -in req.pem -text -noout
&lt;/cmd&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_30_00_02/2.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;可以看到证书请求文件中包含公钥以及证书所属者的字段，下方的Signature Algorithm字段为自己的私钥的签名值，可确保证书请求的真实性。&lt;/p&gt;

&lt;h4 id=&quot;从rsa密钥生成&quot;&gt;从RSA密钥生成&lt;/h4&gt;

&lt;p&gt;有些时候客户手中已经握有密钥，且希望从已有的密钥生成证书请求。指令如下所示：&lt;/p&gt;
&lt;cmd&gt;
$ openssl req -new -key rsaprivkey.pem -out req.pem
&lt;/cmd&gt;

&lt;p&gt;在openssl的交互提示下录入必要的申请者信息即可。此时生成的请求文件同直接生成的请求结构大体相同，如下所示：&lt;/p&gt;
&lt;cmd&gt;
$ openssl req -in req.pem -text -noout
&lt;/cmd&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_30_00_02/3.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;生成dsa证书请求&quot;&gt;生成DSA证书请求&lt;/h3&gt;

&lt;h4 id=&quot;直接生成-1&quot;&gt;直接生成&lt;/h4&gt;

&lt;p&gt;由于dsa密钥的生成需要有一个dsa参数文件， dsa参数文件的生成可以使用以下命令：&lt;/p&gt;
&lt;cmd&gt;
$ openssl dsaparam -out dsaparam.pem 1024
&lt;/cmd&gt;

&lt;p&gt;在创建dsa密钥的同时生成证书请求，指令格式如下：&lt;/p&gt;
&lt;cmd&gt;
$ openssl req -new -newkey dsa:dsaparam.pem -keyout dsakey.pem -out req.pem -passout pass:12345678
&lt;/cmd&gt;

&lt;p&gt;查看证书请求中的内容，指令如下所示：&lt;/p&gt;
&lt;cmd&gt;
$ openssl req -in req.pem -text -noout
&lt;/cmd&gt;

&lt;p&gt;DSA的证书请求看起来似乎复杂一些，但多出来的内容也只是dsa公钥的相关参数，所以单从请求结构上看还是相同的。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_30_00_02/4.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;从dsa密钥生成&quot;&gt;从DSA密钥生成&lt;/h4&gt;
&lt;p&gt;有些时候客户手中已经握有密钥，且希望从已有的密钥生成证书请求。指令如下所示：&lt;/p&gt;
&lt;cmd&gt;
$ openssl req -new -key dsa512\_1.key -out req.pem
&lt;/cmd&gt;

&lt;p&gt;在openssl的交互提示下录入必要的申请者信息即可。此时生成的请求文件同直接生成的请求结构大体相同，如下所示：&lt;/p&gt;
&lt;cmd&gt;
$ openssl req -in req.pem -text -noout
&lt;/cmd&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_30_00_02/5.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;ca操作&quot;&gt;CA操作&lt;/h2&gt;

&lt;h3 id=&quot;签发一个证书&quot;&gt;签发一个证书&lt;/h3&gt;

&lt;p&gt;CA收到证书请求后，会对客户提供的各种证明资料进行审核，审核通过后会进行证书颁发工作，证书的颁发指令格式如下所示：&lt;/p&gt;
&lt;cmd&gt;
rootkiter@PC:~/CA$ openssl ca -in ~/RSA/req.pem -out ~/RSA/cert.cer -notext
&lt;/cmd&gt;

&lt;p&gt;此时，cert.cer就是颁发完成的证书了。可以通过x509指令进行内容查看，指令如下所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_30_00_02/6.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;批量签署证书请求&quot;&gt;批量签署证书请求&lt;/h3&gt;
&lt;p&gt;在“生成证书请求”的章节，已经生成了多个种类的证书，可以将这些证书放到一个目录下，进行批量签署，如下所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_30_00_02/7.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;批量签署命令格式如下所示：&lt;/p&gt;
&lt;cmd&gt;
$ openssl ca -notext -infiles ~/reqs\_file/careq\_dsa\_req.pem ~/reqs\_file/careq\_rsa\_req.pem ~/reqs\_file/dsa\_req.pem
&lt;/cmd&gt;

&lt;h3 id=&quot;查看ca签署过的证书&quot;&gt;查看CA签署过的证书&lt;/h3&gt;
&lt;p&gt;demoCA目录下有个index文件，该文件记录着该CA签署过的证书内容，可以通过cat指令查看，如下所示：&lt;/p&gt;
&lt;cmd&gt;
$ cat demoCA/index.txt
&lt;/cmd&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_30_00_02/8.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;其中第三列为证书的序列号内容，在ca指令的 status选项下，可以通过指定这个序列号，来查看这个证书当前的状态，指令如下所示：&lt;/p&gt;
&lt;cmd&gt;
rootkiter@PC:~/CA$ openssl ca -status FE2B37D676F58905
&lt;/cmd&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_30_00_02/9.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;证书吊销&quot;&gt;证书吊销&lt;/h3&gt;
&lt;p&gt;当客户的密钥出现问题后（被窃取或者丢失），需要进行证书吊销，吊销指令如下所示：&lt;/p&gt;
&lt;cmd&gt;
$ openssl ca -revoke ~/RSA/cert.cer -crl\_reason keyCompromise
&lt;/cmd&gt;

&lt;p&gt;吊销后在查看该证书，可以发现其已经吊销成功，如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_30_00_02/10.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;生成吊销列表&quot;&gt;生成吊销列表&lt;/h3&gt;

&lt;p&gt;为了方便公众查询证书的吊销状态，ca指令提供了生成吊销列表的指令，格式如下所示：&lt;/p&gt;
&lt;cmd&gt;
$ openssl ca -gencrl -crldays 7 -crlhours 7 -out crl.crl
&lt;/cmd&gt;

&lt;p&gt;可以通过 crl指令查看吊销列表内容，指令格式如下所示：&lt;/p&gt;
&lt;cmd&gt;
$ openssl ca -crl -in crl.crl -text -noout
&lt;/cmd&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_30_00_02/11.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;证书验签&quot;&gt;证书验签&lt;/h2&gt;
&lt;p&gt;证书验签方法可以参考《&lt;a href=&quot;/2015/08/25/从百度证书开始.html&quot;&gt;从百度证书开始&lt;/a&gt;》笔记中的相关内容。&lt;/p&gt;

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;
&lt;p&gt;这篇学习笔记记录了OpenSSL中和CA相关的一些操作指令，以及背景知识。&lt;/p&gt;

</content>
</entry>

<entry>
	<title>OpenSSL中的非对称算法（二）</title>
        <link href="/2015/08/27/OpenSSL%E4%B8%AD%E7%9A%84%E9%9D%9E%E5%AF%B9%E7%A7%B0%E7%AE%97%E6%B3%95.html"/>
	<updated>2015-08-27T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/08/27/OpenSSL中的非对称算法</id>
	<content type="html">&lt;h2 id=&quot;前言&quot;&gt;前言&lt;/h2&gt;
&lt;p&gt;最近在读OpenSSL的命令参数，在这个学习过程中发现OpenSSL之中，架构了一个非常庞大的理论系统，结果原以为学习一两天就能学完的基础知识，整整学了两个星期，才学到一些皮毛。&lt;/p&gt;

&lt;p&gt;之前整理了一篇证书相关的学习笔记，这篇将涉及一些OpenSSL同非对称算法（RSA、DH、DSA）之间的知识。&lt;/p&gt;

&lt;h2 id=&quot;非对称加密算法模型&quot;&gt;非对称加密算法模型&lt;/h2&gt;
&lt;h3 id=&quot;概述&quot;&gt;概述&lt;/h3&gt;
&lt;p&gt;非对称算法广泛应用于数字签名和密钥协商的场景下。相比普通加密算法，非对称加密算法更侧重公开性（密钥公开，算法实现公开），这个特性是由现实生活中常见的攻击手法决定的（暴力猜解，逆向分析算法实现），可以发现它解决这种问题的思路很有趣：&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“你是对我感兴趣么，那我就直接就告诉你喽。”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;通常情况下呢，面对这种毫无趣味的人，你都会觉得这玩意真没意思，然后就不去尝试了，它就安全了。:-)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;非对称加密算法一般会有两个密钥，一个为公钥（pub_key），另一个为私钥（priv_key）,两个密钥内容各不相同，其中公钥可以对众公开，而私钥不公开。同时攻击者很难通过公钥以及加解密算法反向推出私钥。事实上，加密算法E(x)同解密算法D(x) 的实现一般也不太相同。&lt;/p&gt;

&lt;h3 id=&quot;常见算法&quot;&gt;常见算法&lt;/h3&gt;
&lt;p&gt;非对称加密算法在“密钥协商”场景下，有两种情况，一种是“密钥磋商”；另一种是“密钥交换”，在密钥交换时公钥总是用于加密数据，而私钥总是用于解密数据。而在 “数字签名”场景下，操作过程又正好相反，即“公钥用于解密（验签），而私钥用于加密（签名）”。正是这些不同，产生了下表：&lt;/p&gt;

&lt;table class=&quot;gridtable&quot;&gt;
    &lt;tr&gt;
        &lt;td&gt;OpenSSL提供的算法
        &lt;/td&gt;
        &lt;td&gt;可用于“密钥协商” 
        &lt;/td&gt;
        &lt;td&gt;可用于“数字签名”
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;DSA
        &lt;/td&gt;
        &lt;td&gt;--
        &lt;/td&gt;
        &lt;td&gt;可以
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;DH
        &lt;/td&gt;
        &lt;td&gt;可以
        &lt;/td&gt;
        &lt;td&gt;--
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;RSA
        &lt;/td&gt;
        &lt;td&gt;可以
        &lt;/td&gt;
        &lt;td&gt;可以
        &lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;看完这个表格，我觉得RSA算法真是完胜，有种男女通吃的赶脚。&lt;/p&gt;

&lt;h3 id=&quot;常见的应用场景&quot;&gt;常见的应用场景&lt;/h3&gt;
&lt;h4 id=&quot;数字签名&quot;&gt;数字签名&lt;/h4&gt;

&lt;p&gt;个人曾经一直觉得，“数字签名”这个名词听起来很有文艺范，它要解决的问题又很不好理解，所以一直觉得那是个特神奇的领域，绝对是“高端大气上档次”。后来发现，这玩意想要解决的，竟然是一个显而易见的哲学问题：“请快速证明，我就是我自己”。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_27_20_20/1.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;为了更好的，理解这个哲学问题，我决定先编一个故事。&lt;/p&gt;

&lt;p&gt;你在网上认识一个网友D，你俩聊得特Happy，但相互没见过面。有一天，有个人敲你家房门，他告诉你：他是D，他想给你个惊喜，来看看你。结果呢，你这家伙生性多疑，完全不信这话，非要核对一下身份，怎么办呢，此时你要做的事情就是证明眼前的这家伙就是D。与此同时他面临的问题就开始哲学起来了：“请快速证明，我就是我自己。”&lt;/p&gt;

&lt;p&gt;其实按理来说这个问题并不太难，你俩只要回忆一下你们之间聊过的独特的话就可以了。&lt;/p&gt;

&lt;p&gt;但有些时候问题确实很麻烦，比如你们俩的聊天内容总会被第三方读到（比如你家里的间谍“路由器先生”，或者他家里的间谍“交换机先生”，甚至你们聊天的会话也可能会被黑客放置了“窃听器”），这时候你们聊过的内容就不再只有你们两个知道，发现了没，哲学问题从“普通模式”转眼就变成“地狱模式”啦。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_27_20_20/2.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;到了这里你可能很快就想到，我有身份证啊，有了身份证，我就能证明这个哲学问题了。恭喜你，你已经打通了任督二脉，没错的，身份证是每个人身份的标识，但是互联网中没有实体身份证，能有的只是一堆数字或者字符。当某一段数字或者字符具有了“身份证”属性后它就成了“数字签名”。&lt;/p&gt;

&lt;p&gt;“数字签名”一般由“CA机构（相当于公安局的户籍管理部门）”签发，网络中每个人都只相信CA说的话，当然了CA机构自己也需要被认定。它的签名是由它自己签发的（自签名）。&lt;/p&gt;

&lt;h4 id=&quot;密钥约定&quot;&gt;密钥约定&lt;/h4&gt;

&lt;p&gt;咱们继续数字签名章节的“哲学问题”往下聊。你和朋友D那天特别开心，然后他回家了。你们还是每天在网上聊天打发时间，但是突然有一天，聊天室服务器被黑客H入侵了，他这人不坏，就是对每个人的聊天记录感兴趣（好吧，我承认，他是个喜欢偷听他人聊天的变态）。&lt;/p&gt;

&lt;p&gt;虽然你和D的谈话被人看见也没什么（别以为我会相信），但知道有人偷窥这个事之后，心里也总觉得怪怪的。你开始思考是不是把聊天记录做个加密，以免黑客H看到。你朋友D想了想这个提议，同意了，并且夸你聪明。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_27_20_20/3.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;事情进展的顺利，加密算法也选好了，用上了当前性价比很高的3DES加密算法。最后的问题就是约定密钥了，这时你发现问题了，怎么把密钥告诉D而不告诉H呢，要时刻记得H是个变态，他一直研究你们的聊天记录呢。&lt;/p&gt;

&lt;p&gt;一旦你在聊天中说出了密钥的内容，他马上就会知道，于是你们只好通过其他途径共享密钥，为了避免黑客H猜解出密码继续翻阅你们的聊天记录，你们每次开始聊天都会进行“共享密钥”的操作，如果每次交换都单独找其他通讯渠道，过于繁琐，也不易操作。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_27_20_20/4.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;于是一大帮数学家想了两种靠谱的思路来解决“密钥约定”的问题。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;思路1（密钥交换）：&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;先假设我们要传输的密钥为  HELLO&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;首先用D的公钥D_pub_key 将密钥（HELLO）进行加密，得到密文（OLLEH）。&lt;/li&gt;
  &lt;li&gt;将密文（OLLEH）通过开放会话传送给D。&lt;/li&gt;
  &lt;li&gt;D拿到密文（OLLEH）后，使用自己的私钥D_priv_key进行解密还原出密钥明文（HELLO）。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_27_20_20/5.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;此刻密钥约定成功，即使黑客H看到了密文（OLLEH）也没关系，他没有D的私钥，自然无法解出明文的密钥。
于是你们终于可以放心的用3DES加密算法聊天了。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;思路2（密钥磋商）：&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;这个思路的精髓在于“磋商”，过程类似于买东西时候 “砍价”。具体过程描述如下：&lt;/p&gt;

&lt;p&gt;首先呢，通讯双方各想一个密钥（两侧的密钥分别为K1、K2）记在心里，随后各自将这个密钥做一次变形（假设变形方法为E1）成为一个密钥参数(两人生成的参数分别为Z1、Z2)，并把它通知对方，此时双方都能够拿到对方的密钥参数Z，用自己刚才想到的密钥K再做一次变形（假设处理方法为E2）作为最终密钥（K3）。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_27_20_20/6.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;由于K3的确定过程中既有K1参与又有K2参与，所以只要算法E1和E2选择得当，双方是能够可以得到相同K3结果的。&lt;br /&gt;
在这个密钥约定过程中，黑客H能得到的只有通讯双方相互发送的密钥参数Z，在攻击者不知道任何一方初始密钥（K1和K2）情况下，便无法得到最终密钥K3。&lt;br /&gt;
于是，双方同样可以进行3DES的加密通讯了。&lt;/p&gt;

&lt;h2 id=&quot;密钥生成&quot;&gt;密钥生成&lt;/h2&gt;

&lt;p&gt;个人一直觉得说是“密钥生成”，这个说法一直不够完美，不完美的原因有二：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;得到的密钥文件一般都是公私钥一体的文件，也就是说公私钥是成对出现在相同文件中的。&lt;/li&gt;
  &lt;li&gt;在DH算法结果中，其实只存在密钥参数而无密钥存在，其结果密钥是双方在API调用中，通过代码实现计算出来的。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;但不管哪种情况，还是先来看看这几种非对称加密算法相关的指令格式吧。&lt;/p&gt;

&lt;h3 id=&quot;生成dsa密钥&quot;&gt;生成DSA密钥&lt;/h3&gt;

&lt;p&gt;DSA密钥生成相对复杂，一般分两步，首先要生成一个密钥参数文件，生成指令如下：&lt;/p&gt;
&lt;cmd&gt;
$ openssl dsaparam -out dsa512.pem 512
&lt;/cmd&gt;

&lt;p&gt;此时dsa512.pem 文件中就存储了一组dsa密钥参数，想要查看其内容，可以使用-text选项，指令格式及执行结果如下所示：&lt;/p&gt;
&lt;cmd&gt;
$ openssl dsaparam -in dsa512.pem -text –noout
&lt;/cmd&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_27_20_20/7.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这表明密钥参数中包含了3个参数的值，分别为P、Q、G，至于这三个值具体有什么作用，是DSA算法的内容，不在本文讨论范围，只要知道它们是DSA密钥参数就足够了。&lt;/p&gt;

&lt;h4 id=&quot;生成dsa密钥-1&quot;&gt;生成DSA密钥&lt;/h4&gt;

&lt;p&gt;有了DSA密钥参数后，即可根据参数生成DSA密钥了。指令格式如下：&lt;/p&gt;
&lt;cmd&gt;
$ openssl gendsa -out dsa512\_1.key dsa512.pem
&lt;/cmd&gt;
&lt;p&gt;此时生成了一个名为 dsa512_1.key 的文件，OpenSSL同样提供了查看该文件内容的指令，指令格式及执行结果如下所示：&lt;/p&gt;
&lt;cmd&gt;
$ openssl dsa -in dsa512\_1.key -text -noout
&lt;/cmd&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_27_20_20/8.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;可以看到，新生成的密钥文件比之前的密钥参数文件多了两个字段，分别为priv字段和pub字段，它们分别代表这DSA私钥和公钥的主体。&lt;/p&gt;

&lt;p&gt;细心的读者应该发现这个密钥的文件名为dsa512_1.key这么起名，有什么意义呢，下面我们再执行一遍生成密钥的操作，来生成一个dsa512_2.key这个文件，然后比对一下它和dsa512_1.key的区别:&lt;/p&gt;
&lt;cmd&gt;
$ openssl gendsa -out dsa512\_2.key dsa512.pem
$ openssl dsa -in dsa512\_2.key -text -noout
&lt;/cmd&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_27_20_20/9.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;看出dsa512_1.key 和 dsa512_2.key 这两个文件的不同点了么，他们在使用了完全相同的命令和密钥参数后，却得到了完全不同的密钥对（仔细比对priv和pub的字段结果）。&lt;/p&gt;

&lt;p&gt;不是你眼花了，也不是gendsa指令出错了，而是DSA密钥在生成过程中，会引入一个随机数作为输入，在未指定随机数时，指令会随便找一个随机数拿过来用，这就导致了每次得到的密钥对各不相同。&lt;/p&gt;

&lt;p&gt;这个随机数也可以通过制定rand种子来设置，指令格式如下（不过经测试发现，即使制定了输入的随机数种子，生成的密钥仍然各不相同）：&lt;/p&gt;
&lt;cmd&gt;
$ echo HelloWorld &amp;gt; myrandfile
&lt;/cmd&gt;
&lt;cmd&gt;
$ openssl gendsa -out dsa512\_3.key -rand myrandfile dsa512.pem
&lt;/cmd&gt;

&lt;h3 id=&quot;生成dh密钥参数&quot;&gt;生成DH密钥参数&lt;/h3&gt;

&lt;p&gt;DH密钥参数生成方法非常简单，只需要一条命令：&lt;/p&gt;
&lt;cmd&gt;
$ openssl gendh -out db512.pem 512
&lt;/cmd&gt;

&lt;p&gt;那么生成的结果中内容有什么呢，可以用另一条命令：&lt;/p&gt;
&lt;cmd&gt;
$ openssl dh -in db512.pem
&lt;/cmd&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_27_20_20/10.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这玩意具体什么意思呢，你也别问我，我现在也还没搞懂，等搞懂了再说。&lt;/p&gt;

&lt;p&gt;密钥协商的过程是通过调用API进行的，所以通常都需要将上面的密钥参数写到代码中，为了便于代码移植，dh指令提供了-C参数，用于C代码格式的调用（好贴心呢）：&lt;/p&gt;
&lt;cmd&gt;
$ openssl dh -in db512.pem -noout -C
&lt;/cmd&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_27_20_20/11.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;生成rsa密钥&quot;&gt;生成RSA密钥&lt;/h3&gt;

&lt;p&gt;RSA密钥生成非常简单，一行指令轻松搞定，格式如下所示：&lt;/p&gt;
&lt;cmd&gt;
$ openssl genrsa -out rsaprivkey.pem 1024
&lt;/cmd&gt;

&lt;p&gt;想要查看密钥中的内容，可以使用如下指令：&lt;/p&gt;
&lt;cmd&gt;
$ openssl rsa -in rsaprivkey.pem -text -noout 
&lt;/cmd&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_27_20_20/12.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这一大堆都是什么东西呢，也是别问我，去问那帮搞密码学的数学家吧，他们会告诉你的。&lt;/p&gt;

&lt;h2 id=&quot;公钥提取&quot;&gt;公钥提取&lt;/h2&gt;

&lt;p&gt;由于DH算法无公私钥机制，所以这里提到的公钥提取，只涉及DSA公钥和RSA公钥。&lt;/p&gt;

&lt;h3 id=&quot;提取dsa公钥&quot;&gt;提取DSA公钥&lt;/h3&gt;

&lt;p&gt;从DSA密钥文件提取DSA公钥的方法很简单，指令格式如下：&lt;/p&gt;
&lt;cmd&gt;
$ openssl dsa -in dsa512\_2.key -out  dsapubkey.pem -pubout
&lt;/cmd&gt;

&lt;p&gt;查看公钥内容：&lt;/p&gt;
&lt;cmd&gt;
$ openssl dsa -in dsapubkey.pem -pubin -text -noout
&lt;/cmd&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_27_20_20/13.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;对比“生成DSA密钥”章节的截图可以发现，公钥实际上是密钥文件的一部分。&lt;/p&gt;

&lt;h3 id=&quot;提取rsa公钥&quot;&gt;提取RSA公钥&lt;/h3&gt;

&lt;p&gt;从RSA密钥文件提取RSA公钥的方法很简单，指令格式如下：&lt;/p&gt;
&lt;cmd&gt;
$ openssl rsa -in pub.pem -pubin -text -noout
&lt;/cmd&gt;

&lt;p&gt;查看公钥的内容：&lt;/p&gt;
&lt;cmd&gt;
$ openssl rsa -in pub.pem -pubin -text -noout
&lt;/cmd&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_27_20_20/14.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;可以看到，RSA公钥同样只是密钥文件中的一部分，可以去对比下“生成RSA密钥”章节中的截图。&lt;/p&gt;

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;
&lt;p&gt;这篇学习笔记记录了OpenSSL中和非对称加解密算法相关的一些潜在知识，并不完全，与之相关的其他内容将在下一篇学习笔记中继续完善。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>从百度证书开始(一)</title>
        <link href="/2015/08/25/%E4%BB%8E%E7%99%BE%E5%BA%A6%E8%AF%81%E4%B9%A6%E5%BC%80%E5%A7%8B.html"/>
	<updated>2015-08-25T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/08/25/从百度证书开始</id>
	<content type="html">&lt;h2 id=&quot;前言&quot;&gt;前言&lt;/h2&gt;
&lt;p&gt;最近在读OpenSSL的命令参数，在这个学习过程中发现OpenSSL之中，架构了一个非常庞大的理论系统，结果原以为学习一两天就能学完的基础知识，整整学了两个星期，才学到一些皮毛。&lt;/p&gt;

&lt;p&gt;这里先整理一个阶段性的学习笔记，其他学习笔记将在后面继续整理。在这篇学习笔记中，将包含一个相对完整的证书周边的知识，以及与之相关的OpenSSL指令用法。为了让这篇笔记看起来更连贯，将以百度的证书为起点展开证书体系的介绍。&lt;/p&gt;

&lt;h2 id=&quot;百度的证书&quot;&gt;百度的证书&lt;/h2&gt;
&lt;h3 id=&quot;获取百度的https证书&quot;&gt;获取百度的HTTPS证书&lt;/h3&gt;
&lt;p&gt;在OpenSSL中，提供了一个s_client选项，它可以模拟一个访问https的客户端。利用这个客户端可以很方便的获取到HTTPS的证书信息。&lt;br /&gt;
命令如下所示：&lt;/p&gt;
&lt;cmd&gt;
$ openssl s\_client -connect baidu.com:443  
&lt;/cmd&gt;

&lt;p&gt;命令执行后，会在控制台中打出一整段格式怪异的执行结果，它包含两个部分 : 证书相关的内容 + 实际https会话相关信息。&lt;/p&gt;

&lt;h3 id=&quot;证书链&quot;&gt;证书链&lt;/h3&gt;
&lt;p&gt;s_client这条命令执行完，可以在结果中看到这样一块区域，名字为：Certificate chain。如下图所示：  &lt;br /&gt;
&lt;img src=&quot;/images/2015_08_25_22_01/1.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;可以看到它包含 0/1/2 三段标示，每个标示都指代着一条证书记录。&lt;/p&gt;

&lt;p&gt;标示0：从它的s字段，可以看出这个证书的所属者为百度（O=BeiJing Baidu Netcom Science Technology），它的注册地点为北京，是一家中国公司（C=CN/ST=beijing）。颁发这个证书的认证机构（所谓的CA）信息在i字段中，他是由G3 这个证书签发的。&lt;/p&gt;

&lt;p&gt;类似的，在标示1中，可以看到G3 这个CA的证书又是由G5这个CA签发的。	在标示2中，G5证书又是由Public Primary Certification Authority.签发的。&lt;/p&gt;

&lt;p&gt;看到这里，“证书链”的概念就容易理解了，根CA为了自身管理的方便，会将证书的签署权限依次下发给其他CA，本例中就是签署了G5，阅读G5的OU内容可以看到该机构只负责颁布证书。G5又签署认证了G3于是G3又合法了。最后，G3就签署了百度的证书。&lt;/p&gt;

&lt;p&gt;从认证流程来看，在“证书链”中，只要有一个证书认证出现问题，那么处于证书链后方的所有证书都将认证失败。&lt;/p&gt;

&lt;h2 id=&quot;证书内的信息&quot;&gt;证书内的信息&lt;/h2&gt;
&lt;h3 id=&quot;提取证书&quot;&gt;提取证书&lt;/h3&gt;

&lt;p&gt;证书链字段下方，就是百度的证书内容了，它被一个起始和终止标签包围，如下所示：&lt;/p&gt;
&lt;cmd&gt;   
\-----BEGIN CERTIFICATE-----  
MIIGaTCCBVGgAwIBAgIQN23AqZqLxKVCT8qo88qpAzANBgkqhkiG9w0BAQUFADC  
...  
...balabala...  
...  
CIhENC7RHoQqph7JJQ==  
-----END CERTIFICATE-----  
&lt;/cmd&gt;
&lt;p&gt;想要阅读这一堆字符所包含的信息，就需要用到OpenSSL的另一条指令：&lt;/p&gt;
&lt;cmd&gt;
$ openssl x509 -in baidu.pem -inform PEM -noout -text  
&lt;/cmd&gt;
&lt;p&gt;在这条命令内，用到了x509指令中的几个选项，它们的含义如下：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;in参数指定一个证书录入路径，&lt;/li&gt;
  &lt;li&gt;inform参数标示该文件的格式，这种base64编码类型的证书串为PEM格式，当编码无法直接可读时一般为DER编码。&lt;/li&gt;
  &lt;li&gt;-noout参数表明该指令不会生成新文件，以免占用本地磁盘空间。&lt;/li&gt;
  &lt;li&gt;-text   参数会告诉x509指令将证书的所有信息以可直接阅读的方式输出。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;由于该指令参数需要从一个文件中读取证书内容，所以，首先要把百度的证书保存为一个名为baidu.pem的文件。如下图所示：   &lt;br /&gt;
&lt;img src=&quot;/images/2015_08_25_22_01/2.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;解析证书中的字段&quot;&gt;解析证书中的字段&lt;/h3&gt;
&lt;p&gt;X509指令执行完毕后，在控制端就可以得到证书的详细内容，下面将对其中部分字段做详细解释。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;序列号字段，指明了该证书的序列号，该序列号在同CA下唯一。&lt;br /&gt;
&lt;em&gt;Serial Number: 37:6d:c0:a9:9a:8b:c4:a5:42:4f:ca:a8:f3:ca:a9:03&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;签发方式字段，指明了该证书的签名算法&lt;br /&gt;
&lt;em&gt;Signature Algorithm: sha1WithRSAEncryption&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Issuer字段，指明了该证书的颁发者信息，百度这个证书是由G3颁发的。&lt;br /&gt;
&lt;em&gt;Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=Terms of use at https://www.verisign.com/rpa (c)10, CN=VeriSign Class 3 International Server CA - G3&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Validity字段，指明了证书的有效期，有趣的是证书有效期竟然使用排除法描述。&lt;br /&gt;
&lt;em&gt;Not Before: Apr 16 00:00:00 2015 GMT
Not After : Apr 16 23:59:59 2016 GMT&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Subject字段，指明了本证书的主体描述&lt;br /&gt;
&lt;em&gt;Subject: C=CN, ST=beijing, L=beijing, O=BeiJing Baidu Netcom Science Technology Co., Ltd, OU=service operation department, CN=www.baidu.cn&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Subject Public Key Info字段，指明了证书中的公钥详细信息。&lt;br /&gt;
&lt;img src=&quot;/images/2015_08_25_22_01/3.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;X509v3 Subject Alternative Name字段，指明了该证书同样适用的几个域名。&lt;br /&gt;
&lt;em&gt;DNS:baidu.cn, DNS:baidu.com, DNS:baidu.com.cn, DNS:w.baidu.com, DNS:ww.baidu.com, DNS:www.baidu.cn, DNS:www.baidu.com.cn, DNS:www.baidu.com.hk, DNS:www.baidu.hk, DNS:www.baidu.net.au, DNS:www.baidu.net.my, DNS:www.baidu.net.ph, DNS:www.baidu.net.pk, DNS:www.baidu.net.tw, DNS:www.baidu.net.vn, DNS:wwww.baidu.com, DNS:wwww.baidu.com.cn&lt;/em&gt; &lt;br /&gt;
可以看到这些域名都是百度公司自己的域名。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;X509v3 Basic Constraints字段，指明该证书是否可用于CA验签，如果可用于验签则其值为TRUE。&lt;br /&gt;
&lt;em&gt;CA:FALSE&lt;/em&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;X509v3 Key Usage字段，该字段指明该证书的用途，百度这个证书是用于数字签名，和密钥加密&lt;br /&gt;
&lt;em&gt;Digital Signature, Key Encipherment&lt;/em&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;X509v3 Extended Key Usage字段，指明该证书的扩展用途，百度这个证书还可以用于TLS服务验证、TLS客户端验证、Netscape服务的加密&lt;br /&gt;
X509v3 Extended Key Usage: 
&lt;em&gt;TLS Web Server Authentication, TLS Web Client Authentication, Netscape Server Gated Crypto&lt;/em&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;X509v3 Certificate Policies字段，是一个扩展字段。应该是由CA要求填写的一个字段。&lt;br /&gt;
&lt;em&gt;X509v3 Certificate Policies: &lt;br /&gt;
Policy: 2.16.840.1.113733.1.7.54&lt;br /&gt;
CPS: https://d.symcb.com/cps&lt;br /&gt;
User Notice:&lt;br /&gt;
Explicit Text: https://d.symcb.com/rpa&lt;/em&gt;&lt;br /&gt;
可以看到该字段中描述了一些赛门铁克相关的网址链接。事实上百度的这个证书正是由赛门铁克颁发的。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;X509v3 Authority Key Identifier字段，指明了G3的证书序列号&lt;br /&gt;
&lt;em&gt;keyid:D7:9B:7C:D8:22:A0:15:F7:DD:AD:5F:CE:29:9B:58:C3:BC:46:00:B5&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;X509v3 CRL Distribution Points，当前的CRL列表，当证书失效或被窃取后，需要将出问题的证书在对应的CA签发机构进行吊销（就是令相应证书失效），每个CA机构都会为自己签发的证书维护一个吊销列表，当某个证书在吊销列表中时，对该证书的验签将会失败。&lt;br /&gt;
&lt;em&gt;Full Name:
URI:http://se.symcb.com/se.crl&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Authority Information Access，和签发CA有关的信息，从内容看一个为在线的CRL服务地址，另一个为CA的证书地址。&lt;br /&gt;
&lt;em&gt;OCSP - URI:http://se.symcd.com
CA Issuers - URI:http://se.symcb.com/se.crt&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Signature Algorithm，这个字段的内容为CA机构提供的数字签名结果，证书验证者用CA提供的公钥解密这个字段值后，会得以上所有内容的一个摘要信息，通过比对这个摘要信息结果，可以确定证书的合法性。  &lt;br /&gt;
&lt;img src=&quot;/images/2015_08_25_22_01/4.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;证书中关键信息回顾&quot;&gt;证书中关键信息回顾&lt;/h3&gt;

&lt;h4 id=&quot;证书主体框架&quot;&gt;证书主体框架&lt;/h4&gt;

&lt;p&gt;通过3.2章节的介绍，可以了解，一个证书是由“公钥数据”+“证书适用范围及其他扩展信息”+“CA的认证签名”三个主要部分组成，其中“CA的认证签名”也只负责前两个主要部分的校验，并保证这两个部分的数据没有更改、替换或遗失。&lt;/p&gt;

&lt;h4 id=&quot;签名算法&quot;&gt;签名算法&lt;/h4&gt;

&lt;p&gt;百度这个证书中，用到的是sha1WithRSAEncryption签名算法，这个算法名由两个部分组成，分别为sha1和RSA，其中RSA为非对称加密算法，正好可以解决身份认证的问题，但该算法在实际使用中有短板，那就是只能加密定长（加密长度取决于密钥长度）的数据（证书中需要认证的数据远大于这个长度），如果使用分组加密模式，加解密的过程又非常耗时，为了解决这两个问题，就引入了信息摘要算法sha1，将需要加密的数据首先做一次摘要，生成一个定长的摘要结果，再对这个定长的摘要结果进行非对称认证就可以迅速解决问题了。&lt;/p&gt;

&lt;h4 id=&quot;证书验证相关指令&quot;&gt;证书验证相关指令&lt;/h4&gt;
&lt;p&gt;实际使用中，证书的验证过程相对比较复杂，不但要验证证书是否由合法CA签发，还要验证这个证书是否已经被吊销过。这一小节就将对这两个操作分开说明。&lt;/p&gt;

&lt;h5 id=&quot;证书验证&quot;&gt;证书验证&lt;/h5&gt;

&lt;p&gt;OpenSSL提供了verify指令以便我们验证证书合法性。下面我们继续以百度这个证书为例，来看一下如何校验证书。&lt;br /&gt;
想要验证百度的这个证书，首先要有其对应CA的证书，在证书中提供了一CA证书的下载地址，直接wget即可得到。&lt;/p&gt;
&lt;cmd&gt;
$ wget http://se.symcb.com/se.crt  
&lt;/cmd&gt;

&lt;p&gt;得到证书后，可以发现该证书是一个DER编码的证书，而OpenSSL大多数指令都要求输入的文件编码为PEM编码，于是，需要对其进行一次格式转换，指令如下：&lt;/p&gt;
&lt;cmd&gt;  
$ openssl x509 -in se.crt -inform DER -out se.pem -outform PEM
&lt;/cmd&gt;

&lt;p&gt;编码转换完，就可以用se.pem来验证baidu.pem这个证书的合法性了。命令如下所示:&lt;/p&gt;

&lt;cmd&gt;
$ openssl verify -CAfile se.pem baidu.pem  
&lt;/cmd&gt;

&lt;p&gt;PS:在ubuntu下，OpenSSL的可信根证书在 /usr/lib/ssl/certs/ 目录下，在这里可以找到G5 的证书，不过由于签发时间有更改，所以证书序列号有改动，但证书公钥完全相同。&lt;/p&gt;

&lt;h5 id=&quot;吊销凭证&quot;&gt;吊销凭证&lt;/h5&gt;

&lt;p&gt;证书在使用中，可能会遇到密钥被窃、密钥遗失等问题，这些问题一旦出现，就需要对已经颁发的证书进行吊销，使其失效。实现这个机制的方案就是由CA机构维护一个证书的吊销列表，当证书被吊销时，会将这个证书的序列号就添加到吊销列表（CRL）中。&lt;br /&gt;
百度这个证书是由赛门铁克签发，所以其对应的吊销列表（CRL）也由赛门铁克维护，在证书中给出了获取该列表的URI，即http://se.symcb.com/se.crl，可以直接使用wget命令将其下载至本地：&lt;/p&gt;
&lt;cmd&gt;
$ wget http://se.symcb.com/se.crl  
&lt;/cmd&gt;

&lt;p&gt;下载到这个证书后，同样可以使用OpenSSL的crl指令来阅读其内容，指令格式如下：&lt;/p&gt;
&lt;cmd&gt;
$ openssl crl –in se.crl –inform DER –text –out result.txt  
&lt;/cmd&gt;

&lt;p&gt;指令执行完毕，可以在result.txt文件中看到crl列表的具体内容， 通过查看该文件，可以发现，该文件的内容也是相对比较复杂的，除了包含必要的CRL介绍信息（Issuer、Last Update、Next Update、CRL Number、Authority Key Identifier、Revoked Certificates）外，结果文件中还包含着对这些内容信息的签名，签名算法同样是使用sha1WithRSAEncryption，这个签名是为了防止伪造CRL文件的，为其签名者同样是G3证书。&lt;br /&gt;
在吊销列表中可以发现，被吊销过的证书有25194之多（2015年8月12日的CRL列表），随着时间的继续，该数量还会继续增加，crl文件的大小也会继续增加，这意味着查找证书序列号会越来越耗时，为了解决这个问题，CA机构一般都会提供一个在线服务（OCSP）来支持快速验证。百度的证书中也给出了赛门铁克公司的OCSP地址:http://se.symcd.com，我们同样可以通过该服务来实现在线验证一个证书是否被吊销过，查找命令在OpenSSL中同样有提供，命令格式如下：&lt;/p&gt;
&lt;cmd&gt;
$ openssl ocsp -issuer se.pem -cert baidu.pem -url http://se.symcd.com -respout resp.der -text -CAfile se.pem
&lt;/cmd&gt;

&lt;p&gt;事实上OpenSSL官网给出的ocsp查询指令示例（https://www.openssl.org/docs/apps/ocsp.html）不包含CAfile选项，但本人测试时发现，如果不加该选项，执行结果会报“Response Verify Failure” 这个错误，这表明本地openssl对ocsp的回复合法性存疑，即无法确定回复确实是由赛门铁克公司给出的ocsp结果。只有添加了CAfile参数并将其指定为赛门铁克的公钥证书时才可以认证通过，估计这可能是openssl官网在写样例命令时的一个疏忽吧。&lt;br /&gt;
这些问题都解决后，命令就可以成功执行了，最后给出的结论为baidu.pem: good 证明百度这个证书没有被吊销过。如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_25_22_01/5.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;事实上吊销凭证的查询还有另一种方式，当我们掌握了被查询证书的序列号后，就可以直接递交序列号来查询，百度证书序列号的查询方法可以用以下命令：&lt;/p&gt;
&lt;cmd&gt;
$ openssl x509 -in baidu.pem -serial -noout  
serial=376DC0A99A8BC4A5424FCAA8F3CAA903  
&lt;/cmd&gt;

&lt;p&gt;那么此时，ocsp的查询指令就变为了：&lt;/p&gt;
&lt;cmd&gt;
$ openssl ocsp -issuer se.pem -serial 0x376DC0A99A8BC4A5424FCAA8F3CAA903 -url http://se.symcd.com -respout resp.der  -text -CAfile se.pem  
&lt;/cmd&gt;

&lt;p&gt;如果证书被吊销过，会显示什么结果呢，我们从刚才看到的crl吊销列表随便找一个被吊销过的证书序列号：0106CCE3880F7C2E74140912A0CC379E，然后查询一下它，就得到如下结果：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_25_22_01/6.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;从这个查询结果中可以看出该证书于2011年12月12日被吊销，吊销原因为：密匙数据外泄。&lt;/p&gt;

&lt;h2 id=&quot;面临的威胁及影响&quot;&gt;面临的威胁及影响&lt;/h2&gt;
&lt;h3 id=&quot;来自ca的威胁&quot;&gt;来自CA的威胁&lt;/h3&gt;

&lt;p&gt;CA是互联网证书体系的根基，一旦CA出现问题，互联网上的证书认证必将混乱。从宏观来看，证书体系对技术的要求并不是很高，一台装有OpenSSL的机器就可以轻松模拟一个CA机构。所以对于一个CA机构来说，最难掌控的部分在于如何维护它的合法性，能够威胁其合法性的情况大体有以下几种情况（个人可以预见的几点，必然不够全面）：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;CA私钥泄漏：这是最危险的情况，因为私钥持有者可以拿着私钥随意签名，随意颁布吊销列表，整个互联网将没有任何信任可言。&lt;/li&gt;
  &lt;li&gt;CA私钥遗失：仅次于私钥泄漏，CA的多数操作（证书签发、证书续约、颁发吊销列表等）都是依赖CA私钥进行的，丢失了私钥的CA将完全无法正常工作。&lt;/li&gt;
  &lt;li&gt;证书颁发流程不严谨：一个CA在颁布一个合法证书前，要对客户进行非常完善的调查（申请人是不是合法公民？证书的使用范围是否超越常理？等等），这套机制不亚于公安机关办案。在这套流程中一旦出现问题，后果是非常严重的，一个只需要普通证书的用户却得到了一个CA证书，那他就可以拿着这个证书去给别人颁发证书赚钱了呢。这样的CA能被人信任就怪了。&lt;/li&gt;
  &lt;li&gt;证书吊销流程不严谨：如果这个流程不够严谨，就意味着我看谁的证书不爽，我就可以去告诉CA吊销了它。这也会给互联网的认证机制造成混乱。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;算法层威胁&quot;&gt;算法层威胁&lt;/h3&gt;

&lt;p&gt;这是一种来自数学层面的攻击，从证书的颁发和认证流程就可以看出它的核心工作流程是基于非对称加密算法实现的，一旦这些认证算法，或者签名算法出现问题，这也会引起认证体系的混乱。和百度证书认证有关的算法，叫做sha1WithRSAEncryption，它由两部分组成：信息摘要算法（sha1）+非对称加密算法（RSA）。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;信息摘要算法&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;摘要算法的基本数学描述为：对一段数据m进行信息摘要得到结果z，摘要算法为H(x)，则 z=H(m)。&lt;br /&gt;
在签名机制中，摘要算法面临的主要攻击是，找到相同摘要结果的不同定制数据。数学描述就是：已知 H(m1)=z 的情况下，很难找到一个有特定意义的m2 另 H(m2)=z也同时成立。一旦攻击者能够很容易找到m2 数据的构造方法，他就可以将自己的密钥对封装在m2中，并复用m1的签名结果，进行签名伪造(不同私钥共用相同签名的状态)。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;非对称加密算法&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;非对称算法在身份认证机制中，主要用到的是公私钥唯一对应关系，即公钥加密的数据只能由私钥进行解密，同时私钥加密的数据只能由公钥进行解密。那么它面临的攻击将有两个方面：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;可通过公钥很容易的推出私钥，这种情况意味着私钥的直接泄漏。认证体系自然会混乱。&lt;/li&gt;
  &lt;li&gt;可通过公钥找到另一个私钥，这种情况虽然不是私钥直接泄漏，但威胁同泄漏私钥的结果是相同的，认证体系也同样会混乱。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;私钥泄漏威胁&quot;&gt;私钥泄漏威胁&lt;/h3&gt;
&lt;p&gt;前面在CA威胁中提到过CA私钥泄漏的情况，这里与之的区别在于泄漏私钥的主体为用户。实际生活中，普通用户对于密钥体系的理解可能会存在误区，导致错误使用私钥，进而泄漏私钥。我这里可以想到的两个误区为：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;对密钥文件的理解误区：了解过OpenSSL指令体系的同学一般都会知道，直接从OpenSSL生成的公钥和私钥一般都存储在同一文件中，如果用户在使用中（一般是公钥公布的环节）没有注意到这一个细节，就会造成私钥的泄漏。&lt;/li&gt;
  &lt;li&gt;对公私钥体系的理解误区：学习过公私钥资料的同学通常会很自然的认为，公私钥权利是等价的：“公钥加密，私钥解密”，或“私钥加密，公钥解密”。他们觉得只要把其中一个称为公钥，而另一个称为私钥即可，而不用在意其顺序。在这种错误的观念下很容易把两者用反，最终导致私钥泄漏。从公钥无法反推出私钥是有大量的数学推导提供安全保障的，而反过来则不存在安全保障。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;
&lt;p&gt;综上所述，证书管理及验证是一套非常庞大的体系，建造一个完备的证书认证系统也是存在一定困难的。身份认证机制并不只在https通信中有应用，它在银行行业中化身为Ukey，网络当中有些功能重要的服务器为了防止密码暴力破解也采取了密钥证书的身份认证机制。&lt;/p&gt;

</content>
</entry>

<entry>
	<title>Android下的NDK</title>
        <link href="/2015/08/06/Android%E4%B8%8B%E7%9A%84NDK.html"/>
	<updated>2015-08-06T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/08/06/Android下的NDK</id>
	<content type="html">&lt;h2 id=&quot;前言&quot;&gt;前言&lt;/h2&gt;
&lt;p&gt;这也是很久之前写的一篇学习笔记，刚翻出来瞅了一眼，有些小细节还是已经有些过时了，看来技术的变更速度真的是太快了。既然也是曾经的劳动成果，那就同样拿出来简单的整理一下吧。&lt;/p&gt;

&lt;p&gt;该笔记参考http://blog.sina.com.cn/s/blog_61b056970100sy0u.html博文而成。&lt;/p&gt;

&lt;h3 id=&quot;环境搭建&quot;&gt;环境搭建&lt;/h3&gt;
&lt;p&gt;首先，jdk，eclipse，android sdk ，android ndk ，cygwin ，cdt，adt你肯定要安装好吧，没安装好的同学请百度下相关配置教程，这不是我文章的重点。&lt;/p&gt;

&lt;h2 id=&quot;编写helloworld&quot;&gt;编写helloworld&lt;/h2&gt;

&lt;h3 id=&quot;编写jni接口&quot;&gt;编写Jni接口：&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;在资源目录下创建 jni.java文件
&lt;img src=&quot;/images/2015_08_06_22_43/1.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;声明jni接口
&lt;img src=&quot;/images/2015_08_06_22_43/2.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;命令行模式下进入src目录执行javac jni.java&lt;br /&gt;
&lt;img src=&quot;/images/2015_08_06_22_43/3.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;将生成的 .class 文件拷贝到 /bin 目录下的对应路径并覆盖
&lt;img src=&quot;/images/2015_08_06_22_43/4.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;命令行进入 /bin/classes/ 目录 执行javah  –jni com.example.killndk.Jni  生成一个 .h  文件：
&lt;img src=&quot;/images/2015_08_06_22_43/5.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;在根目录下创建jni文件夹用于保存C程序代码，并将刚生成的.h文件拷贝进去：&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;以jni目录为根目录建立C工程，添加C源码以及.mk  文件。
&lt;img src=&quot;/images/2015_08_06_22_43/6.png&quot; alt=&quot;rootkiter.com&quot; /&gt; &lt;br /&gt;
&lt;a href=&quot;/files/Android.txt&quot;&gt;Android.mk&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;/files/com_example_killndk_Jni.txt&quot;&gt;com_example_killndk_Jni.c&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;在android工程上配置编译选项：
&lt;img src=&quot;/images/2015_08_06_22_43/7.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;左侧选择Builders，右侧选择New按钮，添加编译选项：&lt;br /&gt;
填写编译配置信息：&lt;br /&gt;
&lt;img src=&quot;/images/2015_08_06_22_43/8.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;这一页主要是填写与cygwin相关的绝对路径，以及工程的绝对路径，各位需要根据实际情况予以调整。&lt;br /&gt;
&lt;img src=&quot;/images/2015_08_06_22_43/9.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;C代码被编译后会放在libs目录下。&lt;br /&gt;
&lt;img src=&quot;/images/2015_08_06_22_43/10.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;C的相关代码放在jni目录下。  &lt;br /&gt;
配置完成后，每次jni文件夹发生变化，就会自动执行makefile命令了。&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;现在可以通过Jni定义的接口来访问C语言函数了：&lt;br /&gt;
&lt;img src=&quot;/images/2015_08_06_22_43/11.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;看看执行效果吧，还算不错：
&lt;img src=&quot;/images/2015_08_06_22_43/12.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;编写内嵌汇编&quot;&gt;编写内嵌汇编&lt;/h2&gt;

&lt;p&gt;由于NDK的C代码是通过gcc编译而成的，则必然支持内嵌汇编式的编程，并通过汇编方式实现C语言无法实现的功能，下面就介绍一下通过NDK如何进行内嵌汇编式编程。&lt;/p&gt;

&lt;p&gt;注意：gcc本身的去除冗余效率是非常高的，除极特殊原因不建议使用内嵌汇编式编程。&lt;/p&gt;

&lt;p&gt;内嵌汇编式编程同其它NDK编程基本类似，需要注意的是Arm的函数调用方式采用快速调用的方法，形参均通过寄存器进行直接传递，在编写内嵌汇编程序时要注意形参同寄存器的对应关系。下面给出“参数加一函数”的内嵌汇编实现。
&lt;img src=&quot;/images/2015_08_06_22_43/13.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;可以看出，key的值被自动关联为R2寄存器，且返回值也被自动的关联为R0寄存器。&lt;/p&gt;

&lt;p&gt;如果想要关注更多关于gcc for arm下的内嵌汇编编程可以参照这篇文章&lt;a href=&quot;www.ethernut.de/en/documents/arm-inline-asm.html&quot;&gt;传送门&lt;/a&gt;。&lt;/p&gt;

&lt;h2 id=&quot;结束&quot;&gt;结束&lt;/h2&gt;
&lt;p&gt;13年的学习笔记，现在看就有些过时了。知识更新真是太快了。。。当时高考报志愿，怎么就偏偏选了这么一个专业呢。。。&lt;/p&gt;

</content>
</entry>

<entry>
	<title>ARM指令结构和crack思路</title>
        <link href="/2015/08/05/ARM%E6%8C%87%E4%BB%A4%E7%BB%93%E6%9E%84%E5%92%8Ccrack%E6%80%9D%E8%B7%AF.html"/>
	<updated>2015-08-05T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/08/05/ARM指令结构和crack思路</id>
	<content type="html">&lt;h2 id=&quot;写在开头&quot;&gt;写在开头&lt;/h2&gt;
&lt;p&gt;很久之前写了一些围绕ANDROID和ARM的学习笔记，前段时间已经整理过&lt;a href=&quot;/2015/07/04/ARM下的ShellCode.html&quot;&gt;一篇&lt;/a&gt;，这是另一篇。这里记录了一些围绕着ARM指令系统的知识。&lt;/p&gt;

&lt;p&gt;ARM指令系统是由ARM公司定义的一类芯片的指令规则，这种芯片普遍应用于各种便携式设备，以及智能终端中，具有低功耗，便于开发等特点。&lt;/p&gt;

&lt;h3 id=&quot;arm指令系统同x86指令的区别&quot;&gt;ARM指令系统同X86指令的区别&lt;/h3&gt;
&lt;p&gt;从指令长度上看，ARM指令属于定长指令系统，每一条指令都为固定的4字节长度，而X86却是变长，长度取决于指令本身的复杂程度。&lt;/p&gt;

&lt;p&gt;从CPU架构上看，ARM指令系统拥有着更多的寄存器供开发者使用(31个通用寄存器和6个状态寄存器)，与之相对的X86寄存器数量便少的可怜了，这一问题也在X64指令中得到了很大程度大缓解。&lt;/p&gt;

&lt;p&gt;以上两点仅是比较明显的区别，也是ARM同X86相比更优秀的地方，如果想要了解更详细的区别可以通过网络自行检索，这里就不细致描述了。&lt;/p&gt;

&lt;h3 id=&quot;arm指令格式介绍&quot;&gt;Arm指令格式介绍&lt;/h3&gt;
&lt;p&gt;前面提到：ARM 指令是定长指令，长度为4个字节（32位二进制位），这样做的好处之一是便于CPU寻址，而另一个好处就是在指令定义时，可以人为固定一些特殊的标志位，用于确定指令的执行规则。ARM指令的一般编码形式如下：
&lt;img src=&quot;/images/2015_08_05_22_34/1.jpg&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;
其中：  
&amp;nbsp;&amp;nbsp;cond 指令执行的条件码；  
&amp;nbsp;&amp;nbsp;opcode 指令操作编码    
&amp;nbsp;&amp;nbsp;S 决定指令的操作是否影响CPSR（状态寄存器类似于X86中的flag寄存器）的值  
&amp;nbsp;&amp;nbsp;Rd   目标寄存器编码（通过二进制序列描述各种寄存器）  
&amp;nbsp;&amp;nbsp;Rn 包含第一个操作数的寄存器编码。  
&amp;nbsp;&amp;nbsp;Shifter_operand  表示第二个操作数  
随后规定了一条ARM指令语法模版：  
&amp;nbsp;&amp;nbsp;\&lt;opcode&gt;{\&lt;cond&gt;}{S}  \&lt;Rd&gt;,\&lt;Rn&gt;,&lt;shifter_operand&gt;  
&amp;lt;/code&amp;gt;&lt;/shifter_operand&gt;&lt;/Rn&gt;&lt;/Rd&gt;&lt;/cond&gt;&lt;/opcode&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;通过上面的描述不难发现，在指令序列中有一个名称为cond的片段，是X86指令序列中所没有的，该序列决定了当前指令是否会被执行，换句话说，通过修改这个字段，就可以实现程序逻辑的修改。&lt;/p&gt;

&lt;h3 id=&quot;cond片段的含义&quot;&gt;cond片段的含义&lt;/h3&gt;
&lt;h4 id=&quot;影响程序执行流程的标志&quot;&gt;影响程序执行流程的标志&lt;/h4&gt;
&lt;p&gt;从X86的汇编指令中我们可以得知，指令执行过程中会出现如下几种情况：&lt;br /&gt;
  &lt;em&gt;1.指令执行结果为“0”&lt;/em&gt;&lt;br /&gt;
  &lt;em&gt;2.指令执行结果出现溢出&lt;/em&gt;&lt;br /&gt;
  &lt;em&gt;3.指令执行结果为负&lt;/em&gt;&lt;br /&gt;
  &lt;em&gt;4.两个操作数的大小判别&lt;/em&gt;&lt;br /&gt;
这些情况将会决定后续程序的执行流程，在Flag寄存器中会找到它们的身影。相同的情况ARM指令系统同样也考虑到了，并且将这些情况通过CPSR寄存器（类似X86中的FLAG寄存器）中进行存储，并为它们命名为：Z、V、N、C 四个标志位。CPU通过访问CPSR寄存器的状态便可以确定程序的执行流程。&lt;/p&gt;

&lt;h4 id=&quot;条件码以及助记符的对应关系&quot;&gt;条件码以及助记符的对应关系&lt;/h4&gt;
&lt;p&gt;通过cond片段的条件码，可以对CPSR寄存器进行相应的访问，为了便于记忆，特规定了一些助记符，它们之间的对应关系可以参照下图：
&lt;img src=&quot;/images/2015_08_05_22_34/2.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;如何使用cond片段&quot;&gt;如何使用cond片段&lt;/h4&gt;
&lt;p&gt;到目前为止，ARM指令系统基本已经熟悉了，可以进行一些破解的思索了，从crackme的游戏规则可以知道：crackme其实就是让一段指令片段在“执行”同“不执行”之间转换，从而达到破解的目的。&lt;/p&gt;

&lt;p&gt;在X86中“爆破”通常都是通过修改jmp，cmp的操作数、或Flag标志位，来crack程序的。这些方法同样适用于ARM平台，然而通过以上对于cond片段的了解不难发现：&lt;br /&gt;
如果修改了cond片段的值同样也能够达到crack的目的，只需修改一位二进制位即可完成BNE到BEQ的转化，修改四位二进制位即可让一条指令失效，或让其无条件执行，可以说，手握“条件码同助记符对应表”即可决定ARM程序中每一条指令的生死。&lt;/p&gt;

&lt;h3 id=&quot;通过crackme来验证cond片段的功效&quot;&gt;通过crackme来验证cond片段的功效&lt;/h3&gt;
&lt;h4 id=&quot;如何获得crackme&quot;&gt;如何获得crackme&lt;/h4&gt;
&lt;p&gt;从各大破解论坛游走一圈之后，并没有找到 ARM 版的crackme，原因大概在于大牛们不屑于 ARM 平台的破解尝试，也可能是ARM平台本来就没有什么值得破解的东西。好在以前编写过 windows 的 crackme ，既然没有那么就自己写一个吧，随便弄一个弱智的功能测试一下修改cond的效果。ARM下的编程语言，除了特定的汇编语言、C语言以外，似乎没有发现其他的嵌入式原生开发的语言，既然我喜欢C语言那么就用C语言实现一个傻瓜式的crackme吧。&lt;/p&gt;

&lt;h4 id=&quot;crackme的构思&quot;&gt;Crackme的构思&lt;/h4&gt;
&lt;p&gt;既然已经定义为“傻瓜式”的crackme了，那就自然要有一个傻瓜式的规则，提示用户输入一个字符，如果输入的是‘a’则提示crack成功，否则提示失败。
具体的C实现代码如下所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_05_22_34/3.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;br /&gt;
代码编写完毕利用交叉编译器生成arm平台对应的二进制可执行文件。
运行结果如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_05_22_34/4.jpg&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;效果还不错，现在不输入‘a’是不会提示OK的了。下面的目标就是：输入除‘a’以外的其他key都会提示“OK：You crack me now !”&lt;/p&gt;

&lt;h3 id=&quot;开始crack&quot;&gt;开始Crack&lt;/h3&gt;
&lt;h4 id=&quot;破解准备&quot;&gt;破解准备&lt;/h4&gt;
&lt;p&gt;Crack必须的工具有两个，一款好用的调试器，和一个16进制文件编辑器，由于crackme并不复杂，IDA 61 +  C32Asm足以。
首先用IDA61打开crackme，并进行简单的分析，如下图所示：
&lt;img src=&quot;/images/2015_08_05_22_34/5.jpg&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;简单看一下都是比较基础的ARM指令，没有什么难度，关键跳转一目了然：“BNE loc_8228”，只需要将BNE改为BEQ，或者B，即可跳转到输出“OK”的分支。既然如此马上动手。&lt;/p&gt;

&lt;h4 id=&quot;找到cond片段&quot;&gt;找到cond片段&lt;/h4&gt;
&lt;p&gt;通过IDA的HEX标签查看可以得知：BNE所对应的指令片段为：02 00 00 1A，如下图所示：
&lt;img src=&quot;/images/2015_08_05_22_34/6.jpg&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;br /&gt;
由于ARM指令在文件中为字节倒序排列，所以其中1A 的1  便是cond片段的值，将其修改为：0A 即可将BNE指令变为BEQ，貌似IDA不支持修改源文件，那么就在C32Asm中修改吧。&lt;/p&gt;

&lt;h4 id=&quot;用c32asm进行代码变更&quot;&gt;用C32Asm进行代码变更&lt;/h4&gt;
&lt;p&gt;通过C32Asm的16进制查找功能定位到该序列处，并将1A修改为0A（BNE-&amp;gt; BEQ）然后保存修改结果。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_05_22_34/7.jpg&quot; alt=&quot;rootkiter.com&quot; /&gt; &lt;br /&gt;
最后用IDA载入查看修改后的程序流程：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_08_05_22_34/8.jpg&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;br /&gt;
可以发现，该指令已经变为预期的BEQ指令。
具体arm平台测试结果如下图所示：
&lt;img src=&quot;/images/2015_08_05_22_34/9.jpg&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;可以发现，输入‘a’同输入‘b’得到的返回值发生了交换，证明程序的流程被有效的修改了，crack成功，现在就可以根据自己的要求修改指令中的cond片段从而达到crack的目的了。&lt;/p&gt;

&lt;h2 id=&quot;结束&quot;&gt;结束&lt;/h2&gt;
&lt;p&gt;以上介绍了ARM平台下通过修改cond条件码的方法达到crack程序的目的，通过这种方式可以任意的修改程序执行流程，所需要的仅是“IDA + 16进制编辑器 + 条件码助记符对应表”的组合，可以说难度并不是很大。&lt;/p&gt;

</content>
</entry>

<entry>
	<title>Jekyll页面的索引实现</title>
        <link href="/2015/07/14/Jekyll%E9%A1%B5%E9%9D%A2%E7%9A%84%E7%B4%A2%E5%BC%95%E5%AE%9E%E7%8E%B0.html"/>
	<updated>2015-07-14T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/07/14/Jekyll页面的索引实现</id>
	<content type="html">&lt;h2 id=&quot;起因&quot;&gt;起因&lt;/h2&gt;
&lt;p&gt;一直觉得博客还缺些什么，思考过后，发现博客还缺一个快速定位文章的功能，于是实现了&lt;a href=&quot;/goto_tags.html&quot;&gt;这样一个页面&lt;/a&gt;，在这个页面里，可以通过标签索引来快速定位文章位置。这个页面的实现既用到了 Jekyll 的特性，也用到了 HTML 标签的一些特性。&lt;/p&gt;

&lt;h3 id=&quot;前人做过的尝试&quot;&gt;前人做过的尝试&lt;/h3&gt;
&lt;p&gt;在Jekyll下实现文章定位，网上有很多人做过尝试，有人通过js代码实现，比如这篇《&lt;a href=&quot;http://www.tuicool.com/articles/6vA36f6&quot;&gt;Jekyll站内搜索：jekyll-lunr-js-search使用说明&lt;/a&gt;》。也有人通过添加 Ruby 插件来实现，比如这篇《&lt;a href=&quot;http://codemacro.com/2012/07/18/add-category-list-to-octopress/&quot;&gt;为octopress添加分类(category)列表&lt;/a&gt;》。这些方法，都很好，而且很简单，但我只想要一个非常基础的文章定位或分类功能。这些方法都显得复杂了。&lt;/p&gt;

&lt;h3 id=&quot;思考后的解决方案&quot;&gt;思考后的解决方案&lt;/h3&gt;
&lt;h4 id=&quot;1-锚标签&quot;&gt;1. 锚标签&lt;/h4&gt;

&lt;p&gt;浏览器实现了一个页面内快速跳转的方法，通过配置某些标签的 name 属性，即可在页面中进行插桩，此时，在浏览器地址栏使用 “#” 字符，即可快速跳到相应的标签。相关的知识细节可以参考这两篇文章
《&lt;a href=&quot;http://www.w3school.com.cn/tags/att_a_name.asp&quot;&gt;HTML &amp;lt;a&amp;gt; 标签的 name 属性&lt;/a&gt;》和
《&lt;a href=&quot;http://blog.csdn.net/qq1712088151/article/details/7402019&quot;&gt;锚标签和href属性&lt;/a&gt;》。&lt;/p&gt;

&lt;h4 id=&quot;2-jekyll-实现&quot;&gt;2. Jekyll 实现&lt;/h4&gt;
&lt;p&gt;Jekyll的文章可以支持tags来给文章打标签。一篇文章可以有具多个标签，格式如下：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;-–&lt;br /&gt;
layout: xxxxx&lt;br /&gt;
title : xxxxxxxxxx&lt;br /&gt;
tags  : [ tag1 , tag2 ]&lt;br /&gt;
-–&lt;/p&gt;

&lt;/blockquote&gt;

&lt;p&gt;由于 Jekyll 的特性，我们可以通过 site.tags 来访问这些标签，这也是一种常见的Jekyll文章索引方法，关于这一特性的具体细节可以参考《&lt;a href=&quot;http://havee.me/internet/2013-11/jekyll-liquid-designers.html&quot;&gt;Jekyll 扩展的 Liquid 设计&lt;/a&gt;》，随后我在主页下方添加了如下代码：&lt;br /&gt;
&lt;img src=&quot;/images/2015_07_14_21_13/4.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;标签能够自动统计了。
&lt;img src=&quot;/images/2015_07_14_21_13/1.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;3-标签分类展示页&quot;&gt;3. 标签分类展示页&lt;/h4&gt;
&lt;p&gt;随后我们可以继续创建一个单独的标签分类页，用来管理博客的所有文章。核心代码如下：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_07_14_21_13/3.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;可以看到在这个具有分类功能的页面中，我在每个分类前加了一个具有name属性的a标签，进行锚定。此时我们就可以通过 ’＃‘ 来实现页面内定位跳转。
于是&lt;a href=&quot;/goto_tags.html&quot;&gt;这样的页面&lt;/a&gt;就实现了。
&lt;img src=&quot;/images/2015_07_14_21_13/2.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;结束&quot;&gt;结束&lt;/h2&gt;
&lt;p&gt;通过这个方法，就可以实现文章的分类以及索引定位了。用起来感觉还挺方便的。&lt;/p&gt;

</content>
</entry>

<entry>
	<title>《一席》中的好故事</title>
        <link href="/2015/07/05/%E4%B8%80%E5%B8%AD-%E4%B8%AD%E7%9A%84%E5%A5%BD%E6%95%85%E4%BA%8B.html"/>
	<updated>2015-07-05T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/07/05/《一席》中的好故事</id>
	<content type="html">&lt;h2 id=&quot;关于一席&quot;&gt;关于《一席》&lt;/h2&gt;
&lt;p&gt;最近在听《一席》这个节目，用了大概一个月时间把每期节目过了一遍，这个栏目原本是参照《TED》来做，但现在看来这里水分确实很大，很多人都是上来推荐自己的产品，或者上这里讲些不切实际的东西，企盼吸引到投资。在这一个月听了上百期左右后找到了几个有趣的议题，下面依次介绍下（文中有视频地址）。&lt;/p&gt;

&lt;h3 id=&quot;当梦想成为地址王丹&quot;&gt;当梦想成为地址－王丹&lt;/h3&gt;

&lt;p&gt;讲者是个丁克家庭，夫妻两人在荒郊野岭盖了一栋房子，吸引外来的人来住讲自己的故事。而这个议题是要介绍整个过程，包括如何租土地，如何和房东博弈，如何找些乡里人盖房子，如何同来住的客人互动。很有趣的议题。&lt;/p&gt;

&lt;p&gt;蒲松龄开个茶馆，写了一本《聊斋志异》，而300年后王丹自己造了个房子，可能也能做出相似的事吧。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_07_05_14_17/1.jpg&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_07_05_14_17/1_1.jpg&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_07_05_14_17/1_2.jpg&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_07_05_14_17/1_3.jpg&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://v.youku.com/v_show/id_XODUwMDI0MTEy.html?from=y1.2-2.4.42&quot;&gt;—&amp;gt;视频地址&amp;lt;—&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;裂变式创业宗毅&quot;&gt;裂变式创业－宗毅&lt;/h3&gt;
&lt;p&gt;作为打通中国南北充电之路的第一人。他讲了很多好玩的内部创业思路，独创的内部集资裂变式创业思路，孵化了很多很有潜质的内部创业项目。值得很多大公司借鉴。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_07_05_14_17/2.jpg&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_07_05_14_17/2_1.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://v.youku.com/v_show/id_XODQ0MjYzMjg0.html&quot;&gt;—&amp;gt;视频地址&amp;lt;—&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;感谢你给我机会上场方励&quot;&gt;感谢你给我机会上场－方励&lt;/h3&gt;
&lt;p&gt;自费出资帮国家打捞“辽宁大连5.7空难的黑匣子”，同时又是国内很多著名电影的制片人，这些华丽的光环背后，他还是北京劳雷影视文化有限责任公司的总裁，这个公司是“世界上最大的集地球物理仪器开发与销售为一体的地球物理仪器公司”，可以说这家伙是个彻彻底底的牛人，用他自己的话说：“自己这一辈子，真的很成功，很高产，他这一辈子完成了别人十辈子的事。”&lt;br /&gt;
在演讲中，他有个更有趣的观点：人赚钱是为了幸福生活，或未来的幸福生活，但如果为了赚钱而去做不快乐／不幸福的事，那么你就输在了起跑线上。&lt;br /&gt;
另一个有趣的观点：惜命的方式，不是用来养生，而是用来折腾。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_07_05_14_17/3.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://v.youku.com/v_show/id_XNzg2MDQyNzYw.html&quot;&gt;—&amp;gt;视频地址&amp;lt;—&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;创业没有美感罗军&quot;&gt;创业没有美感－罗军&lt;/h3&gt;
&lt;p&gt;这家伙讲了自己的两次创业历程，起初还被人看成骗子，后来终于把公司干了起来。按他的说法，旁观者希望看到的故事是有传奇经历的，然而创业者自己知道，创业是件很苦的事，毫无美感可言。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_07_05_14_17/4.jpg&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://v.youku.com/v_show/id_XNzYyODM5OTEy.html&quot;&gt;—&amp;gt;视频地址&amp;lt;—&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;结束&quot;&gt;结束&lt;/h2&gt;
&lt;p&gt;这些人都很棒，他们做了一些超越常理的事情，自己在玩，别人在看，希望有一天也能和他们类似的做些有趣的事，开心地玩它一辈子。&lt;/p&gt;

</content>
</entry>

<entry>
	<title>ARM 架构下的 ShellCode</title>
        <link href="/2015/07/04/ARM%E4%B8%8B%E7%9A%84ShellCode.html"/>
	<updated>2015-07-04T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/07/04/ARM下的ShellCode</id>
	<content type="html">&lt;h2 id=&quot;引言&quot;&gt;引言&lt;/h2&gt;
&lt;p&gt;这是我很久以前写的一些学习 ANDROID＋ARM 的学习笔记，这是其中一篇，其他笔记会在适当的时候继续整理出来。先整理一下这一篇。&lt;/p&gt;

&lt;h2 id=&quot;写段-helloworld&quot;&gt;写段 HelloWorld&lt;/h2&gt;

&lt;p&gt;我编写shellcode也是从HelloWorld开始滴，下图是相应的代码截图：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_07_04_19_25/1.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;然后编译链接运行：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_07_04_19_25/2.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;shellcode-提取&quot;&gt;ShellCode 提取&lt;/h2&gt;
&lt;p&gt;到目前为止，自己编写的ARM汇编程序已经完全可执行了，下一步就是提炼16进制的shellcode，可以通过以下命令获取16进制结果：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_07_04_19_25/3.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;然后就是固定的shellcode测试代码（C语言格式），如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_07_04_19_25/4.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;recvshell-的-shellcode&quot;&gt;RecvShell 的 ShellCode&lt;/h2&gt;
&lt;p&gt;这段代码是网上有人给出的，但是给出的却是objdump-d 版本，在还原指令的时候遇到很多语法问题，也就顺便学了一些Thumb语法，收获挺大的，看下面的截图（可以通过右键菜单中查看原图来查看放大图）：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_07_04_19_25/5.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;程序编译连接后的执行结果如下所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_07_04_19_25/6.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;还是利用objdump提取16进制shellcode，得到如下代码：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_07_04_19_25/7.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;执行后运行结果如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_07_04_19_25/8.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;结束&quot;&gt;结束&lt;/h2&gt;
&lt;p&gt;这里没有高深的技术点，只是一篇学习笔记和一些很详细的操作截图。&lt;/p&gt;

</content>
</entry>

<entry>
	<title>程序员的世界</title>
        <link href="/2015/07/02/%E7%A8%8B%E5%BA%8F%E5%91%98%E7%9A%84%E4%B8%96%E7%95%8C.html"/>
	<updated>2015-07-02T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/07/02/程序员的世界</id>
	<content type="html">&lt;h2 id=&quot;好久没更新博客了今天来写点什么&quot;&gt;好久没更新博客了，今天来写点什么&lt;/h2&gt;

&lt;p&gt;在21世纪开始后，程序员成为了一种很重要的生产力。由于工作性质的特殊性，决定了他们是社会中的另类。你会发现这类人很难管理，他们经常会做出一些奇怪的举动（比如冲着电脑发呆，偶尔舒展下眉宇什么的）；甚至会为了一些工作无关的事情（通常是自然科学和谁更缺心眼这种话题）争吵很久。想要管理这些人，就要知道他们究竟是怎么想的，又是什么原因导致的。&lt;/p&gt;

&lt;h3 id=&quot;我用的语言是世界上最完美的语言&quot;&gt;我用的语言是世界上最完美的语言&lt;/h3&gt;

&lt;p&gt;如果你想在开发者论坛引发一阵辩论，这是百试不爽的开场白。&lt;/p&gt;

&lt;p&gt;程序设计语言千千万，每种语言都有其追随者。《JVM核心技术揭秘》这本书里说过一句类似这样的话：如果一门语言没有改变你思考问题的方式，那么你就没有学会这门语言。。。这就像中国人学英语一样，学会英语前，你会在头脑中用汉语描述一个想法或者观点，最终翻译为英语表达出来；而当你真正掌握英语后，你就会开始用英语思考，并直接说出来。后者的状态意味着你真的学会了英语。。。&lt;/p&gt;

&lt;p&gt;相似的问题也出现在程序设计语言中。各种语言的追随者掌握了自己的语言之后，他们的思考方式就开始顺从于这门语言，当新语言尝试进入他们的视线时，会发现新语言同他们思考问题的方式相左。于是抵触情绪就产生了，这种情绪越强烈，这批人就会越偏向自己原本掌握的语言。于是争论就发生了了，仔细观察双方的论点（java函数范式很难用／C++的指针很难用／python很难系粒度操作内存啊）也会得出类似的结论。&lt;/p&gt;

&lt;h3 id=&quot;我写出的代码才是最优秀的&quot;&gt;我写出的代码才是最优秀的&lt;/h3&gt;

&lt;p&gt;好的程序员一般都是完美主义者，他们会努力让自己的代码更符合自己的审美需求（包括代码逻辑，编程风格，功能逻辑等），为了达到这一目的，他们会尝试不同的方案去解决同一问题，并从中选出最优方案。所以无论代码解决的问题是大是小，都是他们倾注很大的心血完成的。在这样的前提下，他们自己的代码当然是最优秀的。&lt;/p&gt;

&lt;p&gt;其实一个程序员如果没有这种特质，那么他也不会成为一名优秀的程序员。整天被动的拷贝代码，而不去试图区分代码间异同的家伙，能优秀起来那就是贱了鬼了。&lt;/p&gt;

&lt;h3 id=&quot;xxx连程序都不会写凭什么领导我&quot;&gt;XXX连程序都不会写凭什么领导我&lt;/h3&gt;

&lt;p&gt;这种程序员有很多，有些人技术真的很优秀，而另一些却只是在挑毛病。事实上，程序员一般都思维活跃，不喜欢被束缚，在他们看来一切枷锁都是要解决掉的，如果有个人成天在他上面叽叽咕咕，胡乱指挥，他们自然会很讨厌。&lt;/p&gt;

&lt;p&gt;想要驯服这种程序员也很容易，第一种方法是最有效的，让自己比他技术更牛，程序员是很容易服从比他更牛的人的。第二种是比较容易做到的。那就是掌握任何一门有技术含量的手艺（能把office发挥的淋漓尽致也是一门有技术含量的手艺），他也会开始由衷佩服滴。第三种，效果最弱，但也可以一试，那就是把自己工作中很无趣的工作交给他一部分，当他有抱怨情绪时，再适当的透露自己每日为了应付这些事情多么的痛苦。取得他的理解后，再管理起来就会容易一些，这种方法效果最弱，只能解决一小部分问题。&lt;/p&gt;

&lt;h3 id=&quot;工作鄙视链&quot;&gt;工作鄙视链&lt;/h3&gt;

&lt;p&gt;程序员是一个极具创造性的职业，他们敲出代码是一个从无到有的过程，时间久了，这些人会成就感爆棚，觉得自己无所不能（创造这种事，怎么瞧都和上帝很像）。于是他们就会开始鄙视那些不动脑，甚至毫无创造性的职员。当大家都处在同一团队时，会出现协同效果不好的情况。造成这一效果的原因在于他们无法发现这些职位的创造性一面，多沟通多让他们发现这些点，会一定程度缓解这种效果。&lt;/p&gt;

&lt;h2 id=&quot;尾巴&quot;&gt;尾巴&lt;/h2&gt;
&lt;p&gt;写了这么多，却一点都不够系统，甚至可能都没有解决任何问题，但我就是想把它写在这里，总有一天从这些点会穿成一条线，最终形成一个面。到那时这些文字就不再毫无意义了。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>3D打印</title>
        <link href="/2015/06/13/3D%E6%89%93%E5%8D%B0.html"/>
	<updated>2015-06-13T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/06/13/3D打印</id>
	<content type="html">&lt;h2 id=&quot;起因&quot;&gt;起因&lt;/h2&gt;

&lt;p&gt;最近由于痴迷3D打印，所以好久没有更新文章。搞了几天发觉终于有些入门了，就来记些心得。独自happy一下。&lt;/p&gt;

&lt;p&gt;那一日，俺去“XX奶茶店”转了一圈，看到一台3D打印机，感觉有趣，于是就回家淘了一台。价位在1500元左右，算上四盘PLA的材料不到1800元。&lt;/p&gt;

&lt;p&gt;它长这样：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_06_14_00_00/quanji.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;3d打印介绍&quot;&gt;3D打印介绍&lt;/h2&gt;

&lt;p&gt;这台打印机有5个步进电机。下侧打印床可以前后移动，作为Y轴；打印头可以横向（左右）移动作为X轴；两侧的定向杆可以让打印头上下方向移动作为Z轴，每侧有一个步进电机；最后一个步进电机位于打印头上方的黑盒子中，用于控制材料流出速度（PLA材料融化后，会从打印头流出，步进电机可以控制入料的速度）。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_06_14_00_00/jichudianji.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;下侧的打印床是一块方形平台，原本是金属平板，不过由于打印过程中和塑料的收缩系数差距较大（热胀冷缩的面积变化不同），所以会出现打印过程中物体在打印台上滑动的情况，为了让打印过程中，产品始终能粘在打印台上，可以做两种操作：1.贴一层抗热膜，平衡两者的系数；2.加热打印床，以免接触面过凉导致打印件脱落。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_06_14_00_00/jiaodai.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;在打印机中有3处“限位开关”，分别位于 X／Y／Z 轴的尽头处，这是防止运动过程中偏离打印机能承受的最大范围，导致打印机毁坏。我现在也把限位开关定义为打印头的原点坐标（0，0，0）。这样做的好处是不用总去计算起始坐标的偏移量。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_06_14_00_00/xianweikaiguan.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;正式打印前，需要把打印床调平，这里所说的调平不是相对地平线调平，而是相对打印头的打印平面调平，最早不懂的时候我是肉眼调平，结果发现肉眼真的很不靠谱，在同事的指点下，我开始垫一张纸来调平（紧的时候纸会有摩擦力，有缝隙时则没有摩擦力），精度真心高了很多。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_06_14_00_00/tiaoping.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;准备就绪后，就可以开始打印了，这台打印机配套的控制软件叫做 Repetier 。本人用了一段时间下来，觉得它还是挺好用的。打印的模型描述文件为 stl 文件。Repetier可以把这种模型文件按层切片并转换为gcode代码。其中每一层就是一个打印面；不同的层就是不同的高度，也对应着打印机中的 Z 轴。切片层越薄打印的产品就越光滑，和显示屏的像素原理类似。这台打印机目前支持的层高范围为 0.1－0.4mm 。下图是层高 0.2 的大白，可以看到还是有些层次感的。如果选择 0.1mm的层高其实会好很多，但打印时间会翻倍。这个0.2的大白，我可是打了 8 个多小时呢。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_06_14_00_00/dabai.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;3D打印的观赏品一半都只注重外形，对于其内部的填充，一般不是特别看重，所以切片的时候可以选择空心填充，以缩短打印耗时。Repetier自带的切片软件叫做 Slic3r 。我只用过它的两种填充，这两种填充打出来的大白外观差距不大，但用时却差了一倍以上，后者只需打印4个小时左右，就完成了。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_06_14_00_00/qiepian1.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_06_14_00_00/qiepian2.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;打印机调好后，最让人伤神的就是模型文件了。俺不是美工出身，也没学过制图，所以模型文件是极度欠缺的。结果就是有了打印机都不知道该打点什么。在网上搜了好几天才搜到几张比较喜欢的模型图。打了一些物件，毕竟不是自己画的，打出来也不是特兴奋。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_06_14_00_00/beiz.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_06_14_00_00/hama.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_06_14_00_00/zixingche.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;为了能够让自己真的兴奋起来，我又学了几天3D制图，网上一般都推荐 3DMax／Maya 这种专业的制图软件，但都太吃计算机性能（显卡／CPU／内存什么的），找了好几天才找到一个叫 “123D Design” 的软件。这个软件很好学，网上也有&lt;a href=&quot;http://www.tuicool.com/articles/yiimquB&quot;&gt;很详细的文章&lt;/a&gt;，照着操作一次就基本会用了。目前虽然还用的不太熟练，不过基本能设计些很简单的模型了，这就是我刚打出来的一个钥匙配件喽，自我感觉很良好，哈哈。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_06_14_00_00/yaoshikou1.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_06_14_00_00/yaoshikou.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;结尾&quot;&gt;结尾&lt;/h2&gt;

&lt;p&gt;先写这些吧，一个月不更新，都有点生疏了。。。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>借力打力－smali代码窃取</title>
        <link href="/2015/05/08/%E5%80%9F%E5%8A%9B%E6%89%93%E5%8A%9B_smali%E4%BB%A3%E7%A0%81%E7%AA%83%E5%8F%96.html"/>
	<updated>2015-05-08T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/05/08/借力打力_smali代码窃取</id>
	<content type="html">&lt;h1 id=&quot;起因&quot;&gt;起因&lt;/h1&gt;
&lt;p&gt;这两天在分析一个apk样本，在分析中遇到了一个硬编码密文字符串的情况。
下图就是样本中的一个硬编码密文：&lt;br /&gt;
&lt;img src=&quot;/images/2015_05_08_20_00/2_1.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;其对应的解码函数为：&lt;br /&gt;
&lt;img src=&quot;/images/2015_05_08_20_00/2_2.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;要想确定上面的硬编码字符串经isInstallation这个函数还原后的原始结果，有三种思路：&lt;/p&gt;

&lt;p&gt;1.动态调试，调试到解密位置，看寄存器的结果。&lt;br /&gt;
2.重打包，在解密后的位置加段打日志的代码，然后重打包运行，就能在日志中看到解密结果了。&lt;br /&gt;
3.代码窃取，它的主体思路是：将解密函数（isInstallation）的smali代码抠出来，然后我们自己写一段代码去掉用这个解密函数。&lt;/p&gt;

&lt;p&gt;其实头两种是比较常见的做法，可惜这个样本有反调试机制，而且dex文件中有一段代码又是通过so文件动态还原的，导致头两种方法都很难有效。于是只能用最后一种方法。&lt;/p&gt;

&lt;h1 id=&quot;操作步骤&quot;&gt;操作步骤&lt;/h1&gt;

&lt;p&gt;首先按照isInstallation的定义格式（这里方法定义为公有或者私有不用较真，能调用就行），写一个段java框架代码，如下所示：&lt;br /&gt;
&lt;img src=&quot;/images/2015_05_08_20_00/2_3.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;保存运行，试一下这段代码是否有错误：
&lt;img src=&quot;/images/2015_05_08_20_00/2_4.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;将字节码文件（.class）转化成dex文件，命令为：&lt;/p&gt;
&lt;cmd&gt;
$ dx --dex --output=classes.dex HelloWorld.class
&lt;/cmd&gt;
&lt;p&gt;&lt;img src=&quot;/images/2015_05_08_20_00/2_5.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;再将dex文件反编译成 smali文件，命令为：&lt;/p&gt;
&lt;cmd&gt;
$ java -jar baksmali.jar -o aaa/ classes.dex
&lt;/cmd&gt;
&lt;p&gt;&lt;img src=&quot;/images/2015_05_08_20_00/2_6.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;去样本中将isInstallation反编译的代码结果覆盖到 aaa/HelloWorld.smali 的相应代码中：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_05_08_20_00/2_7.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;保存退出后，将这个smali代码编译为dex文件,命令为：&lt;/p&gt;
&lt;cmd&gt;
$ java -jar smali.jar -o classes.dex  aaa/HelloWorld.smali
&lt;/cmd&gt;
&lt;p&gt;&lt;img src=&quot;/images/2015_05_08_20_00/2_8.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;此时将生成的dex文件上传到手机等待调用。&lt;br /&gt;
&lt;img src=&quot;/images/2015_05_08_20_00/2_9.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;br /&gt;
最后将要解密的字符串传到这个程序中就能解密对应字符串了，命令如下所示：&lt;/p&gt;
&lt;cmd&gt;
\# dalvikvm -cp /data/local/HelloWorld.zip HelloWorld Q=6/pbCypY64tfHs8UFBpZfETzsr
&lt;/cmd&gt;
&lt;p&gt;&lt;img src=&quot;/images/2015_05_08_20_00/2_10.png&quot; alt=&quot;rootkiter.com&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这时输出的 “contact_id = ” 就是 ”Q=6/pbCypY64tfHs8UFBpZfETzsr” 这个字符串解密的结果了。&lt;/p&gt;

</content>
</entry>

<entry>
	<title>SSH-Socks-Tunnel</title>
        <link href="/2015/05/03/SSH_SOCKS_TUNNEL.html"/>
	<updated>2015-05-03T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/05/03/SSH_SOCKS_TUNNEL</id>
	<content type="html">&lt;h1 id=&quot;介绍&quot;&gt;介绍&lt;/h1&gt;
&lt;p&gt;SSH是Secure Shell的缩写，常见于linux主机远程管理中，它和telnet之间有一定的联系，区别在于它的网络传输数据是经过加密的，而telnet是明文传输的，如果被抓包程序抓到，可能导致敏感信息泄漏的问题。&lt;br /&gt;
那么SSH和Socks之间又有什么关系呢，看过&lt;a href=&quot;/2015/05/01/使用Socks代理服务.html&quot; title=&quot;Socks代理&quot;&gt;这篇文章&lt;/a&gt;一定会知道 Socks服务在网络管理中有很非常多的优点，除可隐身访问目标服务器外，还可以达到一种翻墙的效果。如果能让SSH服务器快速变成一个Socks代理服务器，对我们会有很多的益处（翻墙／远程内网渗透测试）。可能SSH的开发者也思考过这个问题，于是让SSH服务天生的就支持了Socks代理的功能，看来SSH还是挺可爱的嘛。&lt;/p&gt;

&lt;h1 id=&quot;windows客户端中部署socks代理&quot;&gt;Windows客户端中部署Socks代理&lt;/h1&gt;

&lt;p&gt;在windows主机上利用ssh隧道的方法有很多，我这里用到的工具为Xshell。其使用步骤如下。&lt;br /&gt;
1.配置Xshell，并通过ssh连接远程主机（测试中的ssh服务器为一台位于美国的私人VPS），如下图示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_05_03_16_36/2_1.png&quot; alt=&quot;图1&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/images/2015_05_03_16_36/2_2.png&quot; alt=&quot;图2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;2.在 文件－&amp;gt; 属性 菜单配置 socks代理的隧道&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_05_03_16_36/2_3.png&quot; alt=&quot;图3&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/images/2015_05_03_16_36/2_4.png&quot; alt=&quot;图4&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/images/2015_05_03_16_36/2_5.png&quot; alt=&quot;图5&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/images/2015_05_03_16_36/2_6.png&quot; alt=&quot;图6&quot; /&gt;&lt;/p&gt;

&lt;p&gt;此时本地的 127.0.0.1:1080 端口便有了一个刚配置好的Socks代理服务器，它将以SSH服务器为跳板来处理代理请求。&lt;br /&gt;
有了代理服务后怎么用可参考&lt;a href=&quot;/2015/05/01/使用Socks代理服务.html&quot; title=&quot;Socks代理&quot;&gt;这篇文章&lt;/a&gt;。&lt;/p&gt;

&lt;h1 id=&quot;linux-客户端中部署socks代理&quot;&gt;Linux 客户端中部署Socks代理&lt;/h1&gt;

&lt;p&gt;由于测试环境限制，这里以Ubuntu环境为例其他的 *nux 主机方法类似：
利用 ssh 的 –D 选项可以在本地开启一个监听1080端口的 socks代理服务器。于此同时还能成功连接到远程的主机，如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_05_03_16_36/2_7.png&quot; alt=&quot;图7&quot; /&gt;&lt;/p&gt;

&lt;p&gt;代理的使用，依然可参考&lt;a href=&quot;/2015/05/01/使用Socks代理服务.html&quot; title=&quot;Socks代理&quot;&gt;这篇文章&lt;/a&gt;。&lt;/p&gt;

</content>
</entry>

<entry>
	<title>使用Socks代理服务</title>
        <link href="/2015/05/01/%E4%BD%BF%E7%94%A8Socks%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1.html"/>
	<updated>2015-05-01T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/05/01/使用Socks代理服务</id>
	<content type="html">&lt;h1 id=&quot;socks代理服务介绍&quot;&gt;Socks代理服务介绍&lt;/h1&gt;
&lt;p&gt;Socks代理的工作原理可以通过一张时序图来直观展示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_05_01_16_33/2_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;从上图可以发现以下几点关键信息：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;对于访问目标来说所有的交互都只和 Socks-server 有关，Client的身份被隐藏起来了。&lt;/li&gt;
  &lt;li&gt;当Client和访问目标间无法直接通讯时，Socks-server仍然可以正常工作，这同时又是一种翻墙操作。下面是一张描述该环境的示意图：&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_05_01_16_33/2_2.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;socks代理服务的使用&quot;&gt;Socks代理服务的使用&lt;/h1&gt;

&lt;h2 id=&quot;在浏览器中使用socks代理&quot;&gt;在浏览器中使用Socks代理&lt;/h2&gt;
&lt;p&gt;这里以FireFox为例，其它浏览器均有类似功能，配置方法大家可以自行Google搜索。&lt;br /&gt;
在  菜单 -&amp;gt; 选项 -&amp;gt; 高级 -&amp;gt; 网络 -&amp;gt; 设置&lt;br /&gt;
中可以配置代理，如下图所示(代理服务器为个人的一台国外主机)： &lt;br /&gt;
&lt;img src=&quot;/images/2015_05_01_16_33/3_1_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;点击确定后，代理便生效了，下面通过访问 www.ip138.com 对比下代理前后的区别，如下所示：  &lt;br /&gt;
&lt;strong&gt;&lt;em&gt;代理前：&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_05_01_16_33/3_1_2.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;代理后：&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_05_01_16_33/3_1_3.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;全局代理的配置&quot;&gt;全局代理的配置&lt;/h2&gt;
&lt;p&gt;ProxyCap是一个可以设置全局代理的工具，它可以将主机大部分对外请求以代理方式发出，当某个工具无法配置代理时，这是一个不错的选择，使用方法如下：&lt;br /&gt;
配置代理地址：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_05_01_16_33/3_2_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;添加代理规则：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_05_01_16_33/3_2_2.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;此时代理规则建立成功，如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_05_01_16_33/3_2_3.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;用浏览器访问 www.ip138.com 测试代理结果，如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_05_01_16_33/3_2_4.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;代理协议的转化&quot;&gt;代理协议的转化&lt;/h2&gt;

&lt;p&gt;在实际使用中，ssh工具可以创建socks代理，然而总有一些工具只支持http代理，这时需要将socks代理转化为http代理方可。此处可以用 Privoxy 工具达到这一效果。&lt;/p&gt;

&lt;p&gt;1.安装并运行Privoxy，通过 Options -&amp;gt; Edit Main Configuration 打开该工具的配置文件。随意哪里插入如下两行：&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;listen-address  127.0.0.1:8118  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;forward-socks5   /               127.0.0.1:1080  .  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;PS ：forward 行尾有个点字符，缺失这个字符有时会导致代理失败。&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;这两行的意思是，将本地的 1080 端口监听的socks5协议转化为 8118端口的http代理协议。
保存退出该配置文件后，通过双次选择 Options -&amp;gt; Enable 选项，重启代理服务。&lt;/p&gt;

&lt;p&gt;2.最后，在FireFox 浏览器中配置代理协议为http，代理端口为本地 8118 端口，如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_05_01_16_33/3_3_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;3.此时访问 www.ip138.com 网站测试代理结果，如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_05_01_16_33/3_3_2.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;写在最后&quot;&gt;写在最后&lt;/h1&gt;
&lt;p&gt;本文介绍了一些和socks代理使用相关的知识。文中提到的工具都有其它替代工具，感兴趣的可以自行挖掘新工具的用法。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>端口转发和SOCKS代理</title>
        <link href="/2015/04/28/LCX_SOCKS.html"/>
	<updated>2015-04-28T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/04/28/LCX_SOCKS</id>
	<content type="html">&lt;h1 id=&quot;起因&quot;&gt;起因&lt;/h1&gt;
&lt;p&gt;在&lt;a href=&quot;/EarthWorm/&quot; title=&quot;EarthWorm&quot;&gt;蚯蚓&lt;/a&gt;构思之初，我在网上集中搜集过socks代理的知识，发现网上的很多资料都把 “Socks代理”和”socket端口转发”混为一谈。于是我决定写这样一篇文章，来辨析一下它们之间的异同。&lt;/p&gt;

&lt;h2 id=&quot;socket端口转发&quot;&gt;Socket端口转发&lt;/h2&gt;
&lt;p&gt;lcx.exe 就是一个基于 socket 套接字实现的端口转发工具，它是从 linux 下的htran 工具移植到windows平台的。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_28_22_13/2_1_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;一条正常的socket隧道必具备两端，一侧为服务端，它会监听一个端口等待客户端连接；&lt;br /&gt;
另一侧为客户端，通过传入服务端的ip和端口，才能主动连接到服务器。&lt;/p&gt;

&lt;p&gt;而端口转发工具（lcx.exe/htran)的工作原理其实是将两条 socket 隧道对接起来，打造一条可“异步双向通讯”的转接隧道。由于合法的socket隧道有两种接口分别对应服务端和客户端，根据数学中的排列组合可计算出端口转发供具有4种工作状态，它们是：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;blockquote&gt;
    &lt;p&gt;1.“客户端” 接 “客户端”&lt;br /&gt;
2.“客户端” 接 “服务端”&lt;br /&gt;
3.“服务端” 接 “客户端”&lt;br /&gt;
4.“服务端” 接 “服务端”&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;又由于端口转发为“异步双向通讯”隧道，隧道转接不分先后，所以状态2和状态3 是相同的，合并之后，便分别对应了lcx的三种工作模式，如下所示：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;blockquote&gt;
    &lt;p&gt;1、slave    “客户端” 接 “客户端” &lt;br /&gt;
2、tran     “服务端” 接 “客户端” &lt;br /&gt;
3、listen    “服务端” 接 “服务端”&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;于是便可理解lcx工具的三种命令参数的格式为何是以下的样子了：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;blockquote&gt;
    &lt;p&gt;–listen  ConnectPort  TransmitPort&lt;br /&gt;
–tran   ConnectPort  TransmitHost  TransmitPort&lt;br /&gt;
–slave  ConnectHost  ConnectPort  TransmitHost  TransmitPort&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;socks代理&quot;&gt;Socks代理&lt;/h2&gt;
&lt;p&gt;Socks 代理从名字中的“代理”二字就可以了解它的功能核心：那就是帮他人完成socket访问网络。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_28_22_13/2_2_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;有过翻墙经历的同学大概知道浏览器（IE／Chrome／FireFox等）有设置socks代理的配置项，可用来访问网络的能力。当我们通过代理服务器访问一个网址时，socks服务器其实是起到了一个中间人的身份，他分别与两方（浏览器／被访问的网站）通讯然后将获取到的结果告知另一方。&lt;br /&gt;
在使用代理服务的过程中我们会发现，只要配置好socks代理后，就不再需要指定被访问目标，直接在浏览器的地址栏输入地址就能访问任意网站。这是由于socks代理中有一个交互协议，当我们准备访问一个网站并敲击回车时，浏览器会先发送一个被访问目标的基本信息（URL和服务端口）给socks服务端，socks服务端解析了这个信息后，会代替浏览器去访问目标网站，并将访问结果回复给浏览器端。这便是socks代理的工作原理了。&lt;br /&gt;
通过这段对socks代理的描述，可知socks代理其实可理解为一个增强版的 lcx -tran 它在服务端监听一个服务端口（ConnectPort），当有新的连接请求时会从socks协议中解析出访问目标的URL（TransmitHost）的目标端口(TransmitPort)，再开始执行lcx -tran 的具体功能。&lt;/p&gt;

&lt;h2 id=&quot;两者的异同&quot;&gt;两者的异同&lt;/h2&gt;
&lt;p&gt;1.socket端口转发无需通讯协议支持，而socks代理需要socks协议支持。  &lt;br /&gt;
2.socket端口转发有三种工作方式，而socks代理仅有一种工作方式。&lt;br /&gt;
3.如果说socks是帮他人访问网络（一对多），那么端口转发就是帮他人访问主机的某个端口（一对一）。&lt;/p&gt;

&lt;h1 id=&quot;一句话总结&quot;&gt;一句话总结：&lt;/h1&gt;
&lt;p&gt;这篇笔记从“socket端口转发”和 “socks代理” 两者的工作原理出发，介绍了两者的区别。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>构造ROP</title>
        <link href="/2015/04/24/MAKE_ROP.html"/>
	<updated>2015-04-24T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/04/24/MAKE_ROP</id>
	<content type="html">&lt;p&gt;构造一个可用的ROP可以分7步来操作：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;确定目标&lt;/li&gt;
  &lt;li&gt;针对目标实现步骤，确定需要的ROP样式&lt;/li&gt;
  &lt;li&gt;搜索模块中可用代码片段。&lt;/li&gt;
  &lt;li&gt;封装代码片段至模块&lt;/li&gt;
  &lt;li&gt;书写简单的ROP伪指令&lt;/li&gt;
  &lt;li&gt;组装代码片段&lt;/li&gt;
  &lt;li&gt;调试完成&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;###一、确定目标&lt;/p&gt;

&lt;p&gt;无论做什么都需要有明确的目标：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;已知一信息泄漏漏洞（MS13-037）可泄漏 ntdll 的基地址 @ntdll_base;&lt;/li&gt;
  &lt;li&gt;被攻击目标为 WIN7_x86 ＋ IE8 ，且 ntdll 版本号为 6.1.7601.17514。&lt;/li&gt;
  &lt;li&gt;有一任意代码执行漏洞（任意 EIP 可控漏洞均可）&lt;/li&gt;
  &lt;li&gt;求一可用的 metasploit 的漏洞利用模块。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;通过阅读&lt;a href=&quot;/2014/02/28/ROPIntroduce.html&quot; title=&quot;ROP介绍&quot;&gt;第一篇笔记&lt;/a&gt;可以得知：调用ZwProtectVirtualMemory（）可以完成关闭DEP的操作，而调用之前需要将栈状态布置为下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_24_20_33/2_1_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;此时通过RETN指令调用Zw*函数后才能将shellcode所在区域开DEP保护。所以我们的目标就是构造这样一片的堆栈结构。&lt;/p&gt;

&lt;p&gt;###二、针对目标实现步骤，确定需要的ROP样式&lt;/p&gt;

&lt;p&gt;观察目标堆栈结构可以发现，构造这样的堆栈存在以下几点困难：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;
1.ShellCode 地址由于是动态分配到堆内存中，无法固定&lt;br /&gt;
2.0x00000040   和 0x0000 0400 两个数据存在格式为%u0000的unicode坏字符，无法直接部署。
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;于是，这种栈状态存在7个双字需要在ROP中动态设置(参照上图带红点的位置)。这可能会用到以下种类的ROP代码：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;MOV [ reg ], reg  &lt;br /&gt;
//布置堆栈，操作内存，当然需要写内存指令了&lt;br /&gt;&lt;/li&gt;
  &lt;li&gt;ADD（SUB） reg,reg  &lt;br /&gt;
//计算shellcode -0c、shellcode-04这种地址的值  &lt;br /&gt;  &lt;br /&gt;
//计算MOV [reg],reg 指令中  [reg] 的值    &lt;br /&gt;&lt;/li&gt;
  &lt;li&gt;MOV  reg，ESP    &lt;br /&gt;
//这条指令是最重要的，没有它，根本无法动态定位shellcode地址  &lt;br /&gt;&lt;/li&gt;
  &lt;li&gt;NOT reg          &lt;br /&gt;
//这条指令可有可没有，用来计算0x00000040 和 0x00000400 这种值，如果没有的话，通过Add（SUB） 指令也能实现    &lt;br /&gt;&lt;/li&gt;
  &lt;li&gt;POP reg			  x
//这条指令可用于向寄存器赋值，是寄存器计算前的必要指令。  &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;在这些种指令中，实际查找时会发现除第五条指令外，其他格式的指令均难以寻找。我也是找了一个星期才凑全这5种指令格式。&lt;/p&gt;

&lt;p&gt;###三、搜索模块中可用代码片段&lt;/p&gt;

&lt;p&gt;搜索过程中搜到了很多和最终构造无关但可能有奇效的指令，详情可参考&lt;a href=&quot;/2015/04/23/GOLD_IN_THE_NTDLL.html&quot; title=&quot;NTDLL空间&quot;&gt;第二篇笔记&lt;/a&gt;。&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;MOV [ reg ], reg  &lt;br /&gt;
&lt;img src=&quot;/images/2015_04_24_20_33/2_3_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;br /&gt;
需要 12个字节的垃圾填充。&lt;/li&gt;
  &lt;li&gt;SUB reg,reg&lt;br /&gt;&lt;br /&gt;
&lt;img src=&quot;/images/2015_04_24_20_33/2_3_2.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;br /&gt;
需要 8个字节的垃圾填充。&lt;/li&gt;
  &lt;li&gt;MOV reg,ESP  &lt;br /&gt;
&lt;img src=&quot;/images/2015_04_24_20_33/2_3_3.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;br /&gt;
无需字节填充，但需要在pushad发生前构造各相关寄存器值。&lt;/li&gt;
  &lt;li&gt;NOT reg  &lt;br /&gt;
&lt;img src=&quot;/images/2015_04_24_20_33/2_3_4.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;br /&gt;
需要16字节垃圾填充&lt;/li&gt;
  &lt;li&gt;POP reg  &lt;br /&gt;
&lt;img src=&quot;/images/2015_04_24_20_33/2_3_5.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/images/2015_04_24_20_33/2_3_6.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/images/2015_04_24_20_33/2_3_7.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/images/2015_04_24_20_33/2_3_8.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;###四、封装代码片段至模块&lt;/p&gt;

&lt;p&gt;为了后期使用的方便，最好能够将个代码片段封装成ROP片段，最终ROP_chain构造时直接拷贝粘贴即可。各个指令片段封装格式如下所示：&lt;/p&gt;

&lt;p&gt;&lt;em&gt;MOV [ ecx ], eax&lt;/em&gt;&lt;br /&gt;
&lt;img src=&quot;/images/2015_04_24_20_33/2_4_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;SUB  eax,edx&lt;/em&gt;  &lt;br /&gt;
&lt;img src=&quot;/images/2015_04_24_20_33/2_4_2.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;MOV  ecx，ESP&lt;/em&gt;  &lt;br /&gt;
&lt;img src=&quot;/images/2015_04_24_20_33/2_4_3.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;MOV  eax, ESP&lt;/em&gt;  &lt;br /&gt;
&lt;img src=&quot;/images/2015_04_24_20_33/2_4_4.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;NOT eax&lt;/em&gt;        &lt;br /&gt;
&lt;img src=&quot;/images/2015_04_24_20_33/2_4_5.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;POP ecx&lt;/em&gt;      &lt;br /&gt;
&lt;img src=&quot;/images/2015_04_24_20_33/2_4_6.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;POP edx&lt;/em&gt;       &lt;br /&gt;
&lt;img src=&quot;/images/2015_04_24_20_33/2_4_8.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;###五、书写简单的ROP伪指令&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_24_20_33/2_5_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这段ROP片段 ＋ Zw* ＋ “调用栈结构” + Shellcode，就可以成功关闭DEP并运行后侧的 shellcode 了。&lt;/p&gt;

&lt;p&gt;然而在这段伪指令中发现，每次写地址需要计算两次，如果都用SUB实现，将会经常备份数据，因为eax只有一个，组织代码将会相当复杂，如果能找到其他的加法指令就会好多了。
带着这个问题，我在内存中又简单的搜索了一下，顺利找到了以下代码：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_24_20_33/2_5_2.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这处代码原本是INC ECX \  RETN 如果连续使用4次，正好能够完成ADD ecx，4的功能。至此“万事具备，只欠拼接”。&lt;/p&gt;

&lt;p&gt;###六、组装代码片段&lt;/p&gt;

&lt;p&gt;这个没什么好说的了，就是参照伪代码，把封装好的代码片段组合到一起，如下图所示：
&lt;img src=&quot;/images/2015_04_24_20_33/2_6_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;###七、调试完成&lt;/p&gt;

&lt;p&gt;在metasploit中启动运行，用IE8+Win7访问，查看是否能够成功执行shellcode，如果访问失败，可以通过设置c3断点，或在ROP中设置0x41414141进行中断，另外SUB指令执行时的EDX值，既可以在构造完成后集中计算，也可以单步跟踪时手动调节。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_24_20_33/2_7_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_24_20_33/2_7_2.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;结尾&quot;&gt;结尾：&lt;/h1&gt;

&lt;p&gt;本篇笔记记录了一个相对复杂的ROP构造过程。&lt;/p&gt;

&lt;p&gt;ROP构造是一个奇妙的过程，它和程序设计有着很多相似之处，都是需要先明确目标，然后选择伪代码描述，最终用代码组织完成。然而和普通程序设计不同的是，ROP的语法块需要在内存中去寻找，并自己定义，只有找全了各种功能的代码片段，才能完成最终的ROP_chain编写。&lt;/p&gt;

</content>
</entry>

<entry>
	<title>ntdll 空间中的金疙瘩</title>
        <link href="/2015/04/23/GOLD_IN_THE_NTDLL.html"/>
	<updated>2015-04-23T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/04/23/GOLD_IN_THE_NTDLL</id>
	<content type="html">&lt;h1 id=&quot;背景&quot;&gt;背景&lt;/h1&gt;

&lt;p&gt;通过阅读&lt;a href=&quot;/2014/02/28/ROPIntroduce.html&quot; title=&quot;ROP介绍&quot;&gt;第一篇笔记&lt;/a&gt;，可以知道，ROP构造是软件类漏洞利用中很重要的一环(为了绕过dep保护)，然而用过mona工具的童鞋应该都清楚，这个工具似乎不太好用。即使你通过mona搞定了ROP骨架的生成，有时仍然需要微调，特别是当mona结果中拥有和漏洞环境相关的坏字符时，修复ROP-chain 也成为了软件类漏洞利用的重要一环。&lt;/p&gt;

&lt;p&gt;此时这篇笔记的意义就出现了：&lt;strong&gt;&lt;em&gt;如何找到有用的ROP素材，并将存在问题的ROP-chain修复。&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;文中提到的代码素材均来自于ntdll.dll文件，其中&lt;br /&gt;
&lt;code&gt;
ntdll.dll版本号为：6.1.7601.17514  
本机Win7 启动后ntdll的偏移： 0x77880000
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;声明：&lt;br /&gt;
不同版本，得到的代码偏移可能不同。&lt;br /&gt;
至于DLL模块基地址嘛。。。那是一定不同滴。。。因为我是在Win7环境下查找的指令，看客可以通过搜索特定指令序列，或通过我给出的偏移计算出来。&lt;br /&gt;
本段将纪录，我在 ntdll.dll 中找到的各种指令，它们可以用来做四则运算，甚至用来处理内存拷贝。&lt;/p&gt;

&lt;h1 id=&quot;有趣的代码片段&quot;&gt;有趣的代码片段&lt;/h1&gt;

&lt;h2 id=&quot;xchg系列&quot;&gt;XCHG系列&lt;/h2&gt;

&lt;p&gt;这个系列的指令，在ROP构造中有奇效。ROP-chain中每个寄存器中的值都是宝贝，遗失不得。而在执行 xchg 指令时，完全不会干扰到其他寄存器的内容，他们之间真的非常般配。&lt;/p&gt;

&lt;h3 id=&quot;xchg-eaxesp&quot;&gt;xchg eax,esp&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_23_21_33/2_1_1_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这是 IE 漏洞利用中经常用到的一条控制ESP的指令。它在漏洞触发的那一刻能够将ESP从“栈指针”，改成“堆指针”，配合“堆喷射”技术完成漏洞利用。&lt;/p&gt;

&lt;h3 id=&quot;xchg-eaxedx&quot;&gt;xchg eax,edx&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_23_21_33/2_1_2_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这是一条可用来保存 eax 的指令。由于多数汇编指令都会用到eax寄存器，这条指令刚好能把当前寄存器中的数据同 edx 交换一下，用起来很方便。&lt;/p&gt;

&lt;h3 id=&quot;xchg-eaxecx&quot;&gt;xchg eax,ecx&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_23_21_33/2_1_3_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;当我想把 ECX 作为内存指针时，完全可以通过 EAX 计算出相应地址，然后放到交换到ECX中。&lt;/p&gt;

&lt;h2 id=&quot;add-系列&quot;&gt;add 系列&lt;/h2&gt;

&lt;h3 id=&quot;sub-eaxedx&quot;&gt;sub eax,edx&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_23_21_33/2_2_1_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;看到这里不明真相的群众一定会问，这明明是 sub指令，为毛划分到 add系列 中呢？&lt;br /&gt;
这是因为 sub指令 比 add指令 有效得多，如果使用ADD指令执行 eax +0x20 的操作，得到的ROP素材应该是这样的：&lt;br /&gt;
&lt;code&gt;
Address -&amp;gt; { POP EDX # RETN }  
0x00000020  
Address -&amp;gt; { ADD EAX,EDX …… }  
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;此时，这样的ROP-chain中出现了一个坏字符%u0000％u2000，这个坏字符将会非常难以去除。然而如果用 sub 指令，就可以是这样的：&lt;br /&gt;
&lt;code&gt;
Address -&amp;gt; { POP EDX # RETN }  
0xffffffe0  
Address -&amp;gt; { SUB EAX,EDX …… }  
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;坏字符被巧妙的避开了，减去一个负数 等同于 加上一个正数，初中数学绝对不白学。&lt;/p&gt;

&lt;h3 id=&quot;inc-xxx&quot;&gt;inc xxx&lt;/h3&gt;

&lt;h4 id=&quot;inc-ecx&quot;&gt;inc ecx&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_23_21_33/2_2_2_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这条指令，我是找了很久才发现的。它出现的时候，我真的眼前一亮，它意味着，我可以不用EAX来做简单的加法运算了，当我仅需要给一个数字 +4 时，我只要写四次这个地址就好了。&lt;br /&gt;
&lt;code&gt;
Address -&amp;gt; { INC ECX ,RETN  }  
Address -&amp;gt; { INC ECX ,RETN  }  
Address -&amp;gt; { INC ECX ,RETN  }  
Address -&amp;gt; { INC ECX ,RETN  }  
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;这可以节省我很多 备份数字的操作，更棒的地方在于 retn 指令没有参数，完全不需要垃圾字符填充。绝对是一条高效的 rop 指令素材。&lt;/p&gt;

&lt;h4 id=&quot;inc-eax&quot;&gt;inc eax&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_23_21_33/2_2_2_2.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这个指令素材，有两种功效，当我需要向EAX写入1时，我可以使用三条指令，ROP示例如下：&lt;br /&gt;
&lt;code&gt;
Address -&amp;gt; { XOR EAX,EAX # INC EAX # RETN }
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;而当我仅需要将 EAX + 1 时，我可以使用：&lt;br /&gt;
&lt;code&gt;
Address -&amp;gt; { INC EAX # RETN  }
&lt;/code&gt;&lt;/p&gt;

&lt;h4 id=&quot;inc-ebx&quot;&gt;inc ebx&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_23_21_33/2_2_2_3.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这条指令应该不用说了，和前面的 inc ecx 有相似之处。&lt;/p&gt;

&lt;h4 id=&quot;inc-edx&quot;&gt;inc edx&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_23_21_33/2_2_2_4.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;同上&lt;/p&gt;

&lt;h3 id=&quot;其他运算&quot;&gt;其他运算&lt;/h3&gt;

&lt;h4 id=&quot;xor-eaxecx&quot;&gt;xor eax,ecx&lt;/h4&gt;

&lt;p&gt;xor系列指令貌似都比较少，也都不够高效，需要填充很多垃圾字符：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_23_21_33/2_3_1_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;它的使用大概是这样的：&lt;br /&gt;
&lt;code&gt;
Address  -&amp;gt; { XOR EAX,ECX # POP ESI # POP EBP # RETN 8  }
0x41414141   // skip 4 for pop esi  
0x41414141   // skip 4 for pop esi  
Address  -&amp;gt; { 下一条指令 }
0x41414141   //skip  4 for retn 8
0x41414141   //skip  4 for retn 8
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;这条指令还是可以用来处理一些通常情况无法绕过的垃圾字符滴。&lt;/p&gt;

&lt;h4 id=&quot;xor-eaxedx&quot;&gt;xor eax,edx&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_23_21_33/2_3_2_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;使用方法参照 xor eax,ecx ,不过看起来似乎比那条指令更好用一些，垃圾字符填充也会少一些。&lt;/p&gt;

&lt;h4 id=&quot;idiv-ecx&quot;&gt;idiv ecx&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_23_21_33/2_3_3_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这是一个有趣的素材，它能计算除法，因为除法对寄存器的干扰实在太明显了，所以在ROP中用处也不会太大。但有一条就比没有强，没准会遇到什么样子的奇葩环境。&lt;/p&gt;

&lt;h4 id=&quot;not-eax&quot;&gt;not eax&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_23_21_33/2_3_4_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这条指令，是偶然发现的，并运用到了一次ROP构造中，非常好用，很可惜的是过于浪费空间，一句 RETN 0C 就要浪费 3个DWORD。使用方法大致如下：&lt;br /&gt;
&lt;code&gt;
Address -&amp;gt; { POP EAX # RETN}
Address -&amp;gt; { NOT EAX # POP EBP # RETN 0C }
0x41414141     // skip 4  for pop ebp
Address -&amp;gt; { 下一条指令 }
0x41414141     // skip 4  for  retn0c
0x41414141     // skip 4  for  retn0c
0x41414141     // skip 4  for  retn0c
&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&quot;赋值系列指令&quot;&gt;赋值系列指令&lt;/h2&gt;

&lt;h3 id=&quot;pop-xxx&quot;&gt;POP XXX&lt;/h3&gt;

&lt;p&gt;这系列指令大概不用讲了，都清楚，当你需要执行 MOV EAX，0x43434343 时，
直接用&lt;br /&gt;
&lt;code&gt;
Address -&amp;gt; { POP EAX # RETN }
0x43434343
&lt;/code&gt;&lt;br /&gt;
即可。
对应的4个寄存器的pop指令素材为：&lt;br /&gt;
&lt;img src=&quot;/images/2015_04_23_21_33/2_4_1_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/images/2015_04_23_21_33/2_4_1_2.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/images/2015_04_23_21_33/2_4_1_3.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/images/2015_04_23_21_33/2_4_1_4.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;寄存器间传值&quot;&gt;寄存器间传值&lt;/h3&gt;

&lt;h4 id=&quot;mov-exxexx&quot;&gt;mov eXX,eXX&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_23_21_33/2_4_2_1_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/images/2015_04_23_21_33/2_4_2_1_2.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;pushad&quot;&gt;pushad&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_23_21_33/2_4_2_2_1.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;br /&gt;
请， 先收起你的惊讶的表情… pushad 确实可以进行寄存器间赋值～～～
当你想动态定位shellcode位置时，可能会需要这样一条指令，MOV EAX，ESP，然而你找遍内存也可能搜索不到可用的素材，怎么办呢？这时，你就可以通过 PUSHAD RETN 来构造一条这样的指令。PUSHAD后堆栈的状态是这样的（如下图所示），此时再调用retn其实将会返回到EDI所指向的指令，如下图所示：&lt;br /&gt;
&lt;img src=&quot;/images/2015_04_23_21_33/2_4_2_2_2.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;br /&gt;
那么我只要让堆栈中是下面这种结构，就可以把ESP的值赋值给EAX了：&lt;br /&gt;
&lt;img src=&quot;/images/2015_04_23_21_33/2_4_2_2_3.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;br /&gt;
也就是说，调用PUSHAD前，你可以通过POP EDI、POP EBP、POP EBX、POP ECX等指令，部署各个寄存器所指向的地址，这样在调用PUSHAD RETN之后便可实现任意寄存器间的赋值了。下面是我在一次ROP构造时构造的 MOV ECX，ESP&lt;br /&gt;
&lt;img src=&quot;/images/2015_04_23_21_33/2_4_2_2_4.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;br /&gt;
这条指令很 cool 吧。
其实这条指令还可以在 PUSHAD 的 RETN 后，跳到某个API函数的地址，只要控制好各个寄存器的值，绝对能让人神清气爽！&lt;/p&gt;

&lt;h4 id=&quot;5pop指令&quot;&gt;5POP指令&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_23_21_33/2_4_2_3.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;br /&gt;
我把这条指令放在这个位置，是想说明：5POP指令和PUSHAD可以很奇妙的组合在一起，当你在PUSHAD指令前将EBP指向 5POP，那么你就能非常快速的跳出 PUSHAD 对堆栈造成的影响，顺利回到ROP_chain的空间，5POP指令同样也可以拆分使用，甚至可以在一句话完成多个MOV操作，因为这条指令中同时有POP ECX 和POP EBX两条指令。&lt;/p&gt;

&lt;h4 id=&quot;xchg-eaxedx-1&quot;&gt;xchg eax，edx？&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_23_21_33/2_4_2_4.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;br /&gt;
这段指令共有4条，全部组合在一起，就是一个通过 ecx 寄存器实现XCHG EAX，EDX，而当你使用其中的三条时，指令就变成了 MOV 【EAX：EDX】，【EDX：ECX】或者用其中的两条就变成了 MOV EDX，ECX。&lt;/p&gt;

&lt;h4 id=&quot;mov-ecxeax&quot;&gt;mov [ecx],eax&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_23_21_33/2_4_2_5.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;br /&gt;
这条指令可以实现向 ecx 指向的空间写入一个双字数据，功能很棒，当你无法通过常规方式（ROP的堆栈中存在坏字符）控制堆栈数据时，你同样可以通过这样一条指令完成前方堆栈数据的配置，以及API调用前堆栈的部署。&lt;/p&gt;

&lt;h4 id=&quot;mov-edxecx&quot;&gt;mov [edx],ecx&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/2015_04_23_21_33/2_4_2_6.png&quot; alt=&quot;图片丢失，请联系作者&quot; /&gt;&lt;br /&gt;
这片指令，也能起到写内存的作用，如果你有足够的闲心，再配合上 inc edx 这种指令进行内存计算，一定能把一整段shellcode写到一个可执行的内存片中。&lt;/p&gt;

&lt;h2 id=&quot;回顾&quot;&gt;回顾&lt;/h2&gt;
&lt;p&gt;本文介绍了ntdll中的一些有趣的指令素材，旨在扩充人们对于ROP指令素材的认识，很多人认为ROP素材能做的事情非常有限，通过这篇文章相信你就能很清楚的意识到，ROP指令也可以很艺术，其实我一直相信某些特殊组合的ROP指令素材同样也能具备“图灵完备”性质。当然了，这需要有足够的创造性能力。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;PS: 这是我两年之前写的一篇笔记，现在看这些文字，已经成为了上个世纪的东西。漏洞利用（软件类）的攻防也上升到了一个全新的阶段。现阶段软件漏洞利用让人感觉门槛更高了，DVE技术也开始要求利用者对脚本语言的JIT形态有一定了解，希望在掌握更多基础知识之后，回过头来能追上大牛们的步伐吧。&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

</content>
</entry>

<entry>
	<title>关于博客</title>
        <link href="/2015/04/06/AboutBlog.html"/>
	<updated>2015-04-06T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2015/04/06/AboutBlog</id>
	<content type="html">&lt;p&gt;距离上一篇文章已经过去了一年，这期间一直没想好如何来定位这个博客。&lt;/p&gt;

&lt;p&gt;前段时间把蚯蚓的主页弄起来，才想起是时候重新构思这个博客了。&lt;/p&gt;

&lt;p&gt;现在的我，开始决定不为了写博客而写博客，而是有选择性的写，挑有趣的东西来写，题材也不仅仅局限于技术，读过的书，追过的美剧，只要我觉得有趣，我就准备写在这里，Just For Fun，希望 linus 教主不会怪我乱用他老人家的名言。:-P&lt;/p&gt;

&lt;p&gt;为了保证质量，不准备追求更新时间。只要写了一篇就总有下一篇。&lt;/p&gt;

&lt;p&gt;看来这里将有机会，成为有史以来最不靠谱的博客了，YO-HO-HO-HO~~~。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>ROP Introduce</title>
        <link href="/2014/02/28/ROPIntroduce.html"/>
	<updated>2014-02-28T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2014/02/28/ROPIntroduce</id>
	<content type="html">&lt;h2 id=&quot;背景介绍&quot;&gt;背景介绍&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;DEP保护&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DEP 保护是缓冲区溢出攻击出现后，出现的一种防护机制，
它的核心思想就是将内存分块后，设置不同的保护标志，
令表示代码的区块拥有执行权限，而保存数据的区块仅有
读写权限，进而控制数据区域内的shellcode无法执行。&lt;/p&gt;

&lt;p&gt;下面的两幅图分别表示了数据区域内“不可执行”和“
可执行”的状态：
&lt;img src=&quot;/image/ropimage/ROP1-1.png&quot; title=&quot;ropimage/ROP1-3.png&quot; align=&quot;center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/ropimage/ROP1-2.png&quot; title=&quot;ropimage/ROP1-3.png&quot; align=&quot;center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;DEP的实现分为两种，一种为软件实现，是由各个操作系统
编译过程中引入的，在微软中叫SafeSEH。 另一种为硬件
实现，由 英特尔这种CPU硬件生产厂商固化到硬件中的，
也称作NX保护机制。&lt;/p&gt;

&lt;p&gt;单从DEP的定义可以发现，这种机制应该是能够有效抑制数据
区域内shellcode执行的。此时攻击者的面前出现了一座难以
逾越的山。&lt;/p&gt;

&lt;p&gt;要想知道如何绕过这种保护机制，请详细阅读本文下面的部分。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ret-to-lib&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DEP 保护机制出现后，攻击者几乎无法令数据段中的shellcode
直接执行，看起来“防御技术”此时占得了先机。&lt;/p&gt;

&lt;p&gt;这里插一句题外话：我觉得 Hacker 永远是这个世界上
最聪明的一群人，它们总能发现一些常人无法发现的东西。&lt;/p&gt;

&lt;p&gt;Hacker中此时出现了一位天才，他开始教育大家，既然数据区
域没有执行状态那我们就让他们只保存数据吧，反正地址也是
数据的一部分，而内存中有还有无尽的代码供我们使用，只要
我们能把某些有趣的代码片段按照一定思路拼接起来，那么数
据区域是否可执行完全和漏洞利用就完全没有关系了。&lt;/p&gt;

&lt;p&gt;下面我将开始详细阐述这位“天才 Hacker” 的“天才想法”：&lt;/p&gt;

&lt;p&gt;&lt;em&gt;一方面&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;汇编语言中有一系列非常有用的指令，我管它们叫做“RETN系列指
令”，这些指令的原始功能是当函数调用完成时，回退到上一层调
用函数，并继续下面的执行，示意图如下：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/ropimage/ROP1-3.png&quot; title=&quot;ropimage/ROP1-3.png&quot; align=&quot;center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;另一方面&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;这种DEP的保护机制，虽然安全，却令操作系统在做某些操作时受到限制，所以操作系统中又提供了一些解除DEP保护的API供软件开发人员调用，当攻击者在内存中定位到这些API并调用时，DEP保护便失去作用了。这些API一直散落于内存的某些角落，当攻击者触发它们时，就好像触发了某个密室的暗门一样，豁然开朗。&lt;/p&gt;

&lt;p&gt;当RETN指令同这些API联系在一起时，就会产生一些奇妙的化学反应，首先看一下原本缓冲区溢出的攻击模式：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/ropimage/ROP1-4.png&quot; title=&quot;ropimage/ROP1-4.png&quot; align=&quot;center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;有了DEP后的间接利用攻击的示意图：
&lt;img src=&quot;/image/ropimage/ROP1-5.png&quot; title=&quot;ropimage/ROP1-5.png&quot; align=&quot;center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;可以看到在第二种模式下，EIP的控制是通过栈中的地址，以及代码中的RETN指令共同控制的，此时栈中的数据仍然是“数据”，而执行位置却转移到了内存的代码空间，如此下来便巧妙的绕过了DEP保护。&lt;/p&gt;

&lt;p&gt;那么这种绕过技术其实是基于一个特定条件的，那就是你到某个地址一定能找到对应的包含RETN的代码片段，可以说这是当前漏洞利用方式的薄弱环节。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ASLR保护&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;通过前面的阅读，大家可能已经了解，DEP机制的弱点就是可以通过某些API调用进行关闭，进而令其失效，然而令Hacker叫绝的是，这些API的地址完全固定，只要控制好栈结构，依然可以令shellcode得到执行。于是安全人员又提出了“ASLR机制”辅助DEP，提升系统安全性。&lt;/p&gt;

&lt;p&gt;ASLR是一种内存地址随机化技术，它的核心思路是让程序执行时所调用的外部模块地址完全随机化，这种随机化令关闭DEP保护的API也随着飘忽不定，在WIN7中它的存在并不明显，而在WIN8中该技术得到了长足的发展。&lt;/p&gt;

&lt;p&gt;WIN7中的实现是每次系统启动，模块地址随机，而启动完成后，到关闭之前，这个地址一般都不会改变。然而WIN8中，每两次程序运行，加载的模块地址都会随机起来。这种随机地址带来的安全效果非常明显，攻击者几乎没有办法利用原有攻击手段完成漏洞利用（地址随机导致无法找到关闭DEP的地址，而无法关闭DEP就无法令数据块中的shellcode得到执行），所以安全人员经常戏称“ASLR+DEP”为“海尔兄弟”，下面是WIN7中启用ASLR后，ntdll在两次电脑开启时的地址：&lt;/p&gt;

&lt;p&gt;可以看到这次电脑启动 ntdll.dll模块的位置为 0x77880000
&lt;img src=&quot;/image/ropimage/ROP1-6.png&quot; aglin=&quot;center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;重启计算机后，这个模块的基地址变为0x77620000&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/ropimage/ROP1-7.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;从以上两幅截图可以看出，地址随机化带来的直观效果就是模块顺序同样发生了改变，这就如同把攻击者放到了一个内存密室中，暗门的位置随时在变化，攻击者想要找到暗门的难度无疑增大了许多。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ROP&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ASLR机制出现之后，攻击者面临着另一个严俊的挑战（我想管这个挑战叫：太行山），“ASLR”也成了他们攻击技术提升的障碍，然而所谓“道高一尺，魔高一丈”，“防御技术”总是落后于“攻击技术”出现的。&lt;/p&gt;

&lt;p&gt;对于攻击者来说“关闭DEP的API”在某个模块中的偏移地址是固定的，所以内存漏洞利用的第一步就是找到模块基地址，随后根据偏移位置找到关闭DEP的API，而“信息泄露”类漏洞能够非常出色的完成这个基址定位的功能，所以可以看到WIN7之后很多漏洞的利用都是两个漏洞组合使用的（通过信息泄露类漏洞寻找dll文件基地址，随后计算API地址，最后在代码执行类漏洞中调用API完成“关闭DEP”的操作，关闭后跳转回shellcode进行实际攻击）。 以上这种攻击思路的前半段就是“现在人们传唱的ROP”了。.&lt;/p&gt;

&lt;p&gt;下面是metasploit中某个利用模块的ROP片段截图：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/ropimage/ROP1-8.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;关于以上图片的更多技术细节，请阅读本文下面的部分获得。&lt;/p&gt;

&lt;h2 id=&quot;rop构造方法&quot;&gt;ROP构造方法&lt;/h2&gt;

&lt;p&gt;通过阅读相关文章，可以得知：在Windows中有多种绕过DEP的方式，可供ROP开发，包括但不限于以下几种：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Zw(Nt)SetInformationProcess()&lt;/li&gt;
  &lt;li&gt;VirtualProtect()&lt;/li&gt;
  &lt;li&gt;VirtualAlloc()&lt;/li&gt;
  &lt;li&gt;Zw(Nt)ProtectVirtualMemory()&lt;/li&gt;
  &lt;li&gt;利用可写可执行的内存空间绕过DEP&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;其中1、2、3、5四种绕过办法在《0Day安全（第二版）》中有详细的阐述，其中第一种在《Python灰帽子》中，还详细介绍了如何通过脚本快速实现ROP开发。那些文字都是出自真正的大牛之手,所以我就不多说了，本节将对第四种绕过方式做一定的阐述。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zw(Nt)ProtectVirtualMemory()函数&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这个函数位于ntdll模块中，有两个版本，分别是Zw* 和 Nt* ，分别对应用户态和内核态的调用实现，我个人觉得两者应该没有区别，不过鉴于当前各种EXP都是通过Zw&lt;em&gt;进行利用，我们也就没必要细究Nt&lt;/em&gt; 是否能够达到利用目的了，毕竟两者的构造环境完全相同，花费的精力也完全相同。&lt;/p&gt;

&lt;p&gt;在ROP章节的末尾我给出了一个ZwProtectVirtualMemory（）ROP的构造截图，图中的代码位于metasploit的MS13_037模块中，本意是借助HeapSpray（风水）技术控制内存，进行利用的，所以在实现过程中shellcode以及参数地址可以完全固定，为了分析的方便，我们直接观察触发后堆栈状态即可。如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/ropimage/ROP1-9.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;从上图可以看出以下3点：&lt;/p&gt;

&lt;p&gt;1.EIP目前指向的地址正好为 [ESP-4] 对应的地址0x778896c9，可以表明此时EIP正在受ESP控制阶段。且当前指令如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/ropimage/ROP1-10.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;2.所指向的栈内的结构和1.4节给出的截图完全相同，为了方便观察，我将栈内的结构转换一下，方便大家对比：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/ropimage/ROP1-11.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;3.0x0c0c0c14是常见的HeapSpray（风水）技术的遗留结果，既HeapSpray发生之前，那个位置为ROP，那个位置为shellcode是完全可控的，此处无需考虑ASLR造成的影响。&lt;/p&gt;

&lt;p&gt;通过阅读ntdll_rop 中的注释可以确定栈内各数据的含义，如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/ropimage/ROP1-12.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;把这张图用自然语言描述出来就是：在当前进程（ProcessHandler= -1）划分0x400大小的内存片段，起始地址为0x0c0c0c40，将这块内存的状态设置为0x000040，原始状态为0x41414141（这就是垃圾字符嘛，请无视），操作完成后跳转到0x0c0c0c40继续执行（1、指向ShellCode）。&lt;/p&gt;

&lt;p&gt;相信到达这里就能清楚这条ROP的实际效果了，将shellcode所在的内存区域设置为0x00000040，当我们执行完这条指令后，这段内存会变成如下图所示的状态：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/ropimage/ROP1-13.png&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;利用mona辅助构造ROP&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;目前网络中流通的ROP大部分都出自mona这个脚本，他是Immunity Sec公司开发的一个python脚本，可以辅助安全人员完成ROP的开发，原脚本仅适用于Immunity Debugger，后期开发了适用Windbg调试器的环境，看官可以参照{&lt;a herf=&quot;http://redmine.corelan.be/projects/windbglib&quot;&gt;网址&lt;/a&gt;}进行配置。此处不浪费笔墨。&lt;/p&gt;

&lt;p&gt;通过[ .load pykd.pyd ] [ !py mona rop -m ntdll.dll ]两个命令，可以实现，指定模块的ROP生成，生成时间较长，本次针对ntdll模块的ROP生成共用了近4分钟（没办法，它是虚拟了一个执行环境，然后又由Windbg调用，脚本环境下虚拟执行脚本，能快就怪了），刚开始用时候若不是我去了一趟厕所，我还以为它死掉了呢：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/ropimage/ROP1-14.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;生成结果的一个片段如下图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/image/ropimage/ROP1-15.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mona 一般会生成两段ROP，分别用3种格式展示：Ruby、Python、Javascript。似乎Mona生成的ROP都是针对VirtualProtect的，而且是从内存序列中提取该函数指针，所以在ASLR模式下并不完全适用，我推荐这个工具的原因是：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;它可以给你提供几个有效的ROP指令片段，以免你自己去找。&lt;/li&gt;
  &lt;li&gt;它可以给你一个构造ROP的思路，当然目前来看这个思路也极不靠谱。&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;有个黑阔展示过一个ROP生成工具&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;我听过一个不负责任的传说，为了大家不找我或者谣言散播者打击报复，我就必须声明：该传闻极不负责任，请大家不要相信。&lt;/p&gt;

&lt;p&gt;这个传说是这样的：有个黑阔在BlackHat上演讲，自己历时2年，开发了一个工具，并吹嘘自己的工具可以找到很多其他工具无法挖掘到的ROP指令，然后又现场展示了一下ROP生成效果，据说效果良好- -！。并在演讲的最后宣布：该工具，闭源不放。馋死他人！！&lt;/p&gt;

&lt;h2 id=&quot;回顾&quot;&gt;回顾&lt;/h2&gt;

&lt;p&gt;本文起初回顾了一下ROP技术的前世今生，力求各位对二进制漏洞有兴趣的
人能够读懂。&lt;/p&gt;

&lt;p&gt;第二部分介绍了一种ROP指令的技术细节，以及生成方法。&lt;/p&gt;
</content>
</entry>

<entry>
	<title>第一篇 博客</title>
        <link href="/2014/02/25/firstBlogTest.html"/>
	<updated>2014-02-25T00:00:00+00:00</updated>
	<id>http://rootkiter.github.io//2014/02/25/firstBlogTest</id>
	<content type="html">&lt;p&gt;&lt;em&gt;这里是普通的斜体字&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;这里可以使用-h2-的字体&quot;&gt;这里可以使用 H2 的字体&lt;/h2&gt;

&lt;p&gt;这是本博客的第一篇正文，
用于检测当前的工作状态。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;这是列表项1&lt;/li&gt; 
&lt;li&gt;这是列表项2&lt;/li&gt;
&lt;/ul&gt;

&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;1*1&lt;/th&gt;
&lt;th&gt; =1&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;2*2&lt;/th&gt;
&lt;th&gt; =4&lt;/th&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;&lt;img src=&quot;http://rootkiter.github.io/image/test.jpg&quot; title=&quot;图片测试&quot; align=&quot;center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;##参考&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://tuhaihe.com&quot;&gt;tuhaihe.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
</entry>

</feed>
