2019-07-25 14:22:59 +00:00
<!DOCTYPE html>
2019-08-09 03:54:43 +00:00
< html class = "theme-next gemini use-motion" lang = "zh-Hans" >
2019-07-25 14:22:59 +00:00
< head > < meta name = "generator" content = "Hexo 3.8.0" >
< meta charset = "UTF-8" >
< meta http-equiv = "X-UA-Compatible" content = "IE=edge" >
< meta name = "viewport" content = "width=device-width, initial-scale=1, maximum-scale=1" >
< meta name = "theme-color" content = "#222" >
< meta http-equiv = "Cache-Control" content = "no-transform" >
< meta http-equiv = "Cache-Control" content = "no-siteapp" >
< link href = "/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel = "stylesheet" type = "text/css" >
< link href = "/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel = "stylesheet" type = "text/css" >
< link href = "/css/main.css?v=5.1.4" rel = "stylesheet" type = "text/css" >
< link rel = "apple-touch-icon" sizes = "180x180" href = "/images/hackerrank.png?v=5.1.4" >
< link rel = "icon" type = "image/png" sizes = "32x32" href = "/images/hackerrank.png?v=5.1.4" >
< link rel = "icon" type = "image/png" sizes = "16x16" href = "/images/hackerrank.png?v=5.1.4" >
< link rel = "mask-icon" href = "/images/logo.svg?v=5.1.4" color = "#222" >
< meta name = "keywords" content = "小米,路由器,调试," >
2019-07-25 14:36:55 +00:00
< meta name = "description" content = "0x00 背景与简介在分析嵌入式设备的固件时, 只采用静态分析方式通常是不够的, 你需要实际执行你的分析目标来观察它的行为。在嵌入式Linux设备的世界里, 很容易把一个调试器放在目标硬件上进行调试。如果你能在自己的系统上运行二进制文件, 而不是拖着硬件做分析, 将会方便很多, 这就需要用QEMU进行仿真。虽然QEMU在模拟核心芯片组包括CPU上都做的很不错, 但是QEMU往往不能提供你想运行的二进制程序需要" >
2019-07-25 14:22:59 +00:00
< meta name = "keywords" content = "小米,路由器,调试" >
< meta property = "og:type" content = "article" >
< meta property = "og:title" content = "远程调试小米路由器固件" >
< meta property = "og:url" content = "https://cool-y.github.io/2019/07/25/Debug-a-router-firmware/index.html" >
< meta property = "og:site_name" content = "混元霹雳手" >
2019-07-25 14:36:55 +00:00
< meta property = "og:description" content = "0x00 背景与简介在分析嵌入式设备的固件时, 只采用静态分析方式通常是不够的, 你需要实际执行你的分析目标来观察它的行为。在嵌入式Linux设备的世界里, 很容易把一个调试器放在目标硬件上进行调试。如果你能在自己的系统上运行二进制文件, 而不是拖着硬件做分析, 将会方便很多, 这就需要用QEMU进行仿真。虽然QEMU在模拟核心芯片组包括CPU上都做的很不错, 但是QEMU往往不能提供你想运行的二进制程序需要" >
2019-07-25 14:22:59 +00:00
< meta property = "og:locale" content = "zh-Hans" >
2019-07-25 14:36:55 +00:00
< meta property = "og:updated_time" content = "2019-07-25T14:36:28.915Z" >
2019-07-25 14:22:59 +00:00
< meta name = "twitter:card" content = "summary" >
< meta name = "twitter:title" content = "远程调试小米路由器固件" >
2019-07-25 14:36:55 +00:00
< meta name = "twitter:description" content = "0x00 背景与简介在分析嵌入式设备的固件时, 只采用静态分析方式通常是不够的, 你需要实际执行你的分析目标来观察它的行为。在嵌入式Linux设备的世界里, 很容易把一个调试器放在目标硬件上进行调试。如果你能在自己的系统上运行二进制文件, 而不是拖着硬件做分析, 将会方便很多, 这就需要用QEMU进行仿真。虽然QEMU在模拟核心芯片组包括CPU上都做的很不错, 但是QEMU往往不能提供你想运行的二进制程序需要" >
2019-07-25 14:22:59 +00:00
< script type = "text/javascript" id = "hexo.configurations" >
var NexT = window.NexT || {};
var CONFIG = {
root: '/',
2019-08-09 03:54:43 +00:00
scheme: 'Gemini',
2019-07-25 14:22:59 +00:00
version: '5.1.4',
sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
fancybox: true,
tabs: true,
motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
duoshuo: {
userId: '0',
author: '博主'
},
algolia: {
applicationID: '',
apiKey: '',
indexName: '',
hits: {"per_page":10},
labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
}
};
< / script >
< link rel = "canonical" href = "https://cool-y.github.io/2019/07/25/Debug-a-router-firmware/" >
< title > 远程调试小米路由器固件 | 混元霹雳手< / title >
< / head >
< body itemscope itemtype = "http://schema.org/WebPage" lang = "zh-Hans" >
< div class = "container sidebar-position-left page-post-detail" >
< div class = "headband" > < / div >
< header id = "header" class = "header" itemscope itemtype = "http://schema.org/WPHeader" >
< div class = "header-inner" > < div class = "site-brand-wrapper" >
< div class = "site-meta " >
< div class = "custom-logo-site-title" >
< a href = "/" class = "brand" rel = "start" >
< span class = "logo-line-before" > < i > < / i > < / span >
< span class = "site-title" > 混元霹雳手< / span >
< span class = "logo-line-after" > < i > < / i > < / span >
< / a >
< / div >
< p class = "site-subtitle" > < / p >
< / div >
< div class = "site-nav-toggle" >
< button >
< span class = "btn-bar" > < / span >
< span class = "btn-bar" > < / span >
< span class = "btn-bar" > < / span >
< / button >
< / div >
< / div >
< nav class = "site-nav" >
< ul id = "menu" class = "menu" >
< li class = "menu-item menu-item-home" >
< a href = "/" rel = "section" >
< i class = "menu-item-icon fa fa-fw fa-home" > < / i > < br >
首页
< / a >
< / li >
< li class = "menu-item menu-item-about" >
< a href = "/about/" rel = "section" >
< i class = "menu-item-icon fa fa-fw fa-user" > < / i > < br >
关于
< / a >
< / li >
< li class = "menu-item menu-item-tags" >
< a href = "/tags/" rel = "section" >
< i class = "menu-item-icon fa fa-fw fa-tags" > < / i > < br >
标签
< / a >
< / li >
< li class = "menu-item menu-item-categories" >
< a href = "/categories/" rel = "section" >
< i class = "menu-item-icon fa fa-fw fa-th" > < / i > < br >
分类
< / a >
< / li >
< li class = "menu-item menu-item-archives" >
< a href = "/archives/" rel = "section" >
< i class = "menu-item-icon fa fa-fw fa-archive" > < / i > < br >
归档
< / a >
< / li >
< li class = "menu-item menu-item-bookmarks" >
< a href = "/bookmarks/" rel = "section" >
< i class = "menu-item-icon fa fa-fw fa-map" > < / i > < br >
书签
< / a >
< / li >
2019-08-08 12:42:56 +00:00
2019-08-08 12:47:43 +00:00
< li class = "menu-item menu-item-hack之外" >
2019-08-08 12:42:56 +00:00
< a href = "/hack之外/" rel = "section" >
2019-08-08 12:52:19 +00:00
< i class = "menu-item-icon fa fa-fw fa-heartbeat" > < / i > < br >
2019-08-08 12:42:56 +00:00
2019-08-08 12:52:19 +00:00
HACK之外
2019-08-08 12:42:56 +00:00
< / a >
< / li >
2019-07-25 14:22:59 +00:00
< li class = "menu-item menu-item-search" >
< a href = "javascript:;" class = "popup-trigger" >
< i class = "menu-item-icon fa fa-search fa-fw" > < / i > < br >
搜索
< / a >
< / li >
< / ul >
< div class = "site-search" >
< div class = "popup search-popup local-search-popup" >
< div class = "local-search-header clearfix" >
< span class = "search-icon" >
< i class = "fa fa-search" > < / i >
< / span >
< span class = "popup-btn-close" >
< i class = "fa fa-times-circle" > < / i >
< / span >
< div class = "local-search-input-wrapper" >
< input autocomplete = "off" placeholder = "搜索..." spellcheck = "false" type = "text" id = "local-search-input" >
< / div >
< / div >
< div id = "local-search-result" > < / div >
< / div >
< / div >
< / nav >
< / div >
< / header >
< main id = "main" class = "main" >
< div class = "main-inner" >
< div class = "content-wrap" >
< div id = "content" class = "content" >
< div id = "posts" class = "posts-expand" >
< article class = "post post-type-normal" itemscope itemtype = "http://schema.org/Article" >
< div class = "post-block" >
< link itemprop = "mainEntityOfPage" href = "https://cool-y.github.io/2019/07/25/Debug-a-router-firmware/" >
< span hidden itemprop = "author" itemscope itemtype = "http://schema.org/Person" >
< meta itemprop = "name" content = "Cool-Y" >
< meta itemprop = "description" content >
< meta itemprop = "image" content = "/images/avatar.png" >
< / span >
< span hidden itemprop = "publisher" itemscope itemtype = "http://schema.org/Organization" >
< meta itemprop = "name" content = "混元霹雳手" >
< / span >
< header class = "post-header" >
< h1 class = "post-title" itemprop = "name headline" > 远程调试小米路由器固件< / h1 >
< div class = "post-meta" >
< span class = "post-time" >
< span class = "post-meta-item-icon" >
< i class = "fa fa-calendar-o" > < / i >
< / span >
< span class = "post-meta-item-text" > 发表于< / span >
< time title = "创建于" itemprop = "dateCreated datePublished" datetime = "2019-07-25T22:17:08+08:00" >
2019-07-25
< / time >
< / span >
< span class = "post-category" >
< span class = "post-meta-divider" > |< / span >
< span class = "post-meta-item-icon" >
< i class = "fa fa-folder-o" > < / i >
< / span >
< span class = "post-meta-item-text" > 分类于< / span >
< span itemprop = "about" itemscope itemtype = "http://schema.org/Thing" >
< a href = "/categories/IOT/" itemprop = "url" rel = "index" >
< span itemprop = "name" > IOT< / span >
< / a >
< / span >
< / span >
< span id = "/2019/07/25/Debug-a-router-firmware/" class = "leancloud_visitors" data-flag-title = "远程调试小米路由器固件" >
< span class = "post-meta-divider" > |< / span >
< span class = "post-meta-item-icon" >
< i class = "fa fa-eye" > < / i >
< / span >
< span class = "post-meta-item-text" > 阅读次数: < / span >
< span class = "leancloud-visitors-count" > < / span >
< / span >
< div class = "post-wordcount" >
< span class = "post-meta-item-icon" >
< i class = "fa fa-file-word-o" > < / i >
< / span >
< span title = "字数统计" >
3k 字
< / span >
< span class = "post-meta-divider" > |< / span >
< span class = "post-meta-item-icon" >
< i class = "fa fa-clock-o" > < / i >
< / span >
< span title = "阅读时长" >
13 分钟
< / span >
< / div >
< / div >
< / header >
< div class = "post-body" itemprop = "articleBody" >
2019-07-25 14:36:55 +00:00
< h1 id = "0x00-背景与简介" > < a href = "#0x00-背景与简介" class = "headerlink" title = "0x00 背景与简介" > < / a > 0x00 背景与简介< / h1 > < p > 在分析嵌入式设备的固件时, 只采用静态分析方式通常是不够的, 你需要实际执行你的分析目标来观察它的行为。在嵌入式Linux设备的世界里, 很容易把一个调试器放在目标硬件上进行调试。如果你能在自己的系统上运行二进制文件, 而不是拖着硬件做分析, 将会方便很多, 这就需要用QEMU进行仿真。< br > 虽然QEMU在模拟核心芯片组包括CPU上都做的很不错, 但是QEMU往往不能提供你想运行的二进制程序需要的硬件。最常见问题是在运行系统服务, 如Web服务器或UPnP守护进程时, 缺乏NVRAM。解决方法是使用nvram-faker库拦截由libnvram.so提供的nvram_get()调用。即使解决了NVRAM问题, 该程序还可能会假设某些硬件是存在的, 如果硬件不存在, 该程序可能无法运行, 或者即便它运行了, 行为可能也与在其目标硬件上运行时有所不同。针对这种情况下, 我认为有三种解决方法: < / p >
2019-07-25 14:22:59 +00:00
< ol >
< li > 修补二进制文件。这取决于期望什么硬件,以及它不存在时的行为是什么。< / li >
< li > 把复杂的依赖于硬件的系统服务拆分成小的二级制文件。如跳过运行Web服务器, 仅仅从shell脚本运行cgi二进制文件。因为大多数cgi二进制文件将来自Web服务器的输入作为标准输入和环境变量的组合, 并通过标准输出将响应发送到Web服务器。< / li >
< li > 拿到设备的shell, 直接在真机上进行调试, 这是最接近真实状况的方法。< / li >
< / ol >
2019-07-25 14:36:55 +00:00
< hr >
< h1 id = "REF" > < a href = "#REF" class = "headerlink" title = "REF" > < / a > REF< / h1 > < p > < strong > 综合:< / strong > < br > < a href = "https://shadow-file.blogspot.com/2015/01/dynamically-analyzing-wifi-routers-upnp.html" target = "_blank" rel = "noopener" > 国外大神的博客< / a > < br > < a href = "https://wooyun.js.org/drops/%E9%80%9A%E8%BF%87QEMU%20%E5%92%8C%20IDA%20Pro%E8%BF%9C%E7%A8%8B%E8%B0%83%E8%AF%95%E8%AE%BE%E5%A4%87%E5%9B%BA%E4%BB%B6.html" target = "_blank" rel = "noopener" > 通过QEMU和IDAPro远程调试设备固件< / a > < br > < a href = "https://ray-cp.github.io/archivers/MIPS_Debug_Environment_and_Stack_Overflow" target = "_blank" rel = "noopener" > MIPS漏洞调试环境安装及栈溢出< / a > < br > < a href = "https://wiki.x10sec.org/pwn/arm/environment/" target = "_blank" rel = "noopener" > 环境搭建onCTFWIKI< / a > < br > < a href = "https://www.anquanke.com/post/id/171918" target = "_blank" rel = "noopener" > 路由器漏洞训练平台< / a > < br > < a href = "https://www.anquanke.com/post/id/180714" target = "_blank" rel = "noopener" > 路由器0day漏洞挖掘实战< / a > < br > < a href = "https://5alt.me/wiki/%E9%80%86%E5%90%91" target = "_blank" rel = "noopener" > 逆向常用工具< / a > < / p >
2019-07-25 14:22:59 +00:00
< p > < strong > 环境搭建:< / strong > < br > < a href = "https://xz.aliyun.com/t/3826" target = "_blank" rel = "noopener" > 路由器漏洞挖掘测试环境的搭建之问题总结< / a > < / p >
< p > < strong > Linux相关知识< / strong > < br > < a href = "http://xstarcd.github.io/wiki/Cloud/qcow2_raw_vmdk.html" target = "_blank" rel = "noopener" > qcow2、raw、vmdk等镜像格式< / a > < br > < a href = "http://joe.is-programmer.com/posts/17753.html" target = "_blank" rel = "noopener" > Linux 引导过程内幕< / a > < br > < a href = "https://zhuanlan.zhihu.com/p/32051645" target = "_blank" rel = "noopener" > Linux启动过程< / a > < / p >
< p > < strong > 调试案例< / strong > < br > < a href = "https://xz.aliyun.com/t/5681" target = "_blank" rel = "noopener" > CVE-2019-10999复现< / a > < br > < a href = "https://ray-cp.github.io/archivers/router_vuln_book_note" target = "_blank" rel = "noopener" > 《家用路由器0day漏洞挖掘》部分案例< / a > < br > < a href = "https://paper.seebug.org/448/" target = "_blank" rel = "noopener" > TP-LINK WR941N路由器研究< / a > < / p >
2019-07-25 14:36:55 +00:00
< hr >
< h1 id = "0x01-基础条件" > < a href = "#0x01-基础条件" class = "headerlink" title = "0x01 基础条件" > < / a > 0x01 基础条件< / h1 > < ul >
2019-07-25 14:34:25 +00:00
< li > < p > 一系列的工具,包括:< br > < strong > binwalk< / strong > 帮助你解包固件< br > < strong > buildroot< / strong > mips交叉编译环境帮助你在x86平台下编译mips架构的目标程序 < a href = "https://xz.aliyun.com/t/2505#toc-6" target = "_blank" rel = "noopener" > https://xz.aliyun.com/t/2505#toc-6< / a > < br > < strong > qemu< / strong > 帮助你模拟mips环境< br > < strong > MIPS gdbinit< / strong > 文件使得使用gdb调试mips程序时更方便 < a href = "https://github.com/zcutlip/gdbinit-mips" target = "_blank" rel = "noopener" > https://github.com/zcutlip/gdbinit-mips< / a > < br > < strong > miranda工具< / strong > 用于UPnP分析 < a href = "https://code.google.com/p/miranda-upnp/" target = "_blank" rel = "noopener" > https://code.google.com/p/miranda-upnp/< / a > < br > < strong > MIPS静态汇编审计< / strong > 辅助脚本 < a href = "https://github.com/giantbranch/mipsAudit" target = "_blank" rel = "noopener" > https://github.com/giantbranch/mipsAudit< / a > < br > < strong > 静态编译的gdbserver< / strong > < a href = "https://github.com/rapid7/embedded-tools/tree/master/binaries/gdbserver" target = "_blank" rel = "noopener" > https://github.com/rapid7/embedded-tools/tree/master/binaries/gdbserver< / a > < / p >
2019-07-25 14:22:59 +00:00
< / li >
< li > < p > 一个< strong > mips Linux< / strong > 环境:< br > 在qemu系统模式下, 需要模拟整个计算机系统< / p >
< / li >
< / ul >
2019-07-25 14:36:55 +00:00
< hr >
< h1 id = "0x02-qemu-用户模式" > < a href = "#0x02-qemu-用户模式" class = "headerlink" title = "0x02 qemu-用户模式" > < / a > 0x02 qemu-用户模式< / h1 > < p > 在user mode下使用qemu执行程序有两种情况, 一是目标程序为< strong > 静态链接< / strong > , 那么可以直接使用qemu。另一种是目标程序依赖于< strong > 动态链接< / strong > 库,这时候就需要我们来< strong > 指明库的位置< / strong > ,否则目标程序回到系统< code > /lib< / code > 文件下寻找共享库文件。< br > 在 < em > 《揭秘家用路由器0day》< / em > 这本书里面,他给出的方法是:< br > < figure class = "highlight shell" > < 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 = "meta" > $< / span > cp $(which qemu-mipsel) ./< / span > < br > < span class = "line" > < span class = "meta" > $< / span > sudo chroot . ./qemu-mipsel ./usr/sbin/miniupnpd< / span > < br > < / pre > < / td > < / tr > < / table > < / figure > < / p >
2019-07-25 14:22:59 +00:00
< p > 他把qemu-mipsel复制到固件文件目录下, 然后< code > chroot< / code > 命令改变qemu执行的根目录到当前目录, 按理说此时应该可以找到依赖库,但是结果却是< code > chroot: failed to run command ‘ ./qemu-mipsel’ : No such file or directory< / code > < / p >
< p > 在网上找到了< a href = "https://xz.aliyun.com/t/3826" target = "_blank" rel = "noopener" > 解决方法< / a > :需要安装使用 < strong > qemu-mips-static< / strong > 才可以< br > < figure class = "highlight shell" > < table > < tr > < td class = "gutter" > < pre > < span class = "line" > 1< / span > < br > < span class = "line" > 2< / span > < br > < span class = "line" > 3< / span > < br > < / pre > < / td > < td class = "code" > < pre > < span class = "line" > < span class = "meta" > $< / span > apt-get install qemu binfmt-support qemu-user-static< / span > < br > < span class = "line" > < span class = "meta" > $< / span > cp $(which qemu-mipsel-static ) ./< / span > < br > < span class = "line" > < span class = "meta" > $< / span > sudo chroot . ./qemu-mipsel-static ./usr/sbin/miniupnpd< / span > < br > < / pre > < / td > < / tr > < / table > < / figure > < / p >
< p > 这里还可利用< code > -E< / code > 用来设置环境变量,< code > LD_PRELOAD " ./lib" < / code > 用来劫持系统调用,另外还有< code > -g< / code > 开启调试模式< / p >
< p > 除此之外,也在< a href = "https://wiki.x10sec.org/pwn/arm/environment/" target = "_blank" rel = "noopener" > CTF-WIKI< / a > 上找到了另一种方法:使用 < strong > qemu-mips 的 -L 参数< / strong > 指定路由器的根目录< br > < figure class = "highlight shell" > < table > < tr > < td class = "gutter" > < pre > < span class = "line" > 1< / span > < br > < / pre > < / td > < td class = "code" > < pre > < span class = "line" > < span class = "meta" > $< / span > qemu-mipsel -L . ./usr/sbin/miniupnpd< / span > < br > < / pre > < / td > < / tr > < / table > < / figure > < / p >
< h2 id = "模拟miniupnp" > < a href = "#模拟miniupnp" class = "headerlink" title = "模拟miniupnp" > < / a > 模拟miniupnp< / h2 > < p > 由于没有指定参数, 所以这里miniupnpd只把usage和notes打印给我们了: < br > < figure class = "highlight shell" > < 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 > < / pre > < / td > < td class = "code" > < pre > < span class = "line" > Usage:< / span > < br > < span class = "line" > ./usr/sbin/miniupnpd [-f config_file] [-i ext_ifname] [-o ext_ip]< / span > < br > < span class = "line" > [-a listening_ip] [-p port] [-d] [-U] [-S] [-N]< / span > < br > < span class = "line" > [-u uuid] [-s serial] [-m model_number]< / span > < br > < span class = "line" > [-t notify_interval] [-P pid_filename]< / span > < br > < span class = "line" > [-B down up] [-w url] [-r clean_ruleset_interval]< / span > < br > < span class = "line" > [-A "permission rule"] [-b BOOTID]< / span > < br > < span class = "line" > < / span > < br > < span class = "line" > Notes:< / span > < br > < span class = "line" > There can be one or several listening_ips.< / span > < br > < span class = "line" > Notify interval is in seconds. Default is 30 seconds.< / span > < br > < span class = "line" > Default pid file is '/var/run/miniupnpd.pid'.< / span > < br > < span class = "line" > Default config file is '/etc/miniupnpd.conf'.< / span > < br > < span class = "line" > With -d miniupnpd will run as a standard program.< / span > < br > < span class = "line" > -S sets "secure" mode : clients can only add mappings to their own ip< / span > < br > < span class = "line" > -U causes miniupnpd to report system uptime instead of daemon uptime.< / span > < br > < span class = "line" > -N enables NAT-PMP functionality.< / span > < br > < span class = "line" > -B sets bitrates reported by daemon in bits per second.< / span > < br > < span class = "line" > -w sets the presentation url. Default is http address on port 80< / span > < br > < span class = "line" > -A use following syntax for permission rules :< / span > < br > < span class = "line" > (allow|deny) (external port range) ip/mask (internal port range)< / span > < br > < span class = "line" > examples :< / span > < br > < span class = "line" > "allow 1024-65535 192.168.1.0/24 1024-65535"< / span > < br > < span class = "line" > "deny 0-65535 0.0.0.0/0 0-65535"< / span > < br > < span class = "line" > -b sets the value of BOOTID.UPNP.ORG SSDP header< / span > < br > < span class = "line" > -h prints this help and quits.< / span > < br > < / pre > < / td > < / tr > < / table > < / figure > < / p >
< p > 根据miniupnpd的启动文件< code > /etc/init.d/miniupnpd< / code > ,小米使用了启动脚本来配置< code > service_start /usr/sbin/miniupnpd -f conffile -d< / code > < br > 其配置文件connfile如下所示: < br > < figure class = "highlight plain" > < 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" > ext_ifname=eth0.2< / span > < br > < span class = "line" > listening_ip=br-lan< / span > < br > < span class = "line" > port=5351< / span > < br > < span class = "line" > enable_natpmp=yes< / span > < br > < span class = "line" > enable_upnp=yes< / span > < br > < span class = "line" > secure_mode=no< / span > < br > < span class = "line" > system_uptime=yes< / span > < br > < span class = "line" > lease_file=/tmp/upnp.leases< / span > < br > < span class = "line" > bitrate_down=8388608< / span > < br > < span class = "line" > bitrate_up=4194304< / span > < br > < span class = "line" > uuid=e1f3a0ec-d9d4-4317-a14b-130cdd18d092< / span > < br > < span class = "line" > allow 1024-65535 0.0.0.0/0 1024-65535< / span > < br > < span class = "line" > deny 0-65535 0.0.0.0/0 0-65535< / span > < br > < / pre > < / td > < / tr > < / table > < / figure > < / p >
< ul >
< li style = "list-style: none" > < input type = "checkbox" > 可见因路由器的特殊性,具有两张网卡(eth0.2& br-lan), 暂时我还没想出应该怎么解决, 是否采用qemu虚拟机配置网络可以解决呢? 反正我采用下面这种粗暴的方式是不可以的(直接指定配置文件)< figure class = "highlight shell" > < 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 = "meta" > $< / span > sudo qemu-mipsel -L . ./usr/sbin/miniupnpd -f ../../MiniUPnP/miniupnpd.conf -d< / span > < br > < span class = "line" > miniupnpd[7687]: system uptime is 5652 seconds< / span > < br > < span class = "line" > miniupnpd[7687]: iptc_init() failed : iptables who? (do you need to insmod?)< / span > < br > < span class = "line" > miniupnpd[7687]: Failed to init redirection engine. EXITING< / span > < br > < / pre > < / td > < / tr > < / table > < / figure >
< / li >
< / ul >
2019-07-25 14:36:55 +00:00
< hr >
< h1 id = "0x03-qemu-系统模式" > < a href = "#0x03-qemu-系统模式" class = "headerlink" title = "0x03 qemu-系统模式" > < / a > 0x03 qemu-系统模式< / h1 > < p > 系统模式命令格式:< code > $qemu system-mips [option][disk_image]< / code > < / p >
2019-07-25 14:22:59 +00:00
< h2 id = "MIPS系统网络配置" > < a href = "#MIPS系统网络配置" class = "headerlink" title = "MIPS系统网络配置" > < / a > MIPS系统网络配置< / h2 > < p > 下载mips系统内核和虚拟机镜像 < a href = "https://people.debian.org/~aurel32/qemu/" target = "_blank" rel = "noopener" > https://people.debian.org/~aurel32/qemu/< / a > < br > < figure class = "highlight plain" > < 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" > To use this image, you need to install QEMU 1.1.0 (or later). Start QEMU< / span > < br > < span class = "line" > with the following arguments for a 32-bit machine:< / span > < br > < span class = "line" > - qemu-system-mipsel -M malta -kernel vmlinux-2.6.32-5-4kc-malta -hda debian_squeeze_mipsel_standard.qcow2 -append " root=/dev/sda1 console=tty0" < / span > < br > < span class = "line" > - qemu-system-mipsel -M malta -kernel vmlinux-3.2.0-4-4kc-malta -hda debian_wheezy_mipsel_standard.qcow2 -append " root=/dev/sda1 console=tty0" < / span > < br > < / pre > < / td > < / tr > < / table > < / figure > < / p >
< p > < strong > 1. 安装依赖文件< / strong > < code > apt-get install uml-utilities bridge-utils< / code > < / p >
< p > < strong > 2. 修改主机网络配置< / strong > < br > < figure class = "highlight plain" > < 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 > < / pre > < / td > < td class = "code" > < pre > < span class = "line" > auto lo< / span > < br > < span class = "line" > iface lo inet loopback< / span > < br > < span class = "line" > < / span > < br > < span class = "line" > auto ens33< / span > < br > < span class = "line" > iface eth0 inet dhcp< / span > < br > < span class = "line" > < / span > < br > < span class = "line" > #auto br0< / span > < br > < span class = "line" > iface br0 inet dhcp< / span > < br > < span class = "line" > bridge_ports ens33< / span > < br > < span class = "line" > bridge_maxwait 0< / span > < br > < / pre > < / td > < / tr > < / table > < / figure > < / p >
< p > < strong > 3. 修改qemu网络接口启动脚本< / strong > < br > < figure class = "highlight plain" > < 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 > < / pre > < / td > < td class = "code" > < pre > < span class = "line" > $ sudo vim /etc/qemu-ifup < / span > < br > < span class = "line" > $ sudo chmod a+x /etc/qemu-ifup< / span > < br > < span class = "line" > #!/bin/sh< / span > < br > < span class = "line" > echo " Executing /etc/qemu-ifup" < / span > < br > < span class = "line" > echo " Bringing $1 for bridged mode..." < / span > < br > < span class = "line" > sudo /sbin/ifconfig $1 0.0.0.0 promisc up< / span > < br > < span class = "line" > echo " Adding $1 to br0..." < / span > < br > < span class = "line" > sudo /sbin/brctl addif br0 $1< / span > < br > < span class = "line" > sleep 3< / span > < br > < / pre > < / td > < / tr > < / table > < / figure > < / p >
< figure class = "highlight plain" > < table > < tr > < td class = "gutter" > < pre > < span class = "line" > 1< / span > < br > < / pre > < / td > < td class = "code" > < pre > < span class = "line" > $ sudo /etc/init.d/networking restart< / span > < br > < / pre > < / td > < / tr > < / table > < / figure >
< p > < strong > 4. qemu启动配置< / strong > < br > < figure class = "highlight plain" > < 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" > $ sudo ifdown ens33< / span > < br > < span class = "line" > $ sudo ifup br0< / span > < br > < / pre > < / td > < / tr > < / table > < / figure > < / p >
< p > < strong > 5. 启动mips虚拟机< / strong > < br > < code > sudo qemu-system-mipsel -M malta -kernel vmlinux-3.2.0-4-4kc-malta -hda debian_wheezy_mipsel_standard.qcow2 -append " root=/dev/sda1 console=tty0" -net nic,macaddr=00:16:3e:00:00:01 -net tap -nographic< / code > < / p >
< p > 我自闭了, ubuntu18根本没法联网, 于是我用了ubuntu14.0< / p >
2019-07-25 14:36:55 +00:00
< hr >
< h1 id = "0x04-在mips虚拟机中调试" > < a href = "#0x04-在mips虚拟机中调试" class = "headerlink" title = "0x04 在mips虚拟机中调试" > < / a > 0x04 在mips虚拟机中调试< / h1 > < p > 现在通过上面的配置我得到了这样一台虚拟机, 并通过ssh连接上去。< br > < figure class = "highlight shell" > < 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 > < / pre > < / td > < td class = "code" > < pre > < span class = "line" > root@debian-mipsel:/home/user/mi_wifi_r3_112# ifconfig< / span > < br > < span class = "line" > eth1 Link encap:Ethernet HWaddr 00:16:3e:00:00:01< / span > < br > < span class = "line" > inet addr:192.168.31.246 Bcast:192.168.31.255 Mask:255.255.255.0< / span > < br > < span class = "line" > inet6 addr: fe80::216:3eff:fe00:1/64 Scope:Link< / span > < br > < span class = "line" > UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1< / span > < br > < span class = "line" > RX packets:89377 errors:75 dropped:360 overruns:0 frame:0< / span > < br > < span class = "line" > TX packets:9114 errors:0 dropped:0 overruns:0 carrier:0< / span > < br > < span class = "line" > collisions:0 txqueuelen:1000< / span > < br > < span class = "line" > RX bytes:103978997 (99.1 MiB) TX bytes:924287 (902.6 KiB)< / span > < br > < span class = "line" > Interrupt:10 Base address:0x1020< / span > < br > < span class = "line" > < / span > < br > < span class = "line" > lo Link encap:Local Loopback< / span > < br > < span class = "line" > inet addr:127.0.0.1 Mask:255.0.0.0< / span > < br > < span class = "line" > inet6 addr: ::1/128 Scope:Host< / span > < br > < span class = "line" > UP LOOPBACK RUNNING MTU:16436 Metric:1< / span > < br > < span class = "line" > RX packets:8 errors:0 dropped:0 overruns:0 frame:0< / span > < br > < span class = "line" > TX packets:8 errors:0 dropped:0 overruns:0 carrier:0< / span > < br > < span class = "line" > collisions:0 txqueuelen:0< / span > < br > < span class = "line" > RX bytes:560 (560.0 B) TX bytes:560 (560.0 B)< / span > < br > < / pre > < / td > < / tr > < / table > < / figure > < / p >
2019-07-25 14:22:59 +00:00
< p > 已经把我的小米固件全部上传到这个虚拟机中< br > < figure class = "highlight shell" > < 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" > root@debian-mipsel:/home/user/mi_wifi_r3_112# ls< / span > < br > < span class = "line" > bin data dev etc extdisks lib libnvram-faker.so mnt opt overlay proc qemu-mipsel-static readonly rom root sbin sys tmp userdisk usr var www< / span > < br > < / pre > < / td > < / tr > < / table > < / figure > < / p >
< p > 和用户模式一样, 还是使用chroot, 因为目标二进制是和固件的库链接的, 很可能不能跟Debian的共享库一起工作。< br > < figure class = "highlight shell" > < 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 > < / pre > < / td > < td class = "code" > < pre > < span class = "line" > root@debian-mipsel:/home/user/mi_wifi_r3_112# chroot . ./usr/sbin/miniupnpd< / span > < br > < span class = "line" > Usage:< / span > < br > < span class = "line" > ./usr/sbin/miniupnpd [-f config_file] [-i ext_ifname] [-o ext_ip]< / span > < br > < span class = "line" > [-a listening_ip] [-p port] [-d] [-U] [-S] [-N]< / span > < br > < span class = "line" > [-u uuid] [-s serial] [-m model_number]< / span > < br > < span class = "line" > [-t notify_interval] [-P pid_filename]< / span > < br > < span class = "line" > [-B down up] [-w url] [-r clean_ruleset_interval]< / span > < br > < span class = "line" > [-A "permission rule"] [-b BOOTID]< / span > < br > < span class = "line" > < / span > < br > < span class = "line" > Notes:< / span > < br > < span class = "line" > There can be one or several listening_ips.< / span > < br > < span class = "line" > Notify interval is in seconds. Default is 30 seconds.< / span > < br > < span class = "line" > Default pid file is '/var/run/miniupnpd.pid'.< / span > < br > < span class = "line" > Default config file is '/etc/miniupnpd.conf'.< / span > < br > < span class = "line" > With -d miniupnpd will run as a standard program.< / span > < br > < span class = "line" > -S sets "secure" mode : clients can only add mappings to their own ip< / span > < br > < span class = "line" > -U causes miniupnpd to report system uptime instead of daemon uptime.< / span > < br > < span class = "line" > -N enables NAT-PMP functionality.< / span > < br > < span class = "line" > -B sets bitrates reported by daemon in bits per second.< / span > < br > < span class = "line" > -w sets the presentation url. Default is http address on port 80< / span > < br > < span class = "line" > -A use following syntax for permission rules :< / span > < br > < span class = "line" > (allow|deny) (external port range) ip/mask (internal port range)< / span > < br > < span class = "line" > examples :< / span > < br > < span class = "line" > "allow 1024-65535 192.168.1.0/24 1024-65535"< / span > < br > < span class = "line" > "deny 0-65535 0.0.0.0/0 0-65535"< / span > < br > < span class = "line" > -b sets the value of BOOTID.UPNP.ORG SSDP header< / span > < br > < span class = "line" > -h prints this help and quits.< / span > < br > < / pre > < / td > < / tr > < / table > < / figure > < / p >
< p > 直接运行起来, 还是只打印出usage, 这里我注意到之前忽视的地方< code > Default config file is ' /etc/miniupnpd.conf' .< / code > ,所以我不再使用< code > -f< / code > 参数来指定,而是把配置文件放在默认目录下,在小米路由器里,< code > ext_ifname< / code > 是外部ip, < code > listening_ip< / code > 是内部ip。但是我这里还没有开启两个, 所以都赋值为一张网卡。< br > < figure class = "highlight shell" > < 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" > ext_ifname=eth1< / span > < br > < span class = "line" > listening_ip=eth1< / span > < br > < span class = "line" > port=5351< / span > < br > < span class = "line" > enable_natpmp=yes< / span > < br > < span class = "line" > enable_upnp=yes< / span > < br > < span class = "line" > secure_mode=no< / span > < br > < span class = "line" > system_uptime=yes< / span > < br > < span class = "line" > lease_file=/tmp/upnp.leases< / span > < br > < span class = "line" > bitrate_down=8388608< / span > < br > < span class = "line" > bitrate_up=4194304< / span > < br > < span class = "line" > uuid=e1f3a0ec-d9d4-4317-a14b-130cdd18d092< / span > < br > < span class = "line" > allow 1024-65535 0.0.0.0/0 1024-65535< / span > < br > < span class = "line" > deny 0-65535 0.0.0.0/0 0-65535< / span > < br > < / pre > < / td > < / tr > < / table > < / figure > < / p >
< p > 在这个配置下, 运行miniupnp还是被告知< code > daemon(): No such file or directory< / code > < br > < figure class = "highlight plain" > < 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" > root@debian-mipsel:/home/user/mi_wifi_r3_112# chroot . ./usr/sbin/miniupnpd< / span > < br > < span class = "line" > root@debian-mipsel:/home/user/mi_wifi_r3_112# daemon(): No such file or directory< / span > < br > < / pre > < / td > < / tr > < / table > < / figure > < / p >
< p > 我起初猜测是因为缺乏< code > NVRAM< / code > < / p >
< blockquote >
< p > 在运行系统服务, 如Web服务器或UPnP守护进程时, 缺乏NVRAM。非易失性RAM通常是包含配置参数的设备快速存储器的一个分区。当一个守护进程启动时, 它通常会尝试查询NVRAM, 获取其运行时配置信息。有时一个守护进程会查询NVRAM的几十甚至上百个参数。< / p >
< / blockquote >
< p > 于是我运行二进制程序时, 使用LD_PRELOAD对nvram-faker库进行预加载。它会拦截通常由libnvram.so提供的< code > nvram_get()< / code > 调用。nvram-faker会查询你提供的一个INI风格的配置文件, 而不是试图查询NVRAM。< br > 这里有一个链接:< a href = "https://github.com/zcutlip/nvram-faker" target = "_blank" rel = "noopener" > https://github.com/zcutlip/nvram-faker< / a > < br > < figure class = "highlight shell" > < 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" > root@debian-mipsel:/home/user/mi_wifi_r3_112# chroot . /bin/sh -c "LD_PRELOAD=/libnvram-faker.so /usr/sbin/miniupnpd"< / span > < br > < span class = "line" > root@debian-mipsel:/home/user/mi_wifi_r3_112# daemon(): No such file or directory< / span > < br > < / pre > < / td > < / tr > < / table > < / figure > < / p >
< p > 问题依然存在, daemon是在miniupnpd中常出现的词, 猜测, 会不会某些函数没有实现? 这部分会比较麻烦, 需要反汇编。< br > 但是, 我们不是可以拿到路由器的shell吗! 干嘛还要用qemu模拟再调试, 直接上真机! < / p >
2019-07-25 14:36:55 +00:00
< hr >
< h1 id = "0x05-设备上调试程序" > < a href = "#0x05-设备上调试程序" class = "headerlink" title = "0x05 设备上调试程序" > < / a > 0x05 设备上调试程序< / h1 > < blockquote >
2019-07-25 14:22:59 +00:00
< p > 1、有shell权限< br > 2、有静态编译的gdbserver或者gdb< / p >
< / blockquote >
< p > 只要满足上面两个条件,我们就可以通过在路由器上运行< code > gdbserver_mipsle --attach 0.0.0.0:port PID< / code > 以及 在你的电脑上使用 < strong > gdb-multiarch< / strong > 进行调试(先指定架构, 然后使用remote功能)轻松地调试设备上地mips程序。< br > < figure class = "highlight plain" > < 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" > pwndbg> set architecture mips (但大多数情况下这一步可以省略, 似乎 pwndbg 能自动识别架构)< / span > < br > < span class = "line" > pwndbg> target remote localhost:1234< / span > < br > < / pre > < / td > < / tr > < / table > < / figure > < / p >
< p > 能根据固件中的bin得知这是一个小端mips指令集的设备, gdbserver也不用自己编译, 直接下载编译好的: < a href = "https://github.com/rapid7/embedded-tools/tree/master/binaries/gdbserver" target = "_blank" rel = "noopener" > https://github.com/rapid7/embedded-tools/tree/master/binaries/gdbserver< / a > < br > 把gdbserver.mipsbe通过tftp上传到路由器的/tmp目录下, 然后找到目标程序PID: < br > < figure class = "highlight plain" > < table > < tr > < td class = "gutter" > < pre > < span class = "line" > 1< / span > < br > < span class = "line" > 2< / span > < br > < span class = "line" > 3< / span > < br > < / pre > < / td > < td class = "code" > < pre > < span class = "line" > root@XiaoQiang:/# ps |grep miniupnp< / span > < br > < span class = "line" > 12517 root 1772 S grep miniupnp< / span > < br > < span class = "line" > 28284 root 1496 S /usr/sbin/miniupnpd -f /var/etc/miniupnpd.conf< / span > < br > < / pre > < / td > < / tr > < / table > < / figure > < / p >
< p > < strong > gdbserver attach< / strong > 这个进程,就可以通过< strong > gdb< / strong > 或者< strong > IDA< / strong > 远程调试这个程序< / p >
< / div >
< div >
< div style = "padding: 10px 0; margin: 20px auto; width: 90%; text-align: center;" >
< div > 您的支持将鼓励我继续创作!< / div >
< button id = "rewardButton" disable = "enable" onclick = "var qr = document.getElementById('QR'); if (qr.style.display === 'none') {qr.style.display='block';} else {qr.style.display='none'}" >
< span > 打赏< / span >
< / button >
< div id = "QR" style = "display: none;" >
< div id = "wechat" style = "display: inline-block" >
< img id = "wechat_qr" src = "/images/Wechatpay.png" alt = "Cool-Y 微信支付" >
< p > 微信支付< / p >
< / div >
< div id = "alipay" style = "display: inline-block" >
< img id = "alipay_qr" src = "/images/Alipay.png" alt = "Cool-Y 支付宝" >
< p > 支付宝< / p >
< / div >
< / div >
< / div >
< / div >
< footer class = "post-footer" >
< div class = "post-tags" >
< a href = "/tags/小米/" rel = "tag" > # 小米< / a >
< a href = "/tags/路由器/" rel = "tag" > # 路由器< / a >
< a href = "/tags/调试/" rel = "tag" > # 调试< / a >
< / div >
< div class = "post-nav" >
< div class = "post-nav-next post-nav-item" >
< a href = "/2019/07/24/获取固件/" rel = "next" title = "获取固件的几种方法" >
< i class = "fa fa-chevron-left" > < / i > 获取固件的几种方法
< / a >
< / div >
< span class = "post-nav-divider" > < / span >
< div class = "post-nav-prev post-nav-item" >
2019-10-25 13:13:53 +00:00
< a href = "/2019/10/25/PWNtw-start/" rel = "prev" title = "【Pwnable.tw】start" >
【Pwnable.tw】start < i class = "fa fa-chevron-right" > < / i >
< / a >
2019-07-25 14:22:59 +00:00
< / div >
< / div >
< / footer >
< / div >
< / article >
< div class = "post-spread" >
< / div >
< / div >
< / div >
< div class = "comments" id = "comments" >
< div id = "gitment-container" > < / div >
< / div >
< / div >
< div class = "sidebar-toggle" >
< div class = "sidebar-toggle-line-wrap" >
< span class = "sidebar-toggle-line sidebar-toggle-line-first" > < / span >
< span class = "sidebar-toggle-line sidebar-toggle-line-middle" > < / span >
< span class = "sidebar-toggle-line sidebar-toggle-line-last" > < / span >
< / div >
< / div >
< aside id = "sidebar" class = "sidebar" >
< div class = "sidebar-inner" >
< ul class = "sidebar-nav motion-element" >
< li class = "sidebar-nav-toc sidebar-nav-active" data-target = "post-toc-wrap" >
文章目录
< / li >
< li class = "sidebar-nav-overview" data-target = "site-overview-wrap" >
站点概览
< / li >
< / ul >
< section class = "site-overview-wrap sidebar-panel" >
< div class = "site-overview" >
< div class = "site-author motion-element" itemprop = "author" itemscope itemtype = "http://schema.org/Person" >
< img class = "site-author-image" itemprop = "image" src = "/images/avatar.png" alt = "Cool-Y" >
< p class = "site-author-name" itemprop = "name" > Cool-Y< / p >
< p class = "site-description motion-element" itemprop = "description" > 没人比我更懂中医#MAGA< / p >
< / div >
< nav class = "site-state motion-element" >
< div class = "site-state-item site-state-posts" >
< a href = "/archives/" >
2020-10-21 10:25:01 +00:00
< span class = "site-state-item-count" > 24< / span >
2019-07-25 14:22:59 +00:00
< span class = "site-state-item-name" > 日志< / span >
< / a >
< / div >
< div class = "site-state-item site-state-categories" >
< a href = "/categories/index.html" >
2019-10-15 11:24:26 +00:00
< span class = "site-state-item-count" > 7< / span >
2019-07-25 14:22:59 +00:00
< span class = "site-state-item-name" > 分类< / span >
< / a >
< / div >
< div class = "site-state-item site-state-tags" >
< a href = "/tags/index.html" >
2020-10-21 10:25:01 +00:00
< span class = "site-state-item-count" > 45< / span >
2019-07-25 14:22:59 +00:00
< span class = "site-state-item-name" > 标签< / span >
< / a >
< / div >
< / nav >
< div class = "links-of-author motion-element" >
< span class = "links-of-author-item" >
< a href = "https://github.com/Cool-Y" target = "_blank" title = "GitHub" >
< i class = "fa fa-fw fa-github" > < / i > GitHub< / a >
< / span >
< span class = "links-of-author-item" >
< a href = "mailto:cool.yim@whu.edu.cn" target = "_blank" title = "E-Mail" >
< i class = "fa fa-fw fa-envelope" > < / i > E-Mail< / a >
< / span >
< span class = "links-of-author-item" >
< a href = "https://www.instagram.com/yan__han/" target = "_blank" title = "Instagram" >
< i class = "fa fa-fw fa-instagram" > < / i > Instagram< / a >
< / span >
< / div >
2019-10-01 12:45:37 +00:00
< div id = "music163player" >
< iframe frameborder = "no" border = "0" marginwidth = "0" marginheight = "0" width = "330" height = "450" src = "//music.163.com/outchain/player?type=4&id=334277093&auto=1&height=430" > < / iframe >
< / div >
2019-07-25 14:22:59 +00:00
< / div >
< / section >
<!-- noindex -->
< section class = "post-toc-wrap motion-element sidebar-panel sidebar-panel-active" >
< div class = "post-toc" >
< div class = "post-toc-content" > < ol class = "nav" > < li class = "nav-item nav-level-1" > < a class = "nav-link" href = "#0x00-背景与简介" > < span class = "nav-text" > 0x00 背景与简介< / span > < / a > < / li > < li class = "nav-item nav-level-1" > < a class = "nav-link" href = "#REF" > < span class = "nav-text" > REF< / span > < / a > < / li > < li class = "nav-item nav-level-1" > < a class = "nav-link" href = "#0x01-基础条件" > < span class = "nav-text" > 0x01 基础条件< / span > < / a > < / li > < li class = "nav-item nav-level-1" > < a class = "nav-link" href = "#0x02-qemu-用户模式" > < span class = "nav-text" > 0x02 qemu-用户模式< / span > < / a > < ol class = "nav-child" > < li class = "nav-item nav-level-2" > < a class = "nav-link" href = "#模拟miniupnp" > < span class = "nav-text" > 模拟miniupnp< / span > < / a > < / li > < / ol > < / li > < li class = "nav-item nav-level-1" > < a class = "nav-link" href = "#0x03-qemu-系统模式" > < span class = "nav-text" > 0x03 qemu-系统模式< / span > < / a > < ol class = "nav-child" > < li class = "nav-item nav-level-2" > < a class = "nav-link" href = "#MIPS系统网络配置" > < span class = "nav-text" > MIPS系统网络配置< / span > < / a > < / li > < / ol > < / li > < li class = "nav-item nav-level-1" > < a class = "nav-link" href = "#0x04-在mips虚拟机中调试" > < span class = "nav-text" > 0x04 在mips虚拟机中调试< / span > < / a > < / li > < li class = "nav-item nav-level-1" > < a class = "nav-link" href = "#0x05-设备上调试程序" > < span class = "nav-text" > 0x05 设备上调试程序< / span > < / a > < / li > < / ol > < / div >
< / div >
< / section >
<!-- /noindex -->
< / div >
< / aside >
< / div >
< / main >
< footer id = "footer" class = "footer" >
< div class = "footer-inner" >
2020-10-21 10:25:01 +00:00
< div class = "copyright" > © 2019 — < span itemprop = "copyrightYear" > 2020< / span >
2019-07-25 14:22:59 +00:00
< span class = "with-love" >
< i class = "fa fa-user" > < / i >
< / span >
< span class = "author" itemprop = "copyrightHolder" > Cool-Y< / span >
< span class = "post-meta-divider" > |< / span >
< span class = "post-meta-item-icon" >
< i class = "fa fa-area-chart" > < / i >
< / span >
2020-10-21 10:25:01 +00:00
< span title = "Site words total count" > 74.5k< / span >
2019-07-25 14:22:59 +00:00
< / div >
< div class = "powered-by" > 由 < a class = "theme-link" target = "_blank" href = "https://hexo.io" > Hexo< / a > 强力驱动< / div >
< div class = "busuanzi-count" >
< script async src = "//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" > < / script >
< span class = "site-uv" >
< i class = "fa fa-user" > < / i >
< span class = "busuanzi-value" id = "busuanzi_value_site_uv" > < / span >
< / span >
< span class = "site-pv" >
< i class = "fa fa-eye" > < / i >
< span class = "busuanzi-value" id = "busuanzi_value_site_pv" > < / span >
< / span >
< / div >
< / div >
< / footer >
< div class = "back-to-top" >
< i class = "fa fa-arrow-up" > < / i >
< / div >
< / div >
< script type = "text/javascript" >
if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
window.Promise = null;
}
< / script >
< script type = "text/javascript" src = "/lib/jquery/index.js?v=2.1.3" > < / script >
< script type = "text/javascript" src = "/lib/fastclick/lib/fastclick.min.js?v=1.0.6" > < / script >
< script type = "text/javascript" src = "/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7" > < / script >
< script type = "text/javascript" src = "/lib/velocity/velocity.min.js?v=1.2.1" > < / script >
< script type = "text/javascript" src = "/lib/velocity/velocity.ui.min.js?v=1.2.1" > < / script >
< script type = "text/javascript" src = "/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5" > < / script >
< script type = "text/javascript" src = "/js/src/utils.js?v=5.1.4" > < / script >
< script type = "text/javascript" src = "/js/src/motion.js?v=5.1.4" > < / script >
2019-08-09 03:54:43 +00:00
< script type = "text/javascript" src = "/js/src/affix.js?v=5.1.4" > < / script >
< script type = "text/javascript" src = "/js/src/schemes/pisces.js?v=5.1.4" > < / script >
2019-07-25 14:22:59 +00:00
< script type = "text/javascript" src = "/js/src/scrollspy.js?v=5.1.4" > < / script >
< script type = "text/javascript" src = "/js/src/post-details.js?v=5.1.4" > < / script >
< script type = "text/javascript" src = "/js/src/bootstrap.js?v=5.1.4" > < / script >
<!-- LOCAL: You can save these files to your site and update links -->
< link rel = "stylesheet" href = "https://jjeejj.github.io/css/gitment.css" >
< script src = "https://jjeejj.github.io/js/gitment.js" > < / script >
<!-- END LOCAL -->
< script type = "text/javascript" >
function renderGitment(){
var gitment = new Gitment({
id: window.location.pathname,
owner: 'Cool-Y',
repo: 'gitment-comments',
oauth: {
client_secret: '1c5db4da72df5e6fc318d12afe5f4406f7c54343',
client_id: '180955a2c3ae3d966d9a'
}});
gitment.render('gitment-container');
}
renderGitment();
< / script >
< script type = "text/javascript" >
// Popup Window;
var isfetched = false;
var isXml = true;
// Search DB path;
var search_path = "search.xml";
if (search_path.length === 0) {
search_path = "search.xml";
} else if (/json$/i.test(search_path)) {
isXml = false;
}
var path = "/" + search_path;
// monitor main search box;
var onPopupClose = function (e) {
$('.popup').hide();
$('#local-search-input').val('');
$('.search-result-list').remove();
$('#no-result').remove();
$(".local-search-pop-overlay").remove();
$('body').css('overflow', '');
}
function proceedsearch() {
$("body")
.append('< div class = "search-popup-overlay local-search-pop-overlay" > < / div > ')
.css('overflow', 'hidden');
$('.search-popup-overlay').click(onPopupClose);
$('.popup').toggle();
var $localSearchInput = $('#local-search-input');
$localSearchInput.attr("autocapitalize", "none");
$localSearchInput.attr("autocorrect", "off");
$localSearchInput.focus();
}
// search function;
var searchFunc = function(path, search_id, content_id) {
'use strict';
// start loading animation
$("body")
.append('< div class = "search-popup-overlay local-search-pop-overlay" > ' +
'< div id = "search-loading-icon" > ' +
'< i class = "fa fa-spinner fa-pulse fa-5x fa-fw" > < / i > ' +
'< / div > ' +
'< / div > ')
.css('overflow', 'hidden');
$("#search-loading-icon").css('margin', '20% auto 0 auto').css('text-align', 'center');
$.ajax({
url: path,
dataType: isXml ? "xml" : "json",
async: true,
success: function(res) {
// get the contents from search data
isfetched = true;
$('.popup').detach().appendTo('.header-inner');
var datas = isXml ? $("entry", res).map(function() {
return {
title: $("title", this).text(),
content: $("content",this).text(),
url: $("url" , this).text()
};
}).get() : res;
var input = document.getElementById(search_id);
var resultContent = document.getElementById(content_id);
var inputEventFunction = function() {
var searchText = input.value.trim().toLowerCase();
var keywords = searchText.split(/[\s\-]+/);
if (keywords.length > 1) {
keywords.push(searchText);
}
var resultItems = [];
if (searchText.length > 0) {
// perform local searching
datas.forEach(function(data) {
var isMatch = false;
var hitCount = 0;
var searchTextCount = 0;
var title = data.title.trim();
var titleInLowerCase = title.toLowerCase();
var content = data.content.trim().replace(/< [^>]+>/g,"");
var contentInLowerCase = content.toLowerCase();
var articleUrl = decodeURIComponent(data.url);
var indexOfTitle = [];
var indexOfContent = [];
// only match articles with not empty titles
if(title != '') {
keywords.forEach(function(keyword) {
function getIndexByWord(word, text, caseSensitive) {
var wordLen = word.length;
if (wordLen === 0) {
return [];
}
var startPosition = 0, position = [], index = [];
if (!caseSensitive) {
text = text.toLowerCase();
word = word.toLowerCase();
}
while ((position = text.indexOf(word, startPosition)) > -1) {
index.push({position: position, word: word});
startPosition = position + wordLen;
}
return index;
}
indexOfTitle = indexOfTitle.concat(getIndexByWord(keyword, titleInLowerCase, false));
indexOfContent = indexOfContent.concat(getIndexByWord(keyword, contentInLowerCase, false));
});
if (indexOfTitle.length > 0 || indexOfContent.length > 0) {
isMatch = true;
hitCount = indexOfTitle.length + indexOfContent.length;
}
}
// show search results
if (isMatch) {
// sort index by position of keyword
[indexOfTitle, indexOfContent].forEach(function (index) {
index.sort(function (itemLeft, itemRight) {
if (itemRight.position !== itemLeft.position) {
return itemRight.position - itemLeft.position;
} else {
return itemLeft.word.length - itemRight.word.length;
}
});
});
// merge hits into slices
function mergeIntoSlice(text, start, end, index) {
var item = index[index.length - 1];
var position = item.position;
var word = item.word;
var hits = [];
var searchTextCountInSlice = 0;
while (position + word.length < = end & & index.length != 0) {
if (word === searchText) {
searchTextCountInSlice++;
}
hits.push({position: position, length: word.length});
var wordEnd = position + word.length;
// move to next position of hit
index.pop();
while (index.length != 0) {
item = index[index.length - 1];
position = item.position;
word = item.word;
if (wordEnd > position) {
index.pop();
} else {
break;
}
}
}
searchTextCount += searchTextCountInSlice;
return {
hits: hits,
start: start,
end: end,
searchTextCount: searchTextCountInSlice
};
}
var slicesOfTitle = [];
if (indexOfTitle.length != 0) {
slicesOfTitle.push(mergeIntoSlice(title, 0, title.length, indexOfTitle));
}
var slicesOfContent = [];
while (indexOfContent.length != 0) {
var item = indexOfContent[indexOfContent.length - 1];
var position = item.position;
var word = item.word;
// cut out 100 characters
var start = position - 20;
var end = position + 80;
if(start < 0 ) {
start = 0;
}
if (end < position + word . length ) {
end = position + word.length;
}
if(end > content.length){
end = content.length;
}
slicesOfContent.push(mergeIntoSlice(content, start, end, indexOfContent));
}
// sort slices in content by search text's count and hits' count
slicesOfContent.sort(function (sliceLeft, sliceRight) {
if (sliceLeft.searchTextCount !== sliceRight.searchTextCount) {
return sliceRight.searchTextCount - sliceLeft.searchTextCount;
} else if (sliceLeft.hits.length !== sliceRight.hits.length) {
return sliceRight.hits.length - sliceLeft.hits.length;
} else {
return sliceLeft.start - sliceRight.start;
}
});
// select top N slices in content
var upperBound = parseInt('1');
if (upperBound >= 0) {
slicesOfContent = slicesOfContent.slice(0, upperBound);
}
// highlight title and content
function highlightKeyword(text, slice) {
var result = '';
var prevEnd = slice.start;
slice.hits.forEach(function (hit) {
result += text.substring(prevEnd, hit.position);
var end = hit.position + hit.length;
result += '< b class = "search-keyword" > ' + text.substring(hit.position, end) + '< / b > ';
prevEnd = end;
});
result += text.substring(prevEnd, slice.end);
return result;
}
var resultItem = '';
if (slicesOfTitle.length != 0) {
resultItem += "< li > < a href = '" + articleUrl + "' class = 'search-result-title' > " + highlightKeyword(title, slicesOfTitle[0]) + "< / a > ";
} else {
resultItem += "< li > < a href = '" + articleUrl + "' class = 'search-result-title' > " + title + "< / a > ";
}
slicesOfContent.forEach(function (slice) {
resultItem += "< a href = '" + articleUrl + "' > " +
"< p class = \"search-result\" > " + highlightKeyword(content, slice) +
"...< / p > " + "< / a > ";
});
resultItem += "< / li > ";
resultItems.push({
item: resultItem,
searchTextCount: searchTextCount,
hitCount: hitCount,
id: resultItems.length
});
}
})
};
if (keywords.length === 1 & & keywords[0] === "") {
resultContent.innerHTML = '< div id = "no-result" > < i class = "fa fa-search fa-5x" / > < / div > '
} else if (resultItems.length === 0) {
resultContent.innerHTML = '< div id = "no-result" > < i class = "fa fa-frown-o fa-5x" / > < / div > '
} else {
resultItems.sort(function (resultLeft, resultRight) {
if (resultLeft.searchTextCount !== resultRight.searchTextCount) {
return resultRight.searchTextCount - resultLeft.searchTextCount;
} else if (resultLeft.hitCount !== resultRight.hitCount) {
return resultRight.hitCount - resultLeft.hitCount;
} else {
return resultRight.id - resultLeft.id;
}
});
var searchResultList = '< ul class = \"search-result-list\" > ';
resultItems.forEach(function (result) {
searchResultList += result.item;
})
searchResultList += "< / ul > ";
resultContent.innerHTML = searchResultList;
}
}
if ('auto' === 'auto') {
input.addEventListener('input', inputEventFunction);
} else {
$('.search-icon').click(inputEventFunction);
input.addEventListener('keypress', function (event) {
if (event.keyCode === 13) {
inputEventFunction();
}
});
}
// remove loading animation
$(".local-search-pop-overlay").remove();
$('body').css('overflow', '');
proceedsearch();
}
});
}
// handle and trigger popup window;
$('.popup-trigger').click(function(e) {
e.stopPropagation();
if (isfetched === false) {
searchFunc(path, 'local-search-input', 'local-search-result');
} else {
proceedsearch();
};
});
$('.popup-btn-close').click(onPopupClose);
$('.popup').click(function(e){
e.stopPropagation();
});
$(document).on('keyup', function (event) {
var shouldDismissSearchPopup = event.which === 27 & &
$('.search-popup').is(':visible');
if (shouldDismissSearchPopup) {
onPopupClose();
}
});
< / script >
< script src = "https://cdn1.lncld.net/static/js/av-core-mini-0.6.4.js" > < / script >
< script > AV . initialize ( "EWwoJgHNdlj6iBjiFlMcabUO-gzGzoHsz" , "x8FxDrYG79C8YFrTww9ljo8K" ) ; < / script >
< script >
function showTime(Counter) {
var query = new AV.Query(Counter);
var entries = [];
var $visitors = $(".leancloud_visitors");
$visitors.each(function () {
entries.push( $(this).attr("id").trim() );
});
query.containedIn('url', entries);
query.find()
.done(function (results) {
var COUNT_CONTAINER_REF = '.leancloud-visitors-count';
if (results.length === 0) {
$visitors.find(COUNT_CONTAINER_REF).text(0);
return;
}
for (var i = 0; i < results.length ; i + + ) {
var item = results[i];
var url = item.get('url');
var time = item.get('time');
var element = document.getElementById(url);
$(element).find(COUNT_CONTAINER_REF).text(time);
}
for(var i = 0; i < entries.length ; i + + ) {
var url = entries[i];
var element = document.getElementById(url);
var countSpan = $(element).find(COUNT_CONTAINER_REF);
if( countSpan.text() == '') {
countSpan.text(0);
}
}
})
.fail(function (object, error) {
console.log("Error: " + error.code + " " + error.message);
});
}
function addCount(Counter) {
var $visitors = $(".leancloud_visitors");
var url = $visitors.attr('id').trim();
var title = $visitors.attr('data-flag-title').trim();
var query = new AV.Query(Counter);
query.equalTo("url", url);
query.find({
success: function(results) {
if (results.length > 0) {
var counter = results[0];
counter.fetchWhenSave(true);
counter.increment("time");
counter.save(null, {
success: function(counter) {
var $element = $(document.getElementById(url));
$element.find('.leancloud-visitors-count').text(counter.get('time'));
},
error: function(counter, error) {
console.log('Failed to save Visitor num, with error message: ' + error.message);
}
});
} else {
var newcounter = new Counter();
/* Set ACL */
var acl = new AV.ACL();
acl.setPublicReadAccess(true);
acl.setPublicWriteAccess(true);
newcounter.setACL(acl);
/* End Set ACL */
newcounter.set("title", title);
newcounter.set("url", url);
newcounter.set("time", 1);
newcounter.save(null, {
success: function(newcounter) {
var $element = $(document.getElementById(url));
$element.find('.leancloud-visitors-count').text(newcounter.get('time'));
},
error: function(newcounter, error) {
console.log('Failed to create');
}
});
}
},
error: function(error) {
console.log('Error:' + error.code + " " + error.message);
}
});
}
$(function() {
var Counter = AV.Object.extend("Counter");
if ($('.leancloud_visitors').length == 1) {
addCount(Counter);
} else if ($('.post-title-link').length > 1) {
showTime(Counter);
}
});
< / script >
< script >
(function(){
var bp = document.createElement('script');
var curProtocol = window.location.protocol.split(':')[0];
if (curProtocol === 'https') {
bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
}
else {
bp.src = 'http://push.zhanzhang.baidu.com/push.js';
}
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(bp, s);
})();
< / script >
< / body >
< / html >