<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>小黑猪的技术博客</title>
  
  
  <link href="/atom.xml" rel="self"/>
  
  <link href="https://dark-lbp.github.io/"/>
  <updated>2018-12-11T07:54:02.862Z</updated>
  <id>https://dark-lbp.github.io/</id>
  
  <author>
    <name>dark-lbp</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>基于VxWorks的嵌入式设备固件分析方法介绍</title>
    <link href="https://dark-lbp.github.io/2018/12/11/%E5%9F%BA%E4%BA%8EVxWorks%E7%9A%84%E5%B5%8C%E5%85%A5%E5%BC%8F%E8%AE%BE%E5%A4%87%E5%9B%BA%E4%BB%B6%E5%88%86%E6%9E%90%E6%96%B9%E6%B3%95%E4%BB%8B%E7%BB%8D/"/>
    <id>https://dark-lbp.github.io/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/</id>
    <published>2018-12-11T07:39:21.000Z</published>
    <updated>2018-12-11T07:54:02.862Z</updated>
    
    <content type="html"><![CDATA[<p>VxWorks 操作系统是美国WindRiver公司于1983年设计开发的一种嵌入式实时操作系统（RTOS），它以其良好的可靠性和卓越的实时性被广泛地应用在通信、军事、航空及航天等高精尖技术领域中。2012年8月登陆的好奇号，以及近日成功降落火星的洞察号均使用了VxWorks系统。</p><p>本文将以施耐德昆腾系列PLC的NOE-711以太网模块的固件为例，讲解一下基于VxWorks操作系统的嵌入式设备固件的一些常用分析方法。</p><h2 id="固件提取"><a href="#固件提取" class="headerlink" title="固件提取"></a>固件提取</h2><p>通常我们能够通过设备厂商的官网获取到设备固件的升级包，从该升级包中将真正的固件进行提取后才能进行分析。提取固件的常用方法是使用Binwalk等二进制分析工具对固件升级包进行自动化分析，待确认升级包类型后再进行固件提取或其他操作。<a href="https://download.schneider-electric.com/files?p_enDocType=Firmware+-+Updates&amp;p_File_Name=140NOE77101+For+Non+Unity+Users+V6.4.zip&amp;p_Doc_Ref=140NOE77101+Exec+and+Release+Notes+For+Non+Unity+Users" target="_blank" rel="noopener">测试固件下载地址</a></p><p>通过Binwalk进行自动分析可以发现，NOE 771模块的升级包NOE77101.bin中内嵌了一个使用zlib压缩的文件。 </p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/01DF3092-D1C8-462D-BB5F-B719A03D2DFD.png"><p>通过调用Binwalk的-e参数进行自动提取后，Binwalk会把自动提取后的文件以偏移地址命名并存储在特定的目录中。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/3EC422B8-1491-4663-AC6E-50F7FEDC65EE.png"><p>继续使用Binwalk对提取的385文件进行分析可以确认，该文件的确是我们所需要分析的VxWorks固件，因此提取的385文件也就是我们需要分析的固件文件了。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/0599430F-C628-40A4-B44D-5CF4A834A6B3.png"><h2 id="分析固件内存加载地址"><a href="#分析固件内存加载地址" class="headerlink" title="分析固件内存加载地址"></a>分析固件内存加载地址</h2><p>为了对VxWorks系统固件进行逆向分析，我们首先必须要知道固件在内存中的加载地址。加载地址的偏差会影响到一些绝对地址的引用例如跳转函数表、字符串表的引用等。</p><p>下图是VxWorks系统在PowerPC架构下的内存分布图，如图所示VxWorks的系统固件将会被加载到一个由BSP  (Board Support Package)定义的内存地址中。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/289C5989-E619-41FE-B7B9-E00F5139721D.png"><h3 id="方法一-通过封装的二进制文件头直接识别加载地址"><a href="#方法一-通过封装的二进制文件头直接识别加载地址" class="headerlink" title="方法一  通过封装的二进制文件头直接识别加载地址"></a>方法一  通过封装的二进制文件头直接识别加载地址</h3><p>某些设备的固件会使用某种格式进行封装，比较常见的是使用ELF(executable and linkable format)格式进行封装。采用ELF格式封装后的文件头部有特定的数据位记录了该固件的加载地址，因此针对该情况我们可以直接使用greadelf等工具直接读取ELF文件头，从而直接获取到固件的加载地址，此外IDA也能直接识别ELF格式封装的VxWorks固件，无需额外处理即可进行自动化分析。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/DC2143D3-EFAB-484C-A144-1786799F6431.png"><h3 id="方法二-分析固件头部的初始化代码，寻找加载地址的特征"><a href="#方法二-分析固件头部的初始化代码，寻找加载地址的特征" class="headerlink" title="方法二 分析固件头部的初始化代码，寻找加载地址的特征"></a>方法二 分析固件头部的初始化代码，寻找加载地址的特征</h3><p>在很多情况下我们拿到的固件是没有采用ELF格式封装的，这时就需要我们通过对固件的某些特征进行分析来判断具体的加载地址。还是以施耐德的NOE 711固件为例, 在具体分析某个固件时首先我们需要知道目标设备的CPU架构，具体可以如下图所示通过<code>binwalk -A</code>指令来对固件的CPU架构进行分析，此外也可以用<code>binwalk -Y</code>指令来调用capstone反汇编引擎来进行辅助判断，不过我实际测试下来存在一些误报的情况会把NOE 711的固件识别成arm架构的。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/69C899AC-E605-49DC-990B-FFF77DD23655.png"><p>在得知目标CPU架构后就可以使用IDA加载固件并对其代码进行初步分析。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/40B72C26-5042-4434-B2F1-D4EE821AC3BB.png"><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/45622B8B-EF29-4039-A054-C6F6D3551586.png"><p>下图是默认加载后的IDA界面，仅仅分析出了极少数的函数。接下来就需要根据固件头部的这段代码来寻找加载地址的特征。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/43FF83DF-A4B4-4934-A17D-2185D4AEF99A.png"><p>在固件头部有如下图所示的一段有趣的代码，在r1和r3寄存器进行赋值后进行了跳转。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/3D813CCB-C0CC-4313-A82D-7EF180AF5618.png"><p>下图是PowerPC的寄存器用途说明，从图中可以看到R1寄存器是栈指针，而R3寄存器则是第一个参数。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/707BFBD2-8D46-498B-9D21-80AD2720D028.png"><p>现在回到我们之前看的固件头部代码处，这段代码相当于是先将栈地址设置为0x10000，将第一个参数(r3寄存器)设置为0x0，随后在栈上开辟0x10个字节的空间后跳转到当前地址+0x1cd34处执行。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/B8C21C6D-4158-4AD6-8502-FAA3315CD6CD.png"><p>根据VxWorks官网文档对对内存布局的描述，<code>Initial Stack</code>是<code>usrInit</code>函数的初始化栈。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/38D53E92-0D06-49DD-B487-0B03D8680B2F.png"><p>而<code>usrInit</code>函数则是VxWorks系统引导后运行的第一个函数，再结合之前我们分析的那段代码，可以基本确定在大部分情况下第一个跳转的地址就是<code>usrInit</code>这个函数的地址。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/770A7225-CF27-4F2E-9D76-AA1F4653474F.png"><p>随后我们再回忆一下之前看到的VxWorks PowerPC内存布局图可以发现，初始化栈的地址同时也是固件的内存加载地址，因此r1寄存器指向的0x10000就是我们所寻找的固件加载地址。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/490DB526-C1CA-4162-85A4-167D6442E536.png"><h3 id="方法三-基于bss区数据初始化代码的特征，计算加载地址"><a href="#方法三-基于bss区数据初始化代码的特征，计算加载地址" class="headerlink" title="方法三 基于bss区数据初始化代码的特征，计算加载地址"></a>方法三 基于bss区数据初始化代码的特征，计算加载地址</h3><p>另一个分析固件加载地址的常用方法是，找到bss区域的初始化代码后间接计算出固件加载地址。bss(Block Started by Symbol)区在VxWorks系统中主要用于存储一些当前未赋值的变量,在系统启动过程中VxWorks会使用<code>bzero</code>函数对bss区的数据进行清零 。</p><p>如下图所示我们可以得知VxWorks固件自身有三个section，<code>text</code>, <code>data</code>以及<code>bss</code>这三个部分共同组成了VxWorks固件.</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/BB61D8F1-9C49-4FC7-A1CE-B82BA38F111D.png"><p>从下图所示的内存布局中可以看到bss区紧跟着固件的text和data段之后，因此只要我们找到bss区清零的函数，分析出清零函数的结束位置及后将其减去固件文件的大小即可获得固件的内存加载地址。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/B40A7133-03F6-4856-A93B-4189F2D33EC4.png"><p>接下来我们再看一下VxWorks中的<code>userInit</code>函数，从下图可以看到<code>usrInit</code>除了是系统引导后执行的第一个函数外，在这个函数中还会首先对bss区的数据进行清理。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/A86742AC-61EC-4C33-9E0D-97EA07C40F99.png"><p>对<code>usrInit</code>这个函数进行查看后，可以发现其中有不少的bl跳转函数。根据<code>usrInit</code>的描述，第一个跳转的函数就是负责初始化BBS区的函数。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/69135A5F-B853-4C5E-AEFD-FD5FD1058D51.png"><p>下图是BSS初始化函数的代码，结合PowerPC的寄存器用途可知r3和r4寄存器分别是函数<code>sub_18D59C</code>的两个参数。r3的值为<code>0x339418</code>, r4的值为<code>0x490D2C - 0x339418 = 0x157914</code>相当于长度。因此我们可以得知<code>0x339418</code>就是bss区的起始地址，<code>0x490D2C</code>就是bss区的结束地址。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/9C2E5933-07ED-4F33-9ED1-E755DA18100A.png"><p>在得到bss区结束地址后，我们就可以进一步的计算出固件的加载地址，不过使用这个方法有一个前提条件就是提取出的固件文件本身是完整的，如果提取出的固件文件不完整这个方法则会失效。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/1CC20DBD-1104-4086-8386-DDA4CD467B48.png"><p>上面介绍了三种比较常用的VxWorks固件加载地址分析方法，此外还有通过焊接UART接口查看系统引导过程的串口输出等各种其他非常规手段。在分析出固件加载地址后就可以使用新的加载地址重新加载固件进行分析了</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/F1EBE538-3628-4253-AE6D-856887E1EE7A.png"><p>下图是Windows下的IDA6.8中重新加载后固件的对比图，Mac 下的IDA 在修复了加载地址后还是只能关联识别出很少的函数。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/F80DC40A-08C9-4E56-BB1C-FA4FAAF6153D.png"><h2 id="利用符号表修复函数名"><a href="#利用符号表修复函数名" class="headerlink" title="利用符号表修复函数名"></a>利用符号表修复函数名</h2><p>虽然IDA此时能够正确的识别函数及其调用关系，但依然无法自动识别出函数名，这对固件的分析工作造成了很大的阻碍。 此时可以查看固件在编译时是否编入了符号表，如固件编入了符号表那么我们就可以利用符号表中的内容来修复IDA中所显示的函数名。</p><p>通过使用binwalk可以帮助我们辅助分析VxWorks固件中是否编入了符号表，并识别出符号表在固件中的位置。如下图所示binwalk识别出的符号表地址在文件偏移<code>0x301E74</code>处。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/0B12FF9A-30C8-44A9-AECA-9FA4AE2B5232.png"><p>如下图所示，VxWorks 5系列的符号表有他独特的格式，他以16个字节为一组数据，前4个字节是0x00，之后是符号名字符串所在的内存地址，后4个字节是符号所在的内存地址，最后4个字节是符号的类型，例如0x500为函数名。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/532FF824-B3CF-43E8-9494-F63604BEFBEC.png"><p>基于符号表的特征，我们能够轻松的获取到固件中符号表的起始及结束位置。此时我们就可以使用IDA的api来修复函数名，这里将使用如下图所示的Python脚本。 </p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/4E64522F-0117-459C-BC53-9BDC1EBA2406.png"><p>完成函数名修复后的IDA界面如下图所示，通过修复符号表IDA识别出了8000多个函数。至此VxWorks系统固件的预处理工作就全部完成了，现在我们就可以根据函数名来对一些关键服务的代码进行静态分析了。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/FD071AAF-DE82-4CEF-8BE1-903EEC188099.png"><h3 id="固件分析"><a href="#固件分析" class="headerlink" title="固件分析"></a>固件分析</h3><p>在完成上述的一些预处理工作后，一个固件分析的入手点就是查看例如<code>loginUserAdd</code>等关键函数的调用关系。如下图所示<code>loginUserAdd</code>函数的用途是在登录表中添加一个用户，这个账号可以用于登录例如telnet及ftp等服务。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/BE81A670-4913-44F9-8E78-63DFEC3DFD31.png"><p>通过分析<code>loginUserAdd</code>函数的调用，可以看到在<code>usrAppInit</code>等函数中均调用了<code>loginUserAdd</code>函数。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/F722A6D5-60AC-4041-949B-981742CD9C63.png"><p>再进一步查看<code>loginUserAdd</code>函数可以发现在这个函数中所添加的用户及密码哈希。此类方法也是用于发现后门账号的有效手段之一。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/16406D19-4953-429A-845C-7E2160F4746C.png"><p>此外还可以关注某些服务的初始化函数，例如在<code>usrNetAppInit</code>函数中就可以发现许多网络服务的初始化函数调用。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/10BB50E8-5712-42A7-A4A5-6C6DC0A84DB7.png"><p>至此VxWorks固件分析的常用方法就介绍完毕了，通过使用类似的分析方法，我们也能够在基于VxWorks的其他嵌入式设备的固件中发现一些有趣的信息，下面是其中的两个例子。</p><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/55674D60-4CE7-42F1-B485-E4700BBA20B8.png"><img src="/2018/12/11/基于VxWorks的嵌入式设备固件分析方法介绍/94564149-A3DE-4707-A670-7E8A4B6E37D5.png"><h2 id="Reference"><a href="#Reference" class="headerlink" title="Reference"></a>Reference</h2><ul><li><a href="http://101.96.10.63/class.ece.iastate.edu/arun/CprE281_F05/lab/labw11a/Labw11a_Files/eabi_app.pdf" target="_blank" rel="noopener">Developing PowerPC Embedded Application Binary Interface (EABI) Compliant Programs</a></li><li><a href="http://www.vxdev.com/docs/vx55man/vxworks/ppc/powerpc.html" target="_blank" rel="noopener">Reference Materials    VxWorks for PowerPC</a></li><li><a href="http://www.vxdev.com/docs/vx55man/vxworks/ref/usrConfig.html" target="_blank" rel="noopener">usrConfig</a></li><li><a href="http://www.vxdev.com/docs/vx55man/vxworks/ref/loginLib.html#loginUserAdd" target="_blank" rel="noopener">loginLib</a></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;VxWorks 操作系统是美国WindRiver公司于1983年设计开发的一种嵌入式实时操作系统（RTOS），它以其良好的可靠性和卓越的实时性被广泛地应用在通信、军事、航空及航天等高精尖技术领域中。2012年8月登陆的好奇号，以及近日成功降落火星的洞察号均使用了VxWork
      
    
    </summary>
    
    
      <category term="IoT" scheme="https://dark-lbp.github.io/tags/IoT/"/>
    
      <category term="VxWorks" scheme="https://dark-lbp.github.io/tags/VxWorks/"/>
    
  </entry>
  
  <entry>
    <title>开源工具snmp-set-fuzzer介绍</title>
    <link href="https://dark-lbp.github.io/2018/12/11/%E5%BC%80%E6%BA%90%E5%B7%A5%E5%85%B7snmp-set-fuzzer%E4%BB%8B%E7%BB%8D/"/>
    <id>https://dark-lbp.github.io/2018/12/11/开源工具snmp-set-fuzzer介绍/</id>
    <published>2018-12-11T07:32:50.000Z</published>
    <updated>2018-12-11T07:39:01.678Z</updated>
    
    <content type="html"><![CDATA[<h2 id="什么是snmp-set-fuzzer"><a href="#什么是snmp-set-fuzzer" class="headerlink" title="什么是snmp-set fuzzer"></a>什么是snmp-set fuzzer</h2><p>snmp-set fuzzer是一个用于对目标设备的snmp可写oid节点数据进行Fuzz的小工具。项目的地址是<a href="https://github.com/dark-lbp/snmp_fuzzer" target="_blank" rel="noopener">https://github.com/dark-lbp/snmp_fuzzer</a></p><h2 id="为什么要编写snmp-set-fuzzer这个工具"><a href="#为什么要编写snmp-set-fuzzer这个工具" class="headerlink" title="为什么要编写snmp-set fuzzer这个工具"></a>为什么要编写snmp-set fuzzer这个工具</h2><ul><li>在对许多工业控制设备进行安全测试时发现大量的设备默认开启了snmp服务并支持snmp写操作，且部分设备使用了默认的snmp community值且无法修改。</li><li>希望有一个相对灵活且自动化的小工具能够对这些开放了snmp写权限的设备进行检测从而评估设备的安全性。</li></ul><h2 id="如何使用snmp-set-fuzzer"><a href="#如何使用snmp-set-fuzzer" class="headerlink" title="如何使用snmp-set fuzzer"></a>如何使用snmp-set fuzzer</h2><p>在对目标设备进行fuzzing之前我们, 我们首先需要对目标设备的可写OID节点进行扫描，<code>snmp-set fuzzer</code>会使用<code>snmp-get-next</code>请求来遍历所有的oid节点，通过将获取到的数据使用<code>snmp-get</code>请求写回目标设备并根据返回值来判断该oid节点是否可写。</p><p>下面是对某个设备进行oid节点扫描并将扫描结果进行保存的例子。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="keyword">from</span> snmp_set_fuzz <span class="keyword">import</span> *</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>target = <span class="string">'192.168.70.50'</span></span><br><span class="line"><span class="comment"># 定义用于监控设备存活的TCP端口</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>port = <span class="number">80</span></span><br><span class="line"><span class="comment"># 定义每个oid节点Fuzz的次数</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>count = <span class="number">10</span></span><br><span class="line"><span class="comment"># 获取与目标设备连接的网卡名</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>nic = conf.route.route(target)[<span class="number">0</span>]</span><br><span class="line"><span class="comment"># 创建SnmpTarget，定义各个参数</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>Target = SnmpTarget(name=<span class="string">'test'</span>, monitor_port=port, community=<span class="string">'private'</span>,</span><br><span class="line"> oid=<span class="string">'.1.3'</span>, version=<span class="number">2</span>, target=target, nic=nic, fuzz_count=count)</span><br><span class="line"><span class="comment"># 扫描目标设备的snmp oid信息</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>Target.oid_scan()</span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] Found oid :<span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.2</span><span class="number">.1</span><span class="number">.1</span><span class="number">.1</span><span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] Found oid :<span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.2</span><span class="number">.1</span><span class="number">.1</span><span class="number">.2</span><span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] Found oid :<span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.2</span><span class="number">.1</span><span class="number">.1</span><span class="number">.3</span><span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] Found oid :<span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.2</span><span class="number">.1</span><span class="number">.1</span><span class="number">.4</span><span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] <span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.2</span><span class="number">.1</span><span class="number">.1</span><span class="number">.4</span><span class="number">.0</span> <span class="keyword">is</span> writeable</span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] Found oid :<span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.2</span><span class="number">.1</span><span class="number">.1</span><span class="number">.5</span><span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] <span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.2</span><span class="number">.1</span><span class="number">.1</span><span class="number">.5</span><span class="number">.0</span> <span class="keyword">is</span> writeable</span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] Found oid :<span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.2</span><span class="number">.1</span><span class="number">.1</span><span class="number">.6</span><span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] <span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.2</span><span class="number">.1</span><span class="number">.1</span><span class="number">.6</span><span class="number">.0</span> <span class="keyword">is</span> writeable</span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] Found oid :<span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.2</span><span class="number">.1</span><span class="number">.1</span><span class="number">.7</span><span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] Found oid :<span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.2</span><span class="number">.1</span><span class="number">.2</span><span class="number">.1</span><span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] Found oid :<span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.2</span><span class="number">.1</span><span class="number">.2</span><span class="number">.2</span><span class="number">.1</span><span class="number">.1</span><span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] Found oid :<span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.2</span><span class="number">.1</span><span class="number">.2</span><span class="number">.2</span><span class="number">.1</span><span class="number">.2</span><span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] Found oid :<span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.2</span><span class="number">.1</span><span class="number">.2</span><span class="number">.2</span><span class="number">.1</span><span class="number">.3</span><span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] Found oid :<span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.2</span><span class="number">.1</span><span class="number">.2</span><span class="number">.2</span><span class="number">.1</span><span class="number">.4</span><span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] Found oid :<span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.2</span><span class="number">.1</span><span class="number">.2</span><span class="number">.2</span><span class="number">.1</span><span class="number">.5</span><span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] Found oid :<span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.2</span><span class="number">.1</span><span class="number">.2</span><span class="number">.2</span><span class="number">.1</span><span class="number">.6</span><span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] Found oid :<span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.2</span><span class="number">.1</span><span class="number">.2</span><span class="number">.2</span><span class="number">.1</span><span class="number">.7</span><span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] <span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.2</span><span class="number">.1</span><span class="number">.2</span><span class="number">.2</span><span class="number">.1</span><span class="number">.7</span><span class="number">.0</span> <span class="keyword">is</span> writeable</span><br><span class="line">..............</span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] <span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.4</span><span class="number">.1</span><span class="number">.95</span><span class="number">.2</span><span class="number">.3</span><span class="number">.1</span><span class="number">.1</span><span class="number">.1</span><span class="number">.1</span><span class="number">.0</span> <span class="keyword">is</span> writeable</span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] Found oid :<span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.4</span><span class="number">.1</span><span class="number">.95</span><span class="number">.2</span><span class="number">.3</span><span class="number">.1</span><span class="number">.1</span><span class="number">.1</span><span class="number">.2</span><span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] Found oid :<span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.4</span><span class="number">.1</span><span class="number">.95</span><span class="number">.2</span><span class="number">.3</span><span class="number">.1</span><span class="number">.1</span><span class="number">.1</span><span class="number">.3</span><span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] <span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.4</span><span class="number">.1</span><span class="number">.95</span><span class="number">.2</span><span class="number">.3</span><span class="number">.1</span><span class="number">.1</span><span class="number">.1</span><span class="number">.3</span><span class="number">.0</span> <span class="keyword">is</span> writeable</span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] Found oid :<span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.4</span><span class="number">.1</span><span class="number">.95</span><span class="number">.2</span><span class="number">.3</span><span class="number">.1</span><span class="number">.1</span><span class="number">.1</span><span class="number">.4</span><span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] <span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.4</span><span class="number">.1</span><span class="number">.95</span><span class="number">.2</span><span class="number">.3</span><span class="number">.1</span><span class="number">.1</span><span class="number">.1</span><span class="number">.4</span><span class="number">.0</span> <span class="keyword">is</span> writeable</span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] Found oid :<span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.4</span><span class="number">.1</span><span class="number">.95</span><span class="number">.2</span><span class="number">.4</span><span class="number">.1</span><span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] <span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.4</span><span class="number">.1</span><span class="number">.95</span><span class="number">.2</span><span class="number">.4</span><span class="number">.1</span><span class="number">.0</span> <span class="keyword">is</span> writeable</span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] Found oid :<span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.4</span><span class="number">.1</span><span class="number">.95</span><span class="number">.2</span><span class="number">.4</span><span class="number">.2</span><span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] <span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.4</span><span class="number">.1</span><span class="number">.95</span><span class="number">.2</span><span class="number">.4</span><span class="number">.2</span><span class="number">.0</span> <span class="keyword">is</span> writeable</span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] Found oid :<span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.4</span><span class="number">.1</span><span class="number">.95</span><span class="number">.2</span><span class="number">.4</span><span class="number">.3</span><span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] <span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.4</span><span class="number">.1</span><span class="number">.95</span><span class="number">.2</span><span class="number">.4</span><span class="number">.3</span><span class="number">.0</span> <span class="keyword">is</span> writeable</span><br><span class="line">[INFO    ][snmp_set_fuzz.oid_scan] End of MIB</span><br><span class="line"><span class="comment"># 保存扫描的结果</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>Target.save_scan_result()</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="comment"># This cmd will save all result to ./output folder.</span></span><br></pre></td></tr></table></figure><p><code>snmp-set fuzzer</code>也同样支持从保存的pcap数据包文件直接获取可写oid节点清单。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="keyword">from</span> snmp_set_fuzz <span class="keyword">import</span> *</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>target = <span class="string">'192.168.70.50'</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>port = <span class="number">80</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>count = <span class="number">10</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>nic = conf.route.route(target)[<span class="number">0</span>]</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>Target = SnmpTarget(name=<span class="string">'test'</span>, monitor_port=port, oid=<span class="string">'.1.3'</span>, version=<span class="number">2</span>, target=target, nic=nic, fuzz_count=count)</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="comment"># 查看前目标的可写oid清单</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>print(Target.set_packets)</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>[]</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="comment"># 调用read_test_case_from_pcap来获取可写oid节点数据</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>Target.read_test_case_from_pcap(<span class="string">'./output/192.168.70.50_snmp_set_packet_list.pcap'</span>)  </span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>print(Target.set_packets)</span><br><span class="line">&lt;<span class="number">192.168</span><span class="number">.70</span><span class="number">.50</span>_snmp_set_packet_list.pcap: TCP:<span class="number">0</span> UDP:<span class="number">37</span> ICMP:<span class="number">0</span> Other:<span class="number">0</span>&gt;</span><br></pre></td></tr></table></figure><p>在直接扫描或读取以前扫描生成的pcap文件获取到可写oid节点后，就可以使用<code>snmp-set fuzzer</code>进行fuzzing测试了。下面是执行fuzz的例子，测试过程中将基于各个可写oid节点的数据类型对写入数据进行随机变异后使用<code>snmp-set</code>请求发送给目标设备并对其反馈进行检测，当目标设备对某个写请求不进行反馈或反馈异常时，会对目标设备的存活进行检测。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="keyword">from</span> snmp_set_fuzz <span class="keyword">import</span> *</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>target = <span class="string">'192.168.70.50'</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>port = <span class="number">80</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>count = <span class="number">10</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>nic = conf.route.route(target)[<span class="number">0</span>]</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>Target = SnmpTarget(name=<span class="string">'test'</span>, monitor_port=port, oid=<span class="string">'.1.3'</span>, version=<span class="number">2</span>, target=target, nic=nic, fuzz_count=count)</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>Target.read_test_case_from_pcap(<span class="string">'./output/192.168.70.50_snmp_set_packet_list.pcap'</span>)</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>Target.fuzz()</span><br><span class="line">[INFO    ][snmp_set_fuzz.fuzz] Running test case No<span class="number">.0</span> <span class="number">0</span>/<span class="number">10</span></span><br><span class="line">[WARNING ][snmp_set_fuzz.fuzz] Target <span class="keyword">not</span> response <span class="keyword">with</span> snmp set packet <span class="keyword">in</span> packet NO<span class="number">.0</span>,TestCase No<span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.fuzz] Target <span class="keyword">is</span> still alive!</span><br><span class="line">[INFO    ][snmp_set_fuzz.fuzz] Running test case No<span class="number">.0</span> <span class="number">1</span>/<span class="number">10</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.fuzz] Running test case No<span class="number">.0</span> <span class="number">2</span>/<span class="number">10</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.fuzz] Running test case No<span class="number">.0</span> <span class="number">3</span>/<span class="number">10</span></span><br><span class="line">[WARNING ][snmp_set_fuzz.fuzz] Set failed <span class="keyword">with</span> error code: wrongLength (<span class="number">8</span>) <span class="keyword">in</span> packet NO<span class="number">.3</span>,TestCase No<span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.fuzz] Running test case No<span class="number">.0</span> <span class="number">4</span>/<span class="number">10</span></span><br><span class="line">[WARNING ][snmp_set_fuzz.fuzz] Set failed <span class="keyword">with</span> error code: wrongLength (<span class="number">8</span>) <span class="keyword">in</span> packet NO<span class="number">.4</span>,TestCase No<span class="number">.0</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.fuzz] Running test case No<span class="number">.0</span> <span class="number">5</span>/<span class="number">10</span></span><br><span class="line">[WARNING ][snmp_set_fuzz.fuzz] Set failed <span class="keyword">with</span> error code: wrongLength (<span class="number">8</span>) <span class="keyword">in</span> packet NO<span class="number">.5</span>,TestCase No<span class="number">.0</span></span><br><span class="line">........</span><br><span class="line">[INFO    ][snmp_set_fuzz.fuzz] Running test case No<span class="number">.4</span> <span class="number">4</span>/<span class="number">10</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.fuzz] Running test case No<span class="number">.4</span> <span class="number">5</span>/<span class="number">10</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.fuzz] Running test case No<span class="number">.4</span> <span class="number">6</span>/<span class="number">10</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.fuzz] Running test case No<span class="number">.4</span> <span class="number">7</span>/<span class="number">10</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.fuzz] Running test case No<span class="number">.4</span> <span class="number">8</span>/<span class="number">10</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.fuzz] Running test case No<span class="number">.4</span> <span class="number">9</span>/<span class="number">10</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.fuzz] Running test case No<span class="number">.5</span> <span class="number">0</span>/<span class="number">10</span></span><br><span class="line">[INFO    ][snmp_set_fuzz.fuzz] Running test case No<span class="number">.5</span> <span class="number">1</span>/<span class="number">10</span></span><br><span class="line">[WARNING ][snmp_set_fuzz.fuzz] Target <span class="keyword">not</span> response <span class="keyword">with</span> snmp get packet <span class="keyword">in</span> packet NO<span class="number">.1</span>,TestCase No<span class="number">.5</span></span><br><span class="line">[ERROR   ][snmp_set_fuzz.fuzz] Can<span class="string">'t Connect to Target at TCP Port: 80</span></span><br><span class="line"><span class="string">&gt;&gt;&gt; # 目标设备已崩溃</span></span><br><span class="line"><span class="string">&gt;&gt;&gt; # 调用save_fuzz_result来保存fuzz结果到./output目录</span></span><br><span class="line"><span class="string">&gt;&gt;&gt; Target.save_fuzz_result()</span></span><br></pre></td></tr></table></figure><h2 id="工控设备默认开启SNMP的危害"><a href="#工控设备默认开启SNMP的危害" class="headerlink" title="工控设备默认开启SNMP的危害"></a>工控设备默认开启SNMP的危害</h2><p>在以往的测试过程中通过<code>snmp-set fuzzer</code>发现过一些工控设备的漏洞，主要集中在对snmp写操作的数据没有进行有效的校验。例如某设备支持通过snmp写操作来修改设备网卡的mac地址，但是没有对mac地址的长度进行校验，只要传入过长或者过短的mac地址都会造成设备瘫痪。还有些设备的网卡可以通过snmp写操作来开启和禁用，这样直接就会造成设备的网络中断影响业务。此外通常厂商还会有其自定义的私有oid节点，这些节点也很可能会存在一些安全问题，导致设备出现各种预期外的异常。</p><p>在使用shodan对开启了snmp服务的控制设备进行了简单的搜索后可以发现，目前网络上还是有不少开启了snmp服务的控制设备直接暴露在互联网中，如果这些设备对snmp写操作没有进行有效控制的话，将会面临极大的安全风险。下面是暴露在互联网上的开启了snmp服务控制设备截图。</p><img src="/2018/12/11/开源工具snmp-set-fuzzer介绍/开源工具snmp-set-fuzzer介绍_pic_1.png"><img src="/2018/12/11/开源工具snmp-set-fuzzer介绍/开源工具snmp-set-fuzzer介绍_pic_2.png"><p>SNMP协议在带来方便管理的同时也引入了一些安全性上的问题，这些问题在工业控制领域显得尤为突出，大量的设备默认开启SNMP协议且使用public、private等默认community值进行验证。因此如果在实际生产环境中不需要使用到SNMP服务的话，建议还是关闭SNMP的功能，</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;什么是snmp-set-fuzzer&quot;&gt;&lt;a href=&quot;#什么是snmp-set-fuzzer&quot; class=&quot;headerlink&quot; title=&quot;什么是snmp-set fuzzer&quot;&gt;&lt;/a&gt;什么是snmp-set fuzzer&lt;/h2&gt;&lt;p&gt;snmp-s
      
    
    </summary>
    
    
      <category term="fuzz" scheme="https://dark-lbp.github.io/tags/fuzz/"/>
    
  </entry>
  
  <entry>
    <title>0x02 TP-Link wr886nv7-V1.1.0 路由器分析 - 导出BSS区辅助IDA分析</title>
    <link href="https://dark-lbp.github.io/2018/12/04/0x02-TP-Link-wr886nv7-V1-1-0-%E8%B7%AF%E7%94%B1%E5%99%A8%E5%88%86%E6%9E%90-%E5%AF%BC%E5%87%BABSS%E5%8C%BA%E8%BE%85%E5%8A%A9IDA%E5%88%86%E6%9E%90/"/>
    <id>https://dark-lbp.github.io/2018/12/04/0x02-TP-Link-wr886nv7-V1-1-0-路由器分析-导出BSS区辅助IDA分析/</id>
    <published>2018-12-04T13:36:17.000Z</published>
    <updated>2018-12-11T07:40:06.540Z</updated>
    
    <content type="html"><![CDATA[<p>在之前一篇文章中通过焊接串口调试的方式已经成功的获取到VxWorks的cmd命令行，并且能够执行一些基础的系统命令。这篇文章将会对如何使用cmd命令行工具来辅助IDA进行静态分析。</p><p>通过阅读Vxworks 5.5的mips官方文档可以找得到如下所示的一张图，图中对VxWorks在MIPS架构下的内存布局进行了描述，其中bss(Block Started by Symbol)区在VxWorks系统中主要用于存储一些当前未赋值的变量。<br><img src="/2018/12/04/0x02-TP-Link-wr886nv7-V1-1-0-路由器分析-导出BSS区辅助IDA分析/44C54E5F-6EC2-4BE4-90FE-959C1026F9DC.png"></p><p>由于bss段的数据在固件中是没有进行赋值的未初始化数据，因此我们可以尝试从路由器实际运行的内存中dump出bss段信息，并将其还原到IDA中。</p><p>为了dump bss段的信息，首先我们需要知道bss段的起始地址及大小，这部分的信息我们可以通过分析VxWorks系统的初始化代码进行实现。由于bss段存储的是未初始化的变量数据，因此在每次VxWorks系统加载过程中都会使用<code>bzero</code>函数对bss段的数据使用进行一次清除。</p><img src="/2018/12/04/0x02-TP-Link-wr886nv7-V1-1-0-路由器分析-导出BSS区辅助IDA分析/3788213E-8D00-42DB-85F9-3CCA0DAF740C.png"><p>在IDA中我们可以通过追踪VxWorks的启动函数<code>usrInit</code>-&gt;<code>sysStart</code>来找到这段初始化bss段的代码。</p><img src="/2018/12/04/0x02-TP-Link-wr886nv7-V1-1-0-路由器分析-导出BSS区辅助IDA分析/08119F29-4F8C-4F5D-BE1D-ECE84341DAA8.png"><p>此时我们就可以使用串口通讯dump处<code>0x8024BB00</code>至<code>0x802A07B0</code>的数据了。</p><img src="/2018/12/04/0x02-TP-Link-wr886nv7-V1-1-0-路由器分析-导出BSS区辅助IDA分析/619684F6-6DD6-48AD-84B5-3D1B4FC63DD3.png"><p>dump完成后即可编写idapython脚本还原bss数据，还原代码如下。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> idc</span><br><span class="line"><span class="keyword">import</span> idaapi</span><br><span class="line"><span class="keyword">import</span> idautils</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">bss_dump_path = <span class="string">'path of bss_dump'</span></span><br><span class="line">bss_dump_data = open(bss_dump_path, <span class="string">'rb'</span>).read()</span><br><span class="line">bss_start_address = <span class="number">0x8024BB00</span></span><br><span class="line">bss_end_address = <span class="number">0x802A07B0</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Add segment</span></span><br><span class="line">idc.AddSeg(bss_start_address, bss_end_address, <span class="number">0</span>, <span class="number">1</span>, <span class="number">4</span>, <span class="number">0</span>)</span><br><span class="line">idc.RenameSeg(bss_start_address, <span class="string">".bss"</span>)</span><br><span class="line">idc.SetSegClass(bss_start_address, <span class="string">".bss"</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> offset <span class="keyword">in</span> range(len(bss_dump_data)):</span><br><span class="line">    idc.PatchByte(bss_start_address + offset, ord(bss_dump_data[offset]))</span><br></pre></td></tr></table></figure><p>还原bss区的变量数据对使用IDA进行静态分析还是有很大的帮助的，例如在还原bss段数据前所有对bss段的引用数据都为空无法辅助判断该地址的用途。</p><img src="/2018/12/04/0x02-TP-Link-wr886nv7-V1-1-0-路由器分析-导出BSS区辅助IDA分析/6A132972-80F7-46B2-81A8-6A3DE389E347.png"><p>在还原bss段数据后，bss段的变量引用就可以通过变量的数据来辅助判断程序的处理逻辑。</p><img src="/2018/12/04/0x02-TP-Link-wr886nv7-V1-1-0-路由器分析-导出BSS区辅助IDA分析/623050AD-D659-4302-989F-CC3E9B5F1151.png"><p>同样的有些函数的地址是保存在BSS区的，如果我们不修复BSS区的数据那么在分析例如下图所示的一些函数时将会造成不少的困难。</p><img src="/2018/12/04/0x02-TP-Link-wr886nv7-V1-1-0-路由器分析-导出BSS区辅助IDA分析/0B980F1A-76F1-4E45-BE5B-C388DB78133C.png"><p>通过导出路由器的BSS区数据可以更方便的辅助我们使用IDA等工具对设备的固件进行静态分析，此外如果遇到了未导出的地址也可以通过串口读取对应地址段的数据在IDA中使用类似的方法进行扩充。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;在之前一篇文章中通过焊接串口调试的方式已经成功的获取到VxWorks的cmd命令行，并且能够执行一些基础的系统命令。这篇文章将会对如何使用cmd命令行工具来辅助IDA进行静态分析。&lt;/p&gt;
&lt;p&gt;通过阅读Vxworks 5.5的mips官方文档可以找得到如下所示的一张图，图
      
    
    </summary>
    
    
      <category term="IoT" scheme="https://dark-lbp.github.io/tags/IoT/"/>
    
      <category term="VxWorks" scheme="https://dark-lbp.github.io/tags/VxWorks/"/>
    
  </entry>
  
  <entry>
    <title>0x01 TP-Link wr886nv7-V1.1.0 路由器分析 - VxWorks cmd命令行获取及使用方法</title>
    <link href="https://dark-lbp.github.io/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-%E8%B7%AF%E7%94%B1%E5%99%A8%E5%88%86%E6%9E%90-VxWorks-cmd%E5%91%BD%E4%BB%A4%E8%A1%8C%E8%8E%B7%E5%8F%96%E5%8F%8A%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95/"/>
    <id>https://dark-lbp.github.io/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/</id>
    <published>2018-11-30T01:34:57.000Z</published>
    <updated>2018-12-11T07:40:00.469Z</updated>
    
    <content type="html"><![CDATA[<p>在之前一篇文章中对TP-Link wr886nv7 固件进行初步分析后，下一步则是尝试寻找主板上的串口调试接口从而进一步的获取引导过程中的输出信息或是进一步得到登录命令行。</p><h2 id="焊接串口调试"><a href="#焊接串口调试" class="headerlink" title="焊接串口调试"></a>焊接串口调试</h2><p>在主板上焊接引脚后，可以通过使用万用表测量等方法确定GND、TX、RX等接口，随后即可使用TTL转USB的转换接口查看串口信息。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/B2A1A4D5-56AF-4B00-83CD-419680406C27.png"><h2 id="连接TTL-USB转接口"><a href="#连接TTL-USB转接口" class="headerlink" title="连接TTL-USB转接口"></a>连接TTL-USB转接口</h2><p>连接TTL-USB转接口的具体接线方法如下，需要将路由器和TTL-转接口的TX,RX口反接。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/8AFD1672-C067-4386-8058-DB7445D86CB9.png"><p>这里遇到了一个坑，之前使用的转接口是PL-2303HX芯片的转接口，发生了各种诡异的情况导致无法正常的使用。最后查了网上的各种资料，推荐使用FT-232芯片的转接口说是兼容性比较好，换上新的转接口后果然能够正常使用了。</p><p>使用任意串口通讯软件打开串口后即可看到类似如下内容的串口信息。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/91B64D5F-F6AF-4D89-BCF7-0647F35B1DBB.png"><p>此时如果设备的接线正确，就可以通过键盘输入?键获取VxWorks的CmdTask命令行(前提是VxWorks固件中编入了这个模块)。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/4DC82675-2F09-4421-91A3-717CEA50997B.png"><h2 id="cmd命令说明"><a href="#cmd命令说明" class="headerlink" title="cmd命令说明"></a>cmd命令说明</h2><p>在对这些cmd命令进行了尝试后，发现了一些有用的命令，下面会列举一些命令进行简单说明。</p><ul><li><code>tftp</code> -  tftp命令行工具。</li><li><code>mem</code>  -  内存操作相关的命令行工具。</li><li><code>flash</code> - flash相关的命令行工具。</li><li><code>net</code> - 网络相关的命令行工具。</li><li><code>system</code>  -  系统命令相关的指令</li></ul><h3 id="tftp-命令行工具说明"><a href="#tftp-命令行工具说明" class="headerlink" title="tftp 命令行工具说明"></a>tftp 命令行工具说明</h3><p><code>tftp</code>命令行支持的功能如下图所示。这个命令看起来非常美好，我们既可以通过<code>tftp -put</code>指令直接上传路由器的内存信息，也可以通过<code>tftp -get</code>指令从tftp server中下载数据写入到特定的内存地址中。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/921B607B-EBCB-4383-8C27-A52326305EF5.png"><p>然而在实际使用中遇到了各种奇怪的问题，<code>tftp -put</code>指令一直无法正常使用，总是返回如下的错误信息。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/9ADD361C-E3D9-49DF-B68D-992378136AB6.png"><p>通过对请求的数据包进行分析后发现了一些怪异的情况，下图是一个正常的TFTP写请求数据流。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/7FE5ED3A-78FC-4C97-9B88-D68959631EC0.png"><p>下图是路由器实际发送的数据包，可以看到服务器返回了TFTP的ACK请求，但是路由器却没有对其进行响应，不断的重新发送写请求。由于固件中没有编入WDB调试模块，因此在无法对tftp进行调试的前提下只能先放弃使用tftp 命令行dump路由器内存的想法。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/00D3E84D-5CB3-4CE6-9A7F-E7B2A5D3F2E6.png"><p>当然<code>tftp -get</code>命令也是类似的错误。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/64894233-54E1-4DEA-BFE3-6E85DAF4DCFC.png"><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/BF578075-0CAE-43A3-9F0D-AD30006F1224.png"><h3 id="mem-命令行工具说明"><a href="#mem-命令行工具说明" class="headerlink" title="mem 命令行工具说明"></a>mem 命令行工具说明</h3><p><code>mem</code>命令行支持的功能如下图所示</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/03084D8A-2A25-45C3-96F7-9D25551AF913.png"><p>使用<code>mem -dump</code>命令可以查看设备中的内存信息，不过串口输出的内存信息不是很稳定，经常因为各种原因导致格式错乱。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/DB1AA0C4-B098-4499-AB66-5DCEAF0BDAD7.png"><p>使用<code>mem -md</code>命令可以对内存中的数据进行修改。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/1E07080E-E5D8-435B-877D-92803DE5EAC7.png"><p>可以看到通过mem内存操作命令行工具，已经可以实现诸如内存dump及打二进制patch修改程序逻辑等功能。</p><p>如下图所示，通过编写脚本模拟串口操作即可实现dump特定内存信息的效果。在脚本编写过程中也遇到过一些坑，例如dump的内存信息经常因为路由器的一些其他输出信息导致格式错乱，或在某些特定情况下会出现CmdTask崩溃或卡死导致输入无响应等异常情况需要处理。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/17C32D23-5278-4EA5-9795-0337EFD0D11E.png"><h3 id="flash-命令行工具说明"><a href="#flash-命令行工具说明" class="headerlink" title="flash 命令行工具说明"></a>flash 命令行工具说明</h3><p><code>flash</code>命令行支持的功能如下图所示, 可以通过这些命令对flash进行读写等操作。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/28C107C6-A51C-4018-81F3-512F10709BAC.png"><p>对于Flash的写操作需要慎重，该操作很有可能会影响到路由器的正常启动，导致设备异常。其他还支持例如查看flash存储的布局信息的命令<code>flash -layout</code>。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/DD2D1DA7-CFAE-4636-AB32-EEC5EECF3A4C.png"><h3 id="net-命令行工具说明"><a href="#net-命令行工具说明" class="headerlink" title="net 命令行工具说明"></a>net 命令行工具说明</h3><p><code>net</code>命令行支持的功能如下图所示, 可以通过这些命令对TCP/UDP的运行时信息进行显示。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/0073FA63-7B40-4156-AA2D-3D8308038246.png"><p>通过使用<code>net -show</code>命令即可查看路由器的TCP/UDP端口使用情况，方便后续进行针对性的测试。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/2ED189A0-C26F-45A6-B41A-764832432878.png"><h3 id="system-命令行工具说明"><a href="#system-命令行工具说明" class="headerlink" title="system 命令行工具说明"></a>system 命令行工具说明</h3><p><code>system</code>命令行支持的功能如下图所示, 可以通过这些命令执行诸如系统重启，重置，设置debug级别等相关操作。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/1BA0D705-44FD-43F1-9700-031F4A29A52F.png"><p>根据帮助功显示的功能来看<code>system</code>命令本身也比较简单，但是在对固件中cmd指令处理的函数进行分析后发现了有趣的事情。<code>CmdTask</code>模块所支持的指令是通过如下图所示的代码进行添加的，通过调用<code>cmdAdd</code>可以添加命令行所支持的指令。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/3DC34330-51FC-414F-8CE5-35980A9ACA9E.png"><p>因此只要查看一下所有的<code>cmdAdd</code>调用信息就可以找到命令行所支持的全部指令及指令解析函数逻辑。下图是<code>sytem</code>函数的指令添加代码。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/215670AD-68A2-4F0D-AA05-EAFB489F2DE1.png"><p>指令解析函数<code>sub_80159CE4</code>中会对指令的参数等进行判断，下图是<code>system</code>命令行中对应的参数解析代码。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/B2B15ADC-081C-42FD-B4DF-95E84D72FE87.png"><p>再确认一下<code>system</code>命令的帮助输出，帮助中的确是没有<code>moduletree</code>这个参数的。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/1BA0D705-44FD-43F1-9700-031F4A29A52F.png"><p>执行一下试试，结果的确有输出，输出还挺有趣的涉及到了http请求中传输的一些json数据内容，这部分将在后续的文档中进行说明。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/370B01C8-EA95-42DA-878F-47A3C536646D.png"><p>经过测试除了moduletree参数system指令还有一个-symble的指令，该指令输出的结果如下。会把系统中的符号信息进行输出。</p><img src="/2018/11/30/0x01-TP-Link-wr886nv7-V1-1-0-路由器分析-VxWorks-cmd命令行获取及使用方法/394F0BA0-A5CE-47D2-A668-476710ECF7D5.png"><p>至此，路由器cmd命令行的获取及使用方法介绍就结束了，通过分析可以看到命令行的帮助有时并不会将所有的命令行指令进行说明，通过分析命令行处理相关的代码，有时会有一些额外的惊喜等着我们。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;在之前一篇文章中对TP-Link wr886nv7 固件进行初步分析后，下一步则是尝试寻找主板上的串口调试接口从而进一步的获取引导过程中的输出信息或是进一步得到登录命令行。&lt;/p&gt;
&lt;h2 id=&quot;焊接串口调试&quot;&gt;&lt;a href=&quot;#焊接串口调试&quot; class=&quot;heade
      
    
    </summary>
    
    
      <category term="IoT" scheme="https://dark-lbp.github.io/tags/IoT/"/>
    
      <category term="VxWorks" scheme="https://dark-lbp.github.io/tags/VxWorks/"/>
    
  </entry>
  
  <entry>
    <title>0x00 TP-Link wr886nv7-V1.1.0 路由器分析 - 固件初步分析</title>
    <link href="https://dark-lbp.github.io/2018/11/30/0x00-TP-Link-wr886nv7-V1-1-0-%E8%B7%AF%E7%94%B1%E5%99%A8%E5%88%86%E6%9E%90-%E5%9B%BA%E4%BB%B6%E5%88%9D%E6%AD%A5%E5%88%86%E6%9E%90/"/>
    <id>https://dark-lbp.github.io/2018/11/30/0x00-TP-Link-wr886nv7-V1-1-0-路由器分析-固件初步分析/</id>
    <published>2018-11-29T23:55:24.000Z</published>
    <updated>2018-12-05T05:43:45.836Z</updated>
    
    <content type="html"><![CDATA[<h2 id="固件提取"><a href="#固件提取" class="headerlink" title="固件提取"></a>固件提取</h2><p>系统固件通常会以一定的格式封装在固件升级包中。为了提取系统固件可以先使用Binwalk对wr886nv7.bin进行初步分析。</p><img src="/2018/11/30/0x00-TP-Link-wr886nv7-V1-1-0-路由器分析-固件初步分析/485F3822-659E-4A9C-A2C8-273ADC00F895.png"><p>从上图可以看到，除了一个比较明显的uImage header头以外这个升级包中还有一大堆的LZMA数据信息。通过使用binwalk或直接使用dd命令能够对升级包中的uimage镜像进行提取。</p><figure class="highlight zsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># count长度应该是header + lzma包的长度</span></span><br><span class="line">dd <span class="keyword">if</span>=wr886nv7.bin of=uboot_0x366C.img bs=1 skip=13932 count=20852</span><br></pre></td></tr></table></figure><p>使用binwalk继续分析uboot的镜像，可以发现这个uboot镜像的Data部分使用了LZMA进行压缩。</p><img src="/2018/11/30/0x00-TP-Link-wr886nv7-V1-1-0-路由器分析-固件初步分析/72F7CC89-5789-4FFA-B287-13F50EE70C9D.png"><p>解压uboot的LZMA数据</p><figure class="highlight zsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">dd <span class="keyword">if</span>=uboot_new.img of=uboot.lzma bs=1 skip=64</span><br></pre></td></tr></table></figure><p>由于uboot image中缺乏符号表且大小只有52K不到，因此此处暂时不对其进行进一步的分析。</p><h2 id="VxWorks-系统固件分析"><a href="#VxWorks-系统固件分析" class="headerlink" title="VxWorks 系统固件分析"></a>VxWorks 系统固件分析</h2><p>在wr886nv7.bin中除了uImage外，还有一个2M多的有趣的lzma压缩数据。</p><img src="/2018/11/30/0x00-TP-Link-wr886nv7-V1-1-0-路由器分析-固件初步分析/A4D3A037-E1BA-40A1-A46F-A50E0553DD0E.png"><p>从升级包中提取该<code>0xA200</code>压缩数据并解压。</p><figure class="highlight zsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># count 是0xc317e - 0xa200</span></span><br><span class="line">dd <span class="keyword">if</span>=wr886nv7.bin of=A200.lzma bs=1 skip=41472 count=757630</span><br><span class="line"><span class="comment"># 使用lzma进行解压</span></span><br><span class="line">lzma -d A200.lzma</span><br></pre></td></tr></table></figure><p>使用Binwalk查看解压出的数据后发现这个文件很可能就是路由器所运行的系统固件，VxWorks系统版本5.5.1.</p><img src="/2018/11/30/0x00-TP-Link-wr886nv7-V1-1-0-路由器分析-固件初步分析/B3285E26-60B6-4342-9A68-F91D165F8BC8.png"><h3 id="固件加载地址分析"><a href="#固件加载地址分析" class="headerlink" title="固件加载地址分析"></a>固件加载地址分析</h3><p>在对<code>0xA200</code>地址之前的一些数据进行分析后可以看到一个疑似uimage header的数据段，其中有两处地址指向了<code>0x80001000</code>，这个地址也和很多同类路由器设备的固件加载地址相同，因此我们可以尝试使用该地址作为固件加载地址进行分析。</p><img src="/2018/11/30/0x00-TP-Link-wr886nv7-V1-1-0-路由器分析-固件初步分析/9A500E08-3C01-4CAD-B9FD-897F0323444F.png"><h3 id="使用IDA加载固件进行分析"><a href="#使用IDA加载固件进行分析" class="headerlink" title="使用IDA加载固件进行分析"></a>使用IDA加载固件进行分析</h3><p>在使用IDA加载前，首先我们需要确定CPU架构及加载地址。CPU架构信息已经在升级包中的uimage header中进行了定义，同时我们也可以使用<code>binwalk -Y</code>命令进行识别。</p><img src="/2018/11/30/0x00-TP-Link-wr886nv7-V1-1-0-路由器分析-固件初步分析/A7CB7F7C-4C96-4B12-BE01-8CEEDC3AAAF5.png"><p>加载地址的话，在前面的分析中已经初步可以判定为<code>0x80001000</code>，下一步就是使用IDA对固件进行加载分析了。在IDA中加载VxWorks固件。</p><img src="/2018/11/30/0x00-TP-Link-wr886nv7-V1-1-0-路由器分析-固件初步分析/DA58D4E4-12B5-4205-AA24-D268CEA9D49B.png"><p>在IDA中填写固件加载地址信息<code>0x80001000</code>。</p><img src="/2018/11/30/0x00-TP-Link-wr886nv7-V1-1-0-路由器分析-固件初步分析/0F1D1083-DFE5-4A24-BD00-83D84AD2E716.png"><p>成功加载固件后的IDA界面大致如下图所示，可以看到默认加载的情况下还是有大量的函数。</p><img src="/2018/11/30/0x00-TP-Link-wr886nv7-V1-1-0-路由器分析-固件初步分析/68EB3936-4991-404A-B2BC-71F01C581725.png"><h3 id="尝试修复函数名"><a href="#尝试修复函数名" class="headerlink" title="尝试修复函数名"></a>尝试修复函数名</h3><p>通过初步对加载的VxWorks固件进行分析后发现，这个固件中并没有编入符号表，这对后续研究产生了很大的影响。再次对固件升级包中的内容进行分析后发现，有一个格式为data的文件很有趣。</p><figure class="highlight zsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 使用binwalk -e 默认提取升级包中的文件。</span></span><br><span class="line">binwalk -e wr886nv7.bin</span><br><span class="line"><span class="comment"># 进入目录后查找，是否存在包含VxWorks关键函数名的文件。 </span></span><br><span class="line"><span class="built_in">cd</span> _wr886nv6-20180123.bin.extracted</span><br><span class="line">grep -r bzero ./</span><br></pre></td></tr></table></figure><img src="/2018/11/30/0x00-TP-Link-wr886nv7-V1-1-0-路由器分析-固件初步分析/6F50ADF0-1264-468C-B1BF-FA51A6AAFE36.png"><p>在对C4FAB的内容进行查看后发现有惊喜，文件中保存的数据很像独立的符号表，其中找到了大量的VxWorks关键函数名。</p><img src="/2018/11/30/0x00-TP-Link-wr886nv7-V1-1-0-路由器分析-固件初步分析/D7CE7224-21C1-4E6B-BDFC-28B2A24A1C6B.png"><p>在对这个文件进行了初步的分析后发现这个文件还是有很明显的特征的。</p><img src="/2018/11/30/0x00-TP-Link-wr886nv7-V1-1-0-路由器分析-固件初步分析/A31A419D-D179-4FFA-B850-4617BCF58773.png"><img src="/2018/11/30/0x00-TP-Link-wr886nv7-V1-1-0-路由器分析-固件初步分析/45977573-4BA0-4F4D-A98E-2E00CFDE17B1.png"><p>根据这个独立符号文件的特征，我们可以编写对应的ida_python脚本来对固件进行修复。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># coding=utf-8</span></span><br><span class="line"><span class="keyword">import</span> idc</span><br><span class="line"><span class="keyword">import</span> idaapi</span><br><span class="line"><span class="keyword">import</span> idautils</span><br><span class="line">sym_file = open(<span class="string">"PATH OF SYM FILE"</span>, <span class="string">'rb'</span>).read()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">table_data = sym_file[<span class="number">0x08</span>:<span class="number">0x9f80</span>]</span><br><span class="line">print(table_data[<span class="number">-8</span>:].encode(<span class="string">'hex'</span>))</span><br><span class="line">string_table = sym_file[<span class="number">0x9f80</span>:]</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_string</span><span class="params">(offset)</span>:</span></span><br><span class="line">    string = <span class="string">""</span></span><br><span class="line">    <span class="keyword">while</span> <span class="keyword">True</span>:</span><br><span class="line">        <span class="keyword">if</span> string_table[offset] != <span class="string">'\x00'</span>:</span><br><span class="line">            string += string_table[offset]</span><br><span class="line">            offset += <span class="number">1</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line">    <span class="keyword">return</span> string</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_sym_data</span><span class="params">()</span>:</span></span><br><span class="line">    sym_data = []</span><br><span class="line">    <span class="keyword">for</span> offset <span class="keyword">in</span> range(<span class="number">0</span>, len(table_data), <span class="number">8</span>):</span><br><span class="line">        table = table_data[offset: offset + <span class="number">8</span>]</span><br><span class="line">        flag = table[<span class="number">0</span>]</span><br><span class="line">        <span class="comment"># print('flag: %s' % flag)</span></span><br><span class="line">        string_offset = int(table[<span class="number">1</span>:<span class="number">4</span>].encode(<span class="string">'hex'</span>), <span class="number">16</span>)</span><br><span class="line">        <span class="comment"># print('string_offset: %s' % string_offset)</span></span><br><span class="line">        string = get_string(string_offset)</span><br><span class="line">        <span class="comment"># print('string: %s' % string)</span></span><br><span class="line">        target_address = int(table[<span class="number">-4</span>:].encode(<span class="string">'hex'</span>), <span class="number">16</span>)</span><br><span class="line">        <span class="comment"># print('target_address: %s' % hex(target_address))</span></span><br><span class="line">        sym_data.append([flag, string, target_address])</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> sym_data</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">fix_idb</span><span class="params">(sym_data)</span>:</span></span><br><span class="line">    <span class="keyword">for</span> sym <span class="keyword">in</span> sym_data:</span><br><span class="line">        flag, string, target_address = sym</span><br><span class="line">        idc.MakeName(target_address, string)</span><br><span class="line">        <span class="keyword">if</span> flag == <span class="string">'\x54'</span>:</span><br><span class="line">            print(<span class="string">"Start fix Function %s at %s"</span> % (string, hex(target_address)))</span><br><span class="line">            idc.MakeCode(target_address)</span><br><span class="line">            idc.MakeFunction(target_address, idc.BADADDR)</span><br><span class="line">            <span class="comment"># print('flag: %s' % flag)</span></span><br><span class="line">            <span class="comment"># print('string: %s' % string)</span></span><br><span class="line">            <span class="comment"># print('target_address: %s' % hex(target_address))</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    sym_data = get_sym_data()</span><br><span class="line">    fix_idb(sym_data)</span><br></pre></td></tr></table></figure><p>脚本运行后固件看起来就清晰了很多。</p><img src="/2018/11/30/0x00-TP-Link-wr886nv7-V1-1-0-路由器分析-固件初步分析/74CA8066-1F11-4D6A-9467-75AEBA844F65.png"><p>至此，固件分析的预处理工作就成功完成了，此时固件中依然还有很多很函数无法被正确被识别，还需要后续的一些操作进行手动修复。基本修复后的IDA界面会像下图所示, 具体的修复方法将会在后续的文档中进行说明。</p><img src="/2018/11/30/0x00-TP-Link-wr886nv7-V1-1-0-路由器分析-固件初步分析/D44F78EE-ED1F-457F-A47A-026769511E4A.png"><p>根据固件及设备分析后修复的segments信息</p><img src="/2018/11/30/0x00-TP-Link-wr886nv7-V1-1-0-路由器分析-固件初步分析/DCEB01B1-D41F-4151-9A2C-00C0F858DAE5.png">]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;固件提取&quot;&gt;&lt;a href=&quot;#固件提取&quot; class=&quot;headerlink&quot; title=&quot;固件提取&quot;&gt;&lt;/a&gt;固件提取&lt;/h2&gt;&lt;p&gt;系统固件通常会以一定的格式封装在固件升级包中。为了提取系统固件可以先使用Binwalk对wr886nv7.bin进行初步分析
      
    
    </summary>
    
    
      <category term="Vxworks" scheme="https://dark-lbp.github.io/tags/Vxworks/"/>
    
      <category term="IoT" scheme="https://dark-lbp.github.io/tags/IoT/"/>
    
  </entry>
  
</feed>
