From 774d32afc1663541d68530ad05ad3389df08d1b5 Mon Sep 17 00:00:00 2001 From: 0chen Date: Sat, 22 Jan 2022 02:06:37 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=9F=9F=E5=90=8D=E6=A8=A1?= =?UTF-8?q?=E7=B3=8A=E5=8C=B9=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 增加了域名模糊匹配功能,考虑到部分用户对这个功能需求不强,于是单独开了一个页面,感知不强。不会影响正常体验。 另外将包名一律修改成为小写,规范化了代码。 同时为多处功能添加注释,删除了一些不必要的代码。优化了部分代码。 --- README.md | 29 ++- build.gradle | 2 +- img/similarDomain.png | Bin 0 -> 40361 bytes src/burp/BurpExtender.java | 26 ++- src/{Domain => domain}/DomainConsumer.java | 10 +- src/{Domain => domain}/DomainProducer.java | 182 +++++++++++++-- src/{UI => ui}/BurpDomain.java | 250 +++++++++++++++------ src/{UI => ui}/ControlSwitch.java | 7 +- src/{UI => ui}/NewProject.java | 2 +- src/{Utils => utils}/Config.java | 3 +- src/{Utils => utils}/DBUtil.java | 241 ++++++++++++++++++-- 11 files changed, 616 insertions(+), 136 deletions(-) create mode 100644 img/similarDomain.png rename src/{Domain => domain}/DomainConsumer.java (76%) rename src/{Domain => domain}/DomainProducer.java (59%) rename src/{UI => ui}/BurpDomain.java (64%) rename src/{UI => ui}/ControlSwitch.java (98%) rename src/{UI => ui}/NewProject.java (99%) rename src/{Utils => utils}/Config.java (98%) rename src/{Utils => utils}/DBUtil.java (69%) diff --git a/README.md b/README.md index fcd1c6e..61669fe 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,10 @@ 当使用burp代理时,会从经过burp的流量中抓取域名进行储存。不需要开启,插件启动以及数据库连接之后就会自动拉取。 +* 相似域名模糊匹配 + +会对相似的域名进行匹配,符合正则的就拉取入库 + * 支持mysql/sqlite 我们打算思考一下这个工具与后期其他工具的联动,故而默认选择了mysql作为数据库,根据鸭王的反馈,我们又添加了sqlite作为支持。 @@ -27,6 +31,8 @@ ### TODO LIST - [x] 支持sqlite +- [x] 相似域名模糊匹配 +- [ ] url的后缀名筛选 - [ ] 由于仓促赶时间,所以当前的代码可读性是非常差的,会找个时间重构一下代码。 ## 使用方法 @@ -59,10 +65,29 @@ ![](img/passiveCollection.png) -### 0x04 工具特点 +### 0x04 相似域名收集 + +使用如下代码进行相似域名匹配,正则在其中。各位有更优秀的正则可以提交issue,届时我们采纳使用。感谢。 + +```java +for(String s:BurpExtender.currentRootDomainSet){ + //思路:考虑将rootdomain进行切割,例如baidu.com使用切割成baidu com,然后对baidu进行相似度匹配 + String[] tmp = s.split("\\."); + //通过切割的长度取需要匹配的部分,通过这个来避免当用户设置根域名为www.baidu.com的时候,会匹配成www,baidu的问题,目前直接取baidu,com + String similarRegex = String.format("((?!-)[A-Za-z0-9-]{1,63}(?)h16n;r2Ww>Ot|TH9t37pwZw{82;s!*v_7hsNuqZ4GNqHb5 zE`AWIgaia8q*Qir5g9S3I0ihaQJ)}jNN_t6mTmbdG`+FK?dkc7&(znuuakav8&6X{ zJa5P#4Mb|h(qZPH(tDOLVtxYUvn=)M>ueyPxWb@{!ZBlLus{0xfxGdMJ0X3mL-FhcV;tuVZfh6oYr>uwx0cFXH~J= z#(|J1vJ3YjT6TxA(&IyO1d4V@MGu>8O6cRhRhC6}8g0UoQ7I54oQ{$k^G&XWaS9 zhmsp4?vUunCBCDN`d<7f`}}Ewd2AhF-*IXhG5yq-bzaCbUId~Jw7C~sn`{6plyplN z%F=Dvl`QWlm_yV6jVnY}${sIbe7li;qI@xZaS=p*Yhz{ag3;_yQB-#0y88xvlqFC2 z{A;t9VZS}ddrt5I=YY*JE!aSLLXb&p9TVfjDrA9|AW-prLlMw&Fogp6*gziDd;v$O z^Ip9B5MmT0lV0auFug>mP$SGyP&^SqYKXO7Mr9;g5sq?5sXnI}u&F@!ZPr#K?>>SH z6og>Z3$)k}WFxd-Vtny%>O|UN$Rn}RL=N!~JrW0M6u2;x0#9n#T`?1C=v4?zQ3_=q zSCr2o{y~Z&*ael!M6N{df`NSh-;hU@iN+E;L&a zYJwAbCodrHd3~V?Lk;`UsRNTmX$rrn98$j3}mZ10)TJBa3rcU!2ZXwcI%&pMA z5K5(1Ie%809a2Fer|9FX{|^{;_%5_AB>hlEsijXjvmbxx{vf&Ge&h>}RT;@N$z?{6 zXQza1giA@F8NwgV9n|Yz?~64OG^*F8s3KVeJ&B0xqcm--mss{&rnKd2M&^tC*t_HS znOiLvo)Knb(0u#K$;VO3@w?MYE9yE`Cx!vML)=~8$nL|vo-a)|VF1!rLO^^z`6${A ztYRoJSWaEIvOKr=2eNhYSQN@AXK}Gl@GQBR^6S#{WSnSBs6?n+GBPqp(mb+Z(wD`Y z(rGdTDea^jb_ULaJD*Tq-JLRd6Ag z7>Q1y@=m#ELVxS0&QH}Q#k5^^w9)m%PA#YK! z`uaUnd9*q&N7{SIv*LK0N}DIEm?mWFyAMjoILG2Y_K(?*_!lXT=Uma1_TEa}+;t7d zMxITPWz%xq1}tYe%Ta+=-afm(^tP0L-mlcp0*6hCty?E;C6H$<*FMi`(@4;)& zuIAEa{I!?nyHjfSm^02bw`IRZk2>sCuGIvdA3TG6r*1d}G&8|g5?|=zaiow(e#Kkj z3-PV+nR63(JPxd^^9;3ZdbuX;kWPIPiwW0v)yrgr)`!xssJX0x)`Q;ovXN=8VXw5| zwy|;^v5`L?cQkfGcC$p7PAHm?LP#X=k$=g%*{876w+pV*yYrxntn+JE{{4@8@(1?& z*r(M8i>Kx%<7cqv<|jmEb{u+10@L-azJTfgOAs1j`U3uKs{)w<<~lo;&gFp1_@RXK zA51$;R}Mo2_c9fT2T2&ec=!h>Y@DbO>mR2XK+QK)i9OFPblZ82KcYc{nVoP zv#2!axY#<_4=m$!pUJJ6y^U{Hf1I#bvvg)IYU|mWo$f40m2Ap+Fc3sF#(Yia=$LR^ zIX2hIsAN#m_jeDQfIEyvzs$TZzkj^1oglWrbRi8&s^c=wJs4Y^^d57!{Arfpq{mH> z`#p*=iXy5=hEawudAQYnUGrKvjIK=$)!Qx-Vt8w8XrH`@jq5@Em&D$+B&HUeEwjB>z zw=Fy`Y}m*z+Ui{Mf2BJ4ZtKcP*Fh%5XK6Y$^Zs!)`ZcZ zI5m#TnZZTQdCMVs^;>#bQVWU0J@gjQyQ`Axum|v*k6c=>k*`U2rqftC3_i`iOh(vx zbYJM{8J^z{(zf5GEGU@^DcC8jud3M^b_U?N;{~j3oY}A0$nDEE$cB5+Z_ak6v^N@k zf6}LO*Jo&As9slCXV?_b#?oGFmvWeH7BKwUcHlwFPn&)F`R7K%-JalW_v_2~6CNE0 zEj(Qh{x(6Y$IP9POPYv=6-P5~#=(V-<RkeJJl-WSuG>E zKF+!J?B#{Y&CuFMl8*uzV2t{0r!EgB*j*>jm>G1IHN5%)ZgK9_2kkGv4(&V6Q@Bp; zb5HAkT6G^eHa0EQw^Tc*Y_<8fyu!D1+Us{uw)(wHCG+`tkezShMdIOfj&yT*3;lY{ zfzCpvB(nDm^-{mkzI8f6|3#(IgZs9~{z1soeblD>$!d8%VxVd#qbJ7yjW_u&_POe& zZSlHYi zqENY+FuiN<#PLQzghgC=oQ|rR^H@II`Wc1y2JGs*2$L1f4a_Z8p2a!|7IZ%#JjfU+Af}nVRrzJtDLBRj`9Eg!4tUw_CJVz0D|NSEkynbKvuXnHl zu)ofLswn{fD-DYB`&40k)o;KXtfRD!3kV22`tKJgNOmp`@D+%RxQMzZ=;=p~0*t1| zy8w)|Qc?+&Auuge2nh+up>Wb*Ey$tZE@QEw%{pxLs>n!v`emP?a1-z~OggM+QVHSN zN({`#H#YiKjJu@tI&GuAOSB~}iLsoaNvM|4nBl>a<}Y+=~# zR@rm*7r4&W+gvIg4m4c;I3s9|Ou6w!Jz0{J80?>p2P$GUqt`6iPcV^z|L-G}7&Hq^ zu1=*m`TzYraNT}>pnTASC2iC{m ze3xP1U176SlQihi{cu>CWB)Fy>Unyz%SY&<7d$N^g}yKG!|bP_Eon`M`BDYv^oiO{ z*Lj7RDSp2xnhj37l?L;zZa<=c=gZuZl3bu*0T8cc`Tp;;?5A+%k3^lUb39wD$`3Vl z?cByFGK_d-rqa$9a#787mBWr4I?gyH(>{7^X0aHr*|oepUr*CbsHVfNyHC4kPC`i2 z+}Pdd)fx2xckMZEKRK@(KssA(TC>de>wbHElD}aJVK0p;Q~dZI%8fJ(qq%hasZJF!30)PGdXQC&#q0x9FAZtP-!}g%`%?h$L*TKmPL-; z>9i>HXRMmfeBr)NXDwgfURwI$=-3@LeP;?pc(`il;#NFc>^BU2FNbnVBv>0n3zZ~E zf2sXh!{gz??xnpYav8hT*ZV0-uP26Y-WPq)J~uy{?sp=DUT)@bcZq$-Ddz5D#5G@m z271-;BEgge0Sma>3J}uhosr4(5({f%l{d01!7ZKU$yzI|?YxrxKJ`(F|8mgl`tX3B z`5<=eg~~Ga$hFW+(|&%YgR%3X-{-vT`>Yg^!rv9@?7bND`}Wl>n~w`xhAKMg&{VmO zqR#2gUB}HnNCUQE+OmZXE^CCo7kz9N6GkiH5~sj z?8^>b4;&^kS^D5KoqK7*HcvD;De`0%VrTlD84A3H+pCdD5k=5o$&y#`)TX#s?D{k z{qA5?&+FrfaRk9_Lcnu~)X|D%{^Wc%J2yLl%LGgH`=NQNERG>Cr(9oh-|6--qKjtlXx9;NE_r-1vi@xJ$_tTPLfI>R(>!Y-GUkU|_ z@$-gb7A}u7xt7{Jn_c^+_lXL19EbgSD~v&p#D_b9yY+eQijTfmV`aI{vOWGU%(3t6 zDh@Y&etrx-ERAg0^p0`=zHtSGXKUn>5i?tji>~VAv1{tD| z3V;Y zzp&Y9{w4xVaC6!?JqH?W_ihaDlqxk+B-(za-R;BxhzhR8sD>m&j-DYSR;1me4{gr3 zK9jpdt?aOnGE5#?5Zs@4{A_?Ro2XDJf_nW{)q3H>ahGZc`R+VX42kD@g3U{H#%jyw zXP2Pg;#q~2C z>#ikseI#TB{xtD2X&w}HN-$<; z4_(BU$8@e57%Xmbgpi4_=cp73tr?KUg9X6j#BnSx`#+u8EPM`&%1=LDX)L30ohz21 zr-m`z*h38f8nnJuST_$<3f~E00KU=O0RKH=96NuKSBl?h{fL3ouPRd%oL6hBtzdF_k?|M9}$nU^B`T9 z`PlDr2-}mH<BP0g+KSvFM##u5SIic~KR5cDK5D5XJSKiAh z3OU81FoJv)G7F4kw2{cu)mNs3cO1v9d+~dYEQD{i1f+5=kH31JujI7G*aybEr}6}z zeiS80P6LgV!8V)u(FpdVpdWAL`pfMaGT*zL!%RCp$3Dnk#|s1WFrn;ehOLe}fUh1K z$8W5P$>6-wh4@uxY7p@9i=9`F!#474t);9wt{?DO;_FcLqTgU9vvMz)2*z$1v5RyG z5ae%IiiST)#CS3(WVYYyk2<{5LK3J(af=!)o}S3%K@Srd-{{L-Sc;BzL6$rx6Uy4+ z(HHlBWT%VaJI=PLi7H~53PcvTL2+@)F0z=+?$%67H$gEfgaPeQc5gBpr!nxULSD9hp4pRK4O4*4cV$mi+nv~h^+jK2UJ&8- zjqY-mSAdyfkkvhys(pTol_qoyZn1>DHE7wH;kk}Dbm(~*7LarAsekraF*lb(a8EXR z^JrXi-fMVLQhGO=-><`=igZ7I4-#_cpy&58V(ztlRZoum+ki`z%A9b!>JN-Rm@dk>kXO)PY$PmI5h>dn*QV#d5|)bmF%Ef_)iqce zE?DiRSGNl(gG8pCe5b52OFu*o&B*n%P(t-H(0MIHr`Ue%#xMAs(K8p+RG1Fdd67qWoxP|&+8xm`a( zIA9&Fg}pPc$QO46FKiSh6SI`SW0R~QNh!~cdrdgc+bKoSG30aBwDic(zha;c>VsGv z0F04ya9?O@1aOK2g)3QH#$_X9DQ|tSHQ8d4usfT1J9TfrnuLG%AnCF4w6Qz57llI| zkh7&rpXaoqnW#-d3K7cRx0Dt2j)^sTqjbRWXh+BX;$pPKy2pF;u1>7=Ld zLRmof$Y74z1}enFm9eE%XUO~^*Za6)-@Mm2Dwu&am{9@49#bCYBdBid{KMl{{j~iB&vw_kG+x)BgA|e{=|k>12W|7tar> ze&8bx^lt_hQ>Hpude3;BeB7jyKi{}jS59w1x{ciJ8C4|@E!ICI(c~_Wyad+93gJLS z)EfDH#mU&JeU1>Ew2Tlr6!o7koA0iIXCA&R7=f9xh$r&DC#lh!aKt%Uz8tXdedMta zao=HXb|gkdhtfkK#m!1;(1pBaxx?tnuCygIaqp8B)v|PsiAx|H(loK?q~trnz%aV( zm&|>++sbFAA)~$Y&Vz>I4N0|BE>?cQ_*Z-$^jW%~p;Q=));6W@hvSmI2O=SVCN9*p z++t}JSd=mhR`+IB33tB$;& z?_efpBQPneP2t=w9~ng7Vfjpa<~b#zV-|ASDL$%SLmQ)n&!PB83*nQY`=vS_&uXBL zai0ruN_@<@s@E6NGfF|rczD7Bs|xS=#3syms3(E@1I=8ma?}%@GrEp|A7D#ZAxLh; z!OtwQ>%P~M^yav{zSW*``8$*6-%BL@h5E<>HzdQswc=p^u%KoM+g^mmSVGk5WeLn# z{E*VFpQqb8!G1X;VAZyeuroijA3yl*zR+e;;Gb}*sxmbu<<>=!Y~KZ(&xaOrFLSAO zH>s?>z-#78za=H@xRAdn`iu~Gh#MG6#EnB zrVW$`Uh5^I+o$Ya;U^ru9u8eK?n>Rr&c_jB)XpVXtPx6+)4)TtRTF4-V}p<#fo;p3 zp!jQ09~w_ki<$;%BPUS&cHV$n9usIf^bl+?Jf;iL-up;_*^en?5!HRmps%rqi}&ADK%(a`o#Pu!b9_7eN!(QY491N1I=;E`>JZNTvxv=>H1NJ>6FU!G@c zx$}Qs0W+F6#U5Dwfh_{&o|0uY5wbxq@r-8Pkf$C88$Fx#0N0G%KVhrQWW2qd;6NGp zt;Sb=9OLys9Fu?QLiLNgFkF*o2!kjX=gG^{)|+^){B##zAcO^ zI!HHc? zmIc^93;{KkzVDq1%^R*U-jo)%r%$@kPY#XIvqGz@N4LA5=I&(gH91jE$@P9c^-S(U z?KX5+$>Rj!D(*aYwhd)2elO?C`RJD&xLZ~mi_Gl#HoVY+;HV>O-#dcl`=g9M!inQ% zfd2;%U3wH^vyqKS<21)y$11Dw0L40tao+S?FSh5F-`$SN*VdhGwGrxAzZs>|;W~l{ zQ|ip_hNiG;xpRvCVReG2Z%Tj8*~{l3oLL}E>h^GBvl0;7?y2ilVyGC=bsEJjf1>3D z`o_eC@CyUVN2@0adIT&V@tQ>zsFCC#X!KIZX@@b~r~ycWBL;Ep)y3vrj3cD8C}$2N zcQm0Ab^P;o#ZLnTHod|;6jOL|EcV>SSd&)4OH@qHt7Ei-hg--T;!JmDTvnn3X|*>a z9VdqVOWtRefKOQyg$$XMn*ncrQ|>#;Zw2M4WFa^@ghmmN+=|e-Hdg9z?!ed*n<6^i zR5t`DMzr|f#{X#T=A!3>zTYC;Zm zk~n?1ygyn}r7d6Y_YziK(c36OaP2xUNVkz2{oMkwW_`bZ^tgqdCT1~wpY67P1FjeW z3<5Ev*#LUMk-3M0(cIqtphjZ+N5csWB6ocx z+%VQ-;@0bRE^B1~k3KBEuY-3HJ`?GZZvP~hGAn7As^{_UXTq=RShlHc^E@8CNQhIK z!=_zDzB7zeD>4-*ArXUCR!1jA=_vW0YHzqdl^5Yn*!>2PWo<7{+eR+L0V2!idhhR5 z-u}B5(^(!>-+7#49&)30^zpx2yZATO3aDu)#`Z@?KtqdO(CpFa!|b@RGaW=4i?I-f z*;e*_rB@Bzz>Ux@MQufOlIE$D&3*O~I?d21!1=r_tGL)Gm%*3|HHsw8N$d!P@8b8G z`HChsq(bO&T#{ihUYstre!t4P_QIVpm}Z#DJVO4&;Jh6K-4GN^DMkTchk99~Bx9KY zOZ?zh0xzx2-URj_-RPlFDOg*6>mu?L>1{Sc_RBuT!HxszdFJb8=Q-qyseA$!c^9(x zES5vzyIWF8W;d0i3WK1$Sf~OF$$$-gg3<)Hc(9!|hA^T+;_6-z#+ZdePY!5=Ui;=C z=v}&H-C4tZHA>dzawLsIG%fVzi=dGtIxlX_eiNayOZGmfe`&o(16Rn;L@+n?Wb`Ul zBm^(<&>~2xx03)ip7RjKtLH3|rKM-<4Ofn=Ys1eBqwDd*R1CT6S`ub z;`M^0ceA87N^iJH%-cW=Ld(Ls=Kdwfh^zU$#{cg6r@44rRqTF&_NMK_%hqIkPfwdd z@Ja|5cD}h$LDeGhs22H8K# zO@jw(jOByY6~wQEjcs^nk|yK~^I*`a6l2w5@gS@&%&Z1*G0F!6ClEi_<6k@I84Shz zOVSg@q);BP7yN7n$t<~DJD8FwMG2aB4sl_#$D&uLD=4uCHo#}>v&+q5w*SrGYSq%Q z4o1t)7x}V!TjX4_lt^&~{X4ee(=HiuG0BAbTAo|KkD?wVOG!zsV>rbl1KLFESH=$J zqTP_uzRD8xG2W~=D*Ftv79(uh$x^4Leu@-G5JQQZpJZIPnDRezORY$c)a;q=_h^g| z9_2^uj=D9QOB^YRdYqJ!xR*=)4d@mTiBZ4>a>DG)!g1{$UBS9FyAS(x7tmaO-ITOx zsln`l^uLeK;G%z9-woDqL~q?`eKp+e+Ncgjl%gf{1^hu==qIl7YU%JG1Wd+Bz!eaX zRm(^Xq2CrI2u9lgkt7n1bt)Gl zkpqNW*gydj$y%m79E^uM^T{bue7mn-mf);GdL&^KkMU{Y(UUBZ!wbjD(8h8958$ze7vdNMK4>*H`TEY#>Yc=Xhf`QTZ z*8zHn@Dh@=d^m2%931wM&4CSJr$)%2uT|JQKXn$#tUuO(0!meI4lz#r%^TX!vp!n! zKkM|%C$0~5s<278w0hZHT!jXQ$!pnaWr~0p2|e z4L%*QDalJJ9@X=`mo?_tS(GsTbKo513+nWOJk)P=#vG*~_chH}-4VzbD=vd`+Qy5- zZ=X=)n$oQhway6o+}SchAhY$oMb*+3g?#IM+)5{myVX#bbE zJ&u}4Q#a0$g@N^-!v24zgY;nb&l*YEFlzY!D^p@HjTGTC(2td+yA?Kmee)IA6<~jA z=fvs4XSgnh!v^0V{~H*9qQanRGhkG3=Lcfx38D}EYy81T5{?5zcFjlFWB&R9zddC^f$S1 z1~2#g-%9)&!bnE|_~Xb?ljh&|{U6|>YzEd8qt_k%7SsFu06!9!!)!Wy2aiRMmJEhk zZrF2vT*>uwuEaD1>en+V7Lx(L&+REBJQm7DEp4eVM7pkh+vBejKu(SgGz>k5&zA{j z8S4^Ij0_w}s$dqxZSB>BVLpHuJHsrCU1f=vXH{~F*-Ia}-=`ck6+xr;tDTeyA*@F) zRBpn}(w|4kiul}Z*J?I|ju$F*UH!&2g2Ldj{azo6VbLjX&pKQN-;L@sn~$ebDrB<* z!mqpC%EtQ5nzF`Q~_lfBNqg1?X>`7K46Ch$`S>X z1>q8we~2MSmyn5qU4&3BiTbZP3~C@zKIy!kqRSaqpN)Sr4lSCuHB>Wx@zAaYkwtG)yb5t4+gx{AgR8=rsGiC-yfNla>W%L7pjI`ccQMB-H zU^B+q4*V`n>i>UfhzF!DbDW1`SM1iBX}bv*#K4uo`Bk-UA!{4PX_KU16s1a!J> zCo|RrWH9XI3DDA9)@1`H-g1Jy(dBz$C8tJTRTzjI;xK28(7(8xa2grV^Sl)}{T^?? zk@=Yo51d9`VDkydtS3OYJ4dS+Fg%2y{-X`xy2Wj9*-vz z12p z@OsqeO6*RpXNhHX%%MTZLr++5t@Od_M-D%7|(T;~A+(EVgF zj!8N*RUPg(ee=n=d_1XjSZl6+u>!+{ODLZHIvwzGVhCuFdtG;%J^*l;u>ug5&ERiT z_q$f~P{*|PoF#U3hy~uBuM1kA&O0KIiCzH|G?6bPlw9g4#8%r6RQm;hqp%dw4O#J- zn`&Ekqw(y%pymf0ZFW7y;<8DnZxNztMb|2knACJXTH7zk%1(V1-jB!ewXy^np$C95 ztSaZ{4lh>+nPjZAG)kN6B*zkSZM3-RO`4X$@7|WrR#PzChMiuY0pt+0A|SBv+Se$`!63<%w^g4>r+ewydDlRJb-EP zZ)Cd@K~xhfpM(8GK*{zrk6fob*dSBlc=%g|wFPU34sa6M@WfLj0l5ZD#jRz-o$vRg zk@uLo+dIf^DmA9$bnETaBNypkO#x6_r>eN+PDOw-0`Ml(JzzJAiqs13j_sOurUpjp9=p8`!|mAgVRjb)Rq^``LK~-?xz$LT@8LkP z>6`X2R{;s%cUs`iOyf&+1s%gn(8dqF%`?m;MhRTHQ(;SRO#zej(NQI?EJSRIKoeLp zuORgXGuvJab+{I#pwIO6{~kRqwh;RjayW;2VjTkL|df_sBGW$ z>mh8z!TrIbS6#cN1%Q7*bIV7Fg(I*)=$P69C=h1FWm-Td2>sz^UdiKh+36rn>wK;R z9!v6hiMhb2t@Wrhhja$$mTy2v%*zT+Hi@aF7c>Ixj!Y<{A2u9{poq#3GP@Yhj0DzB2W!o1M;=A!B_3#T%F@cr>5Vy|OToS2Lh!xP7RMb?S`OoW2sl4Lp7?S01!=Q1 zQ+mA;Fk^yngd&`d*f_r9->U`yV!nIs0WkW`t8qFQa;OZk=8jcbVKnhB?_a_ENzWa? zCz@>bdDcdvrnsFVl z)WYlXP;zbJ4MDpqcYRyewjQ#G+RHDqPr9YFbkGFxwDjh9#-OzHyk{jIvk%%efl$D{ z=f#~YU9fEciLX^cJg@P*WMbeP(T1qBPld%LD@{fxcs<(r38NmCcHVcK?(c{t4CZ-S zC&+gYT}lXR?iAUaGIdLo?VoLy`C{7;E1}b27Cmv`nT1p|_??*N2>kDNfF6ji znGEC<>&d^Q4Q`5Mwb}UqjBpVrMDXuprIr;)U6+X`RCgA29o+WnIrChmc(4t9S-$!# zn&Mz*7MtXdA(j}Kii%l`jZ!gT!5Ko+)5vchFU0uA4}5+Bx?NrQCg98}Fv3AjvOavf zsO&vP&3O+Y+MsD4cZE4T5n6vr^mZSC34?g*y)5{l!7|SasQRffe9;b>$s#~dYCd-)pH? zD^EULU9mNoH0bpf^$Qe_y(8qvKi}^bH)ow|&6dq&>EZ#NehG)BZg9s07ME8jQt*Bo z+`FnPI%|R#*#u-+#2T>WAdg1U}1s5G$)VB{|>+M+L0v29p<@SJ|{Qj?RmOz9-^Z7E*F{SE;JEaMo(@UyI(z^T2p)Au~f;H2oi3ajzcO9>T;Wut?=G<5k zwGtpY*Ra+GEb3Si#A9rmW0qRmNBpL6U0=F|Gcxg-c_G$<$zbkQEQtcIt4Jo;Ml)CE z#RY5@=?U#zY3WxHzVUkm6VT%vEq+_#nGD)UH6U31`aSnd8`W3%8ZBOA45o~#b)@Wm zTE{R#-eetbQBeLxg#}&3OGa&XUA4n6dKtpYN(%Pxxem1-SW{dyeI@tLC`dF;$Xf&4 ze6nDOG)?qr(Y>7^%{Ul)vtm(wN3I=+KnRN|j2UPxMRZuL{MkqW$=n+LCa7gkz zlxc4AVztrUG-m!bgfKF900bgtBPDTWph}Fs0^0H>OWTHwJIx^qC;~E3pK&@Pi@9qa zd5xxwyc{4OLG{40v`roN(d;p*9@p7(U9l>_9`8|R7)0o_jJo^jQJpH-=9uethphTN z^NpDb#x4lKuD1I^DhMR;YksdQpdY?~uF|N)YT6#8etzOsgh6Jll6HzVcI^!vC%sIJkI7?Ps)7f8E^eQ+f1UOPTrxQ#%@AUA{&vBj3b z#tDlZ1+Lx_B)=cdnHX`0oEb!Q93`Z$3&F#V2}a@;YUH;j>m$s(^YuqNnLEsD#!ew1 zivslCt~lGuIt=r;22OGr>OS&!s18vv50%E;vJb#L#{CtsAR+v z^OE<;7fg4pZppvM#^QUboyLk8ZvxtJ^~0DYl*vxbmxb*hS?HwZ)OcAuK~wT#4+VlW zYG**#59+2VGlJ`_`Q9D5IoXxW^6N6z9nC-1y3d5QToRh?`&wRd@yxydFLEV z+Z`m5nF;UL@42;>{n%n`4c@WP!}}$px(d;ZPxIp4K!EUd>ORdhJinw7VRxrN!&ORt zBc~1}sL#M^M1>Ho1t}Gim29rAb&C>e4l&aiHOb#`NQu&RPpPmkul9G-SR-s^7lI-# z7d6wL1MCCs-^5MwdV7Q3!Z;usmW?_X(~)#_@z3j^vh%eiC$h&4et~DAu4qNV&Mk*a z2eRI$8kd7~1kavp4;-l}K^a{$_u(HvRy=6wH#inqnY(S@Xi8HQlbzpOdTVVBia<0ojGib|Rf3-{_4eJp7sJM_R}D6Y zo{mm_&Q)u4P0k7QeW(UXyc?o&@?>Oy>!(yxiX*g^RLflBc3!AffaO6eSQHVMjYH5(GmbzB8j!et|8bU8V+*&gSs!UX;;!z5O$4X;5+BwdP6GOyM zi<29?$6?VSBF%l@2xd7ny1I~RPEgbu8iYy3`uYL8N@CgCioiz46uOdQ9pcyE5EQtY z^E@D2_Ib2=}%SiFLKbw$R5m5p_6 zDOT^TrJpp*^$v7I^`z}p6K^7v4J(ww)H|0Y2TD+sDh;H8Pf^8Ij+90n-? zGf`yh8Gt5x5pAp8Ac1+?N=Gu z@-2R{|9nvQL&t$avwy>C5P!u8i>DO?)5tNAYk2I*f2 zM({M2-Pzg8D`3)*_Ie~^)HvkjY=z9YSU3rI=R%MLBW06Z=E)?=uIITeM8`6(xz}JK zSoiKCbU?3ho52y>al~WY5U6za-agct6c1D)v2k5C$GnFp+a$_dMGe;0sciV{cVG zu2^eZtV2P-PaKlp(bw81I)r;Jdi%myMeWd|=L|h(*o~rol`s9Os)~sdJSke=15=1S)FKe9&}t_$ViaB7+x6MzUkxQb@b|e3@pRB9T^o=<05nRCCJn$VvC{1 za715Y9uaB;%~B#P;`C9SuyHx%ro<)^ic$x~<{=X8&!8Y{YCO;s?3H;qwGO5Fv>X6O z_k5)N)Rt_;>W;B{By(0*ex;+WYJ%1G9mxS~71fmVDQ1H{bW+B}v#5?OX|noooy)hB zxgxXldk*>OPq`Y7>WLOG?y<<`0fu-?zRl8b$;7cJs=QIvh;)+;Br~iBb~vfxtbrct zkNG&w%7INN-;*R3?@nR*i+xPlN;lbxR4*h>Xdn)D8dRmYClnA z3-!HwAX72MR7HX!8$`Eo@&mYto|zOK(hNB+ZqgV*Uze$gaxcDtMP(pSeSRL&K!#*u zucXDRZPXFOeLp3oZ99s3JtB*JZ~mvZd7;;L)~yFGQ}PL)IvUiW-YpD1L1{INcI|EI zIsK0Ge_|BLheibqII}tDxWK36b@z=Y(tm;9WA=#P*=Hv${^k#rwG1sarExgcPaK}J z4@;FRTxqOrnaHB+{SpqW`(?hXwF)!RomucQ59Y#x@*Bptmwb&LO}8KW5W=(kvnzJk zzj#e4_NAN}yn{k>WA&>he`S3z7fT;Bdn57szL(n|{g5nW;&bjVKF);LiQmo)FvA~! z85T82wE0D^L4?_xjA8#pFQ_5GIA~p08{V75^kKvPq+;!lj%ucFkgz4r* zo-YK|fiyGr46bekSOo)`2i~4-unmaF1l~)5pl=&SAFg&Oqo7SRosEJ^KsxYBd6(49 z!U{N{Xo}cC13DPpEfqJ};}bctX_B&LN-0Z@vNG40eO5XlMq`$98L-Vp!p}d;a#&5a zZlcL2gu?yuaN{&?7H)Rf+Kih%>n?ERN3S;>{*`WIIZTl3xwmTN>iCmDiw-@Wj)Ho9 znh<*r`xsfo$!l--WixLph`L4(kI1-RI23c>u^kwaMz^8lkO%qCHX*x(D`mn#^<*!H z5A0BorTVp_;~MS4SNyiye(f7Mp=MGlFtcU~pk>(&<3qXYnqXSjK5r7^#$&=Fe=umj z`MH&k?T=LoyFY`!PLL(^dt&xU_`zI^DGeB>)F`b28mJDBFDToDpwYHBbw!Y(0=>WpWVJ%iXJXA<7g!(WoHxT9B0ER zGGl-xZ`HUQxWzU}F>wIokR*H?38v0Ag@ltKsLfRARS5pUrsn~Lo^Cm7V?arvX1mK2 zayShQ!`?*$=K?;?<_DZanj%=n7_fjpuBGV-HaoWx0XKL4#rhHKg?)^Losp5JlU-Dh zDEtsn*7=dWww>9otxwvAgCy}^b>{ucmg#f;nf8ug0Z-wtRh!y_{qfOrBQcJM!|n6Y zXXE39=w=Qzm{g1wBR{p)-v;0Jo=){Inpt2AV`dEJdJ?-6zR_^n;!IX4-WqAW7c`a`R0ka1G@i+m8MfI*U2k#f3%KGp;(%H z4C&*83Qd~Zu~IS`KP$UfS+K$b8d&78LaRvA3cbpunuYNWq9!jFwmo-#zpE?SIRt`e zrn79nHHt(m9OLdq_D~_k|BVURJ`25u*}M*xcA^C0-));HjD;6kN%GP4^F#}1Hm4o1 zGXCu}UcT&ywf6Ya&j4PJ^Um{)7T1%hZmY%ju&;&oCSli#fho|-OSV%dU;5n)wJ~_0 zg8{&l{Tndx3&Q9bu|a1#j~n?69Tm98l9}#>@DEL1$&jGf24jqCp#Gh+M!azK^%P(2 zIE}sq902k>Co-LK`R40(WS!;d^!6C_T7iY^-I>hBCJBW48HTR`@yn)K^!bX1>nxlU z^(SSHywc90AXJe~_-GM9&c_rvOY4>GOnUED!qL5ba;ZTR$Wml{!5o7oA&kbY&{pXb z(SMVuU3AZAU9c8@1KAJ3{OP1Be;3DGOxPfZVm9^qI}<*aeSa+O7L#^eIXMQc6a^68 zbvzzVcDNob7l;@!ar&rRPUm$Q^?`vMXg{G*3O$K>WPw6%;xVP0^v zVh&S*V=u!2l!~~mYd2MeZ#YTjkjCC={R$_49m0!V`qRIoy%2zw9?Zsn4*P55{tqVc zFP5t=EbK!<2U7g??-KuS0)UwSOiOTAXZZWR|C=ZP1Ng8eh;+t3666AY7=RBGo|V7< zXM_w1NB&GyPhpEYm+;6h@Z#k>=tL92f8gFqx!A z=ilrNY~z&8a!UNUdCmSrQt)yRT|CcuoW{Nw@k#Ww1X$DAtl!~&YY7(w09R167=~tT z%a3lnu0JjS_^bBg_Y(WZ<4P^SzPNHv;S?Szn;MgZFCBw)%8d< zcVjr7AO?2&`S-REo=P78Edk4hx$ND^-p*RK@_5}o#}RQ@s|QDXWE!*}#|AqC_O&rT z8`lCGzM#KP=16tb!4d-C0izvw`~)19PyKTnX0X409TbC1E=+0(v;0#5G=l%wl~q!z zkW+JeXV_>l$=Lqm6M_5kPJ+Db-;m<2$6$pbDb9x575 zFntU*li+qBxF*1+*KZO{fhp-Wu-8iL6mYPUJ*}XswSR0=A>f<`JQvCX@aY+_MF1QM z0c3R;&mnfm1t2fbqku?_2$vI^ddsA`g$?LQ1tCc7$Db>y4}g7g&0{ba7}*PPv^QsK z9^1V^lQ~=-NrC_``!e*ovc|g~mTLRk10Yzpw$sr6gMlc+{a%f_d+&a-6<|vM@HtbK z7o#uUz~&)BKuHHg>uZ38@_qk5?Y(tW)NA(#s)VF8DvE?iNevBxfQobpQi_12bV^8v zAc%AfjY>&KN+=DI11N}sAk82M(vrg6gL;nVecyBM|9Ab)I_s=C%rHFPC-(mA&;IQF zq&RWcZB0U!h^#?K2a@cgXo# z5lS0ER_CLR@$tSbquY$$Hci_1OUW_gz6OQ;FUx6%8MMr^_x0lcM%t@C^ zP|URW-W19j%Gn8i&WZT;bPUl+ZciwN<5cgF$-IoAcP(X4QL^H(y!wBg5X;$&7D)dE zGIyD@yb2~*2s&dc0+pn^-gn5X2l57>K2g+hS}sfj>hG|#rS`o*7imu*4!mr~JxDq` zQp?ug-(4K*MH!tQwJz)K5t$;saazLDEm_Fs+^e~qf3dbw z>}2h4IF_Lh^Nou6ei$!N07JNk$fJp~GKGV5V%~dhLXj0V!{5Q?um+W_ZG{CrM|eEy zz4(quT`DKovyvs2?x5UH z(XZgpLe(Zl4Dfx(eClM#P!AV=Gn;E8;fI$6`qLeuGUvZ7mVrAU2=-Ecg7Vy%QS6 z`;wVLW85E?h~h$oEaR;J^5J}Ko|;7^1%m>PMjn5gJVDF%_We`>C_E*R_FgK#fa#3O z0rnZY^Z7-N+yXiVJ(t2Lkt7227Enr=t(tCI-o%MS=iHoBW7GeQg#J_w!RrRr$Vcq< z-xr4X_xFd}3VNJ9Dq zTsw%HK49f%|FNU~!_ei7F2h}!OA5T9Lz7B|$u&Bs zhpJ@Ayk#$1wREtgGoN+fWN2l=f)ZSoVv`PvI=@GWoaWn?OJ0By^J6azgrzjeC?PR0JE-uzFXAXS1- z)k&pOu#-EoPN2ks{Xyn;F90}o{mR0o$%xlYORtwCNR-53D*LssGKc;*hB*Amc~HC| z5+h!iN&6ZfA1Y8**TcF64*NPCGsW-N@;`uuTmnXSwyI_EZ!3FF?L1bsr%LXSNN2cE_X&DwT9JN9@qRK;+``=4rrmrqzw>|p=}11m zPm~h7;xp&+)f`guB423gYTj$g8@bo9YPL3pS`bN}!3 z@NabS*AO&=U_LanpJ(RcOO0dH4WRG=7gc9HR4U*{l|LfzHMjI{^O2E6_V)dYB!Tig zc8qtt3~2FK37a~OLR143Y6Dg(d2`}cL0QkmvlpGWK!oxRQ=+NowK2eP<0DI%A7R-b zPNUCQM$?&#v!b8E}Als=k}}EeB-w8H!NFCL_7x zU!Fdy3iL39#tK@xrg0z`n+Fub#8Q3n{6jW74!PDkuU!&akz(jfP{kHbcj?oK!at7W z4JVifG1m*457|wzTwDn+`s{ngtU_J=9hr~CcdllKgZ@!GW)z3u)%inE6-fmYq;K23(`hicn3oNKzKLjdAIxu|Lj#d#K1-vuV7J@gIjTY7 z2-=h;vP8YJ2JW{m^GN_y$_*qLf6DD${ddBK%x_+v!PatCC5wMJ>)0EW;FsT!#^DnK zUlKtI0Z6ENqbZ-{kv=rS81m@y49C&?Z2Ni<(Occ2gsd!Jk_{j6Irvc>%KkR9F+3=) zP%~dk$cts>QwxqIRKZ8*zj$@Q{IugIA`RgYiqAN-__0({d1WUl@=+`h7z^o1*mlO9h%RllGBEsg&081 zC4zjluqM^z(;O7T7`25Y>)$yvOMabXk=ll)U)YQAGi8rxd^3qZIJpB9H!gnmb1dre<(E>oVY;Wv@fr^I;B_*f<|ocFrMs{JQK} z)9HfpJ_T|=hZ(-~GOY@D{CDWde3tqj-;=jPI!Ya;TE9orSAm342(%?;ZV+XaYMY~w zeqL|)iI4er4#%3ku<*I?r`a~dZ&6-!L{p~3ZEGlS22nLyASxJoT+tha+jBVwAoSs` zT~`lJouG80WKpVu1{^jrzXpFnUMjmm0qcefxm-vCiP*w20JYN151zpZk1MT@qBYKl zp6m@G(!+wH+uJC6P-PxDb1&fOWak_2;3YcxCsU8PUq{>MFZg1T7g|ld61xk4fEPz= zU)P#o4dU^Bci2*ds4x*L&7qa1W;M%_)=CcRLi;l}LYj}YdF$5)Im{SEO<$!SJU0|LoTEw~6Lp)e=DjHq|5C6#6cOR6DM+)7 z39bqmZz2t8f_#fczh9=fUj^ezE zl=Xk-Z3=+dK~i%w|NAHM6yWdVeRAx(^*0Fk8-yIj45jDbAZk^`>ip{`@-AR1PAt3R z?fw-XwTA-u(Vb8?`qxk7=HXb9(o5v!&2!iO1*1D3fs5XKP2I=&ChJM@Kjz{_nv{(+ zF|C{Z46eNY-|yTAYIys^b$duqaV3#W<{v|LWKjz}6KLL@6zAj>dmZ!EB>r9N5GIXl zQv(^AW}~JjKJ`QAG7nK z{vOMJtQZcg#wp*Ye^nX$7m{U@1e6zVkev7LEwRWjOx%&szxm4lSS;y`Jq(-YZIgF8 z^+HjpaKQ1Qq51!++ur00X^SwMai-E|7XlBJ#O)D1l$`MD!x=i_S{8&yu z)2{d@!+lwb1T_G1Fg=(oO1g!HX@Qf&v?J=syPZm%Z%{AM-7-eRQzMnHj70b?gOWSz zdVc2p2Y-z;?uhEqee1;q7#wujS+@cd3G&ps*)$KOn&dZV&BImijP^C_*|zy0j$G8S zAvrDZ1pv@Y$2y>;sUD2R9<8k?pHG4V&7dxyXn-a!U;A@^QsRxNzC;d zreO%hHaLfGFpU^?3Sw;VugySa5gFr6H39b!VoXKA{d%DkKxCmx>LJ_*Sng(ZA7tyv zVR9HoEm^>#uhdj=Cy)KgL8#O=`Q1w#eR?i_EdZ421P!BRwA)s5$>GU?d{elW zBy6X0ipR|Ly#n1g{rhvwL5-SPx>>GEqmuhu#_kCA)SGwjYh1KpRF=+2qC`Y&oZz~- zP};?f5!0>>Tari*KteG$4QD?|#0s5~-r5_$PA1%-TV{4g|1#64Rtd5r!ZKPt6<;Yu z!~y*8R}f{y*MSbm6R4H<-hd3Dagh}eaUm@VgU@6mfV6Vo-`mD$fwfC0jF!HBdik|S zY-ta=sDL)!X1YBJNrdr%iafQ>ds{12&sV=Wzk7NuhE2|>B*9)Ns77_ouIHrP zx4ef{@JdS-YyJB~b8y+VGxWsD58o&%z2_oZ7&s9wY=4R{LSz#E*j4>>THtLpD_WWJ zs$l6qA=DLd^5~Do-^6IBDW_nY9&CIx7z3=DPmeutX#ARR1e{2mp0icBTqC$pHwxhp zr-=B|W2AJRAh6cEH=qf9Tna^!)gSs^J(AD>LB~3rB&HV-E1gbYdB06C?yVx z=jrFvym6o|$^YY#U4K(N&idAuf|DZQm}qjszy~UEh*+=K7B?RIo`)63nlYz5L!$uR zNs0x>%|n(iyGV$aMRF6xe4Pfy^dgnt)J`y>`mgMmoJ#i&#^ zp&DSo%aC1xtTU4K5dj(1|=nn2;5qM`o5VI;M0^zIhbW|1}Telx|$dy5#YFdQH~z6PBuFkaAtfjeM=b3pW$`Zrtim z?z28=!HhK{>wDHFWucK#sOJ5IJ!yD%BUKfM)p4vsmmXX?Vh(&^4ZE<<8oHY(TRZd6 z(;b0B5$+ryZcQe0E?um}Dpio+K!)(GDtUY0ksLh-H3s^|7OM7myfqgpZ4HV2*HFDw z#_0dJ7OH1%!ExDckV}zD*$2SL^Vr^q!6TSg)mUoUnR<$tEulfgHk1b&Ykpeu6*<#0 zN=fCgZDAcjZm22I3OIJWi8B3;)8~61XA1OPg>?}L=gOF2zAIW{f%0S!#-csw%yfk) zcbd{2>dZu^ zK&8iDUz`!OH?;6_A@kwxael;>mp9VGabrKn&uDzU#nw=B?OSor|_+j40v zxAc81>*wu=XB^TKrROtBvQSBy#}xt`7uaVRW4p=yt_F_^8aC|P%AS?*yz#tSU2mh0 zAU{6`Qzy{H+NCPxo~*{@G4MM+Ag;0&4o?#W-8* zvMnU-%zJtx{p!|}RY&MgS-gAtp!%jz*Hl&K1(*ad-G&;)$6i^E;@$9qD4>+FA<|YN zRa;0<{Tc=~WMsmAvrc9rHOIZF`$y3BU$`Nb6Y!m4g+(UvU$M<}48Wi5Om^MB=&t{K zp;n5?i4J8)8U5!we}VW&RjjPLgzskq)`ps*p)zz?_~>IUpBT27gMkdwzQ{b8YkrS|^8wm)JlOQlwin(gmo5;f&p&MYGtg@0x(X(+cM*o)s2qrfxW z0#cgqg+B#`^^}sq5vVW;d_I3(JwPk9A}=;OOGxqg4O7R?f){C&LZ-iXPQO*gj1H;o za#M@EX#Nw4{t4P9F{n^hX64Uc`^RfFEzHE_qi>l0 z`D_1p%@7W=?_fgpN2YZ~)ew5|tAOc8wk9Bkd0A@>*sdUH(R$#O*)|1;I-=#Nk1N)TZ85uz#`vzu^s?vxZ6Uhy43{0 z&J*DE)(VEN%ALmhHSTe^j}D(k?3j_rJ1g2r{SH`T(q zm~%Z#jfCv{uu$?R4wei`%-C`B4E+ZUosjFc+CGq|++T_C*>VKrxDR+W$xV16C#(fA zJNNl@Wr%Zgl!^Ox;^O0w?O^ zOPFaco7U3ON7r`bbLHRBJ+@z@6SDxQbuFlVU&oCViM0#W<<4K!-a-Rj_u7pQ7@8Pg z61E*6ZZF#eYmPc_DN1DBs#H4AEm8Ld|Cv$4faA!~T6jPJtZx{DY5Q`oGl6XJvvZ7m z$aXZ%cS4Q=U;cMsuWO*t2GW!^=sqYl{8V^Lm?Qm2g-!H8zBVb(V^WDNU*x-IvQVN} zayj4_e%q1D(6ZGSK3)l*PV&b{4q$_=9!ustg$0gaN-Y@dwmM@ zQp`g$2?jlHFEgC7n9+l>7MG(iE4}>w|DOx&u8RR85=QU@45>LF0@$kbhK`r(`b-zt z+RO+pq!%CuilzMKtqF;Rf+rSS?kV|IaX}uaZe$ezTPsv&%AP*PJ<7c7w6#28DC;ONo@*oawrlx;dNLvhEUL9~WQiix*$v~wp~9UqBKi3I)~o&L?-K>kV{+uu z$C$N6gq^CZSE+x|4}Mq3>{+oJhi=+`IEmSmUua|F5!xj~0ZkYKfHoZxRjT`I7lc+^ zu7YS2dw<6Y?3jNUvzdtJrkrmA_F4@F0wH3AtQ)Ftmzp~8Br;#j{{d?q!OmIK&)WxF zw0UNuD89z$g`qNDu}NBIaPfTf(Bswhj~GJd+l$)oH??-5R<1J29k|ajjowaKkz3!l zJYb?q==iM6V;FAXCRV7cL7cjh_X8@6MN@+&a7W}tE$Q8ofbvZF~~axb9Zkh6r! z^tV?@YbQfF5J`G2L#8!xBHyZ}A|sdvZdw(-gbHFu{?+@2tzk4_H!4OB&pB-wG}}!M z!*6Ld7iOTOK{b6a)aOEQrnpUpz%$NRJb;mv!TN_KsQ34aA7D^u@Dr7PlPktbq}%W&dUwNRG1 z(8LKRnMsF`A7{ZA#q3t-2Io3DNYojWaEY3{VO103Cao?<`1r~oA)o*`+Rr~%yW&KL z29M9A34d#M#=;7bwS6{sCaKDN0d4(5k&X^0{)A-e7r#+M=G8w=d3Qh`Ut&J!WSMM2 z5)({k5!*?dEJYOsL8dghwyQpcG$gQOXA!UrNN86nY_sxP)x6xf;Xht9zDE14y9V-Kw~sewb!>~V4r|+>WooF zOHOZR8{fkxK*{o)N5dIy#SLM?AAV^i4A~#btM?01Ao;2fk_Gs5kTBk@JtVWS&H1CY z5$%tfwxwY93ho9p0pAoRb7x5rsQmnW(C0;+`*p;Xk zb{>i4z^`<|A8W6KjhU&a8k2hJ!(%F>U5E>G7i$YQ>$zkiH(`!AT)5)N#vuG`Vi}cm ziLx#0MP$$>zd12`ESlO$ zFC+^g{cknnF4yZSIb$7R(t?eA)?yBmN=AY;| zMMVd$nvbVT#b`}%Nm<`U_jnhd+I+T@mI0QTqcGl+tx{=r$-37w1WE`c_ zX5JQ)L)%uWQ|M)HNFk&ZzW(Byj{7 zEO+N^=(bh)W?boAk>$i={6V;SFs~XUUAEgMjKoahvS1GtM>&?Q`91mv+tIRoMmpE^ zW@4`%D}j_#Vi~Ry6l}t=@-3ie-q&e87rFQXxOfrn5Na}89o2%e6IRBQ_8i2&AK?VxaI5#T`yZ^4qy z68+K@kk1KBKn4*LB(sG5h$3+SEnD&9lk`t9!R+m3bYCMLJ@i?L7#|Bh+epahTSOoH zBk@#Ehs0DEKSJ*nZpmik?c25|9>83yGuaQ`2~KtHlg}0jqT+N#qG|4kFgHk-_O)sN zjY4vvux@AGEdR8-vMMGv{EV$&*g78}1`N;AG)O$?zQmD^XaE>MGT>cb#m%xfZi{250$N_hpq*qY4q+ zP&waiRdm*F3{CP$ZKI1qc)XNTK~BjA%+saJpQP;PXH-+Fc9l+$#H^UB#opz5vgMo{ zd%2@Rul^w|+KiinL-#k^D)(5*zT!m62Cl|2CZ_(68Rdq!Of(o5q;(Tq5a&+=W$j=} z!*)-D;jO4a#A8IwGc(-WJU*WUANpP=Yh5bCdmz8e*yyn>E6jBRTr-_dIfgS6eu z>W($cWlHfw$XB{4#$s(&5%TD@zW&A>2-L*R7CT?hFlJaSvP>ob2M) ziFeQ@?JUu?cCcm8}n5if8P!LxxI7_4bpMZYgMlbYY} zzH&A_6*@~q1z=(1mHM(%#1C1lXPWcdb4_N}C{?8dWSgMN`I~(sBM~+-ADPakZw;eY zjqKe_u0HMPisxn-V?nh&>acCv0RaUA4-O(;S9GvP=cwaJrzvAzULNeK&PRCh2_uxTbz*&sS)e$^urV8^~1|T=&_`BNrFEHV}Ep}95qV4oP^xav0d5zPc#_Ypgo(cb!l;kpx_Pd9Y5IH|z z$qGX3tUVs7p@j5hOUE%V{)6n7sgNhV+-_dZ7711g`WQbfOOSU?mG z&Av%h`**W8=C|R9ide(U+B~TTIF5H8;w1j{xSMSI=Zu^pDWfvdHB)^hPw=kOh%sn7 zH9yF=2s(s+nuI+W{>}HmcRgHvgs)IB^UBXzr<(b~Z~bl}W&2VAPkmpsRn%2oFr-?& z16tG~9Ej?+X&34Uf^hZ8n)<2*&)o2(n3mfwS9C}rchdz@=A92X$uhs~Gr%vobg7`2 zL}#je`}w%=(-*G&k;ThMx{o{gyzRLsL3hOCh^q+{6i7wS8+tMZ1OvFy;>4MFkQUZRUlR#&vRlTlGLS|jzZ(Wo=4DQS#@$haJ+pdv^` zVR9ksbNw2Hn+HF}AnFE*v{n6EppGy(4R24q`;w-5N-5J->!C1QIX@{-^FTgkNbYh} zyL=1_uhL7akC^K#fM-%Y7t-A;7Z14g8Kn4aK9!43K4e07C!6<)1Az`{17@b)G>>nh z?yJ)eQ=p%SEvVdxLokXf2%k1+-Gb#n4;DLrv;e_H^FBpAacD7UQgXfZ)0 z1EB)H#ksQ#(YzRDfgh~~eKk^FE{^#GKF-AvttiM?b>09PYZqdM;tnb{0l#VPI|}rd z?yqAyd|B~9^2MS*I}yWf6d=qdnjT=H_k-xZt{-{3>=0y&cq}@R*e9z^Yi$ zVm@7Ki_sW08yd38%2e4_BmA2 zg6bJV1!LAC+d-Cg@do@4u#uofBKpm7b8g19*ckzuF2A^rCdG_tn&*-SVPCntJ5j?| z*nb|pJVL*54F-{~L=bGr%+mqY@Yl54Vy693Tf?@`flc{48K_p_=(?1zzncw0DGxt5v-QZp}K34-hsjAjN)VO>)MK90*t}61`UrPr9B5Qed57bG#lAvpQ z2l-jJG|Cz?>2SMENT%Jy`>W@dT3MBlhWr$6ph`nB7eRwKI6u44r0bzOC?iYQkpj-9 zd`b3drPVF<7_SOayCr$n)N)8t-J9z(g@h;Q$N6tALaRE*55?!H$^5JdAkSwE^#m=g zZI7+jjxhnKpMxuXjB|{OUjhGMTeofIdX^5g3YxRc`2j0vcsBp`2{unbRsTsIebloD zaAybHC(!WH9}=g2sj*$}7ZLN9!@Urt=bWVDq7?uGf3 zpdb?!?3RIt0nP>feg4XnKO;mMex66+(&>#E4K6((uOf+HHA9GVmlQK_0of$4whx`O zvgmJmQGsP}Ot7a0z#xgl;-$)QB7`#m$sr|v&W?|Z8C%eGqMKb6EW-L}Vt~>L0%kVG^MLfhF z{PBQI5{Y;0{T_xs`_ZA;)+SXENw&L<3#Rt?*}o~UoO-UYJg zC5`*n9+@&saZz2~3?$BFOu8NP2; zHil3YiR+F+7^Q$}4C-V|iOa9xV>&nw=7GWB@T4vgdW!TA%+>k(JU{UIVD+Lp`#Im^ z_Vouy!%jn!Kuxuq#TMrdBPJnZwCTIopxsk1(ys;SUkYN0-@WV&Q(R?{91%neld)~G zakHH9MEMa|>|}7NUtlR6S#~t-yK-wS-d`~Qk2ISUQv;h&V2dQ^058+a78uMY#f`bx49(1HSFzI5%pk`X)(L`G z5}tCWs_BF)?`kdx53lH4s|O32=?;elBbB^}b4Ou9nTKaWSzm~twDT2kTiwhfKFA5& zA94ZFkID8o9*u`JWlRGV1)N_Tn7Gz}kkl|U_aGh)N(l~Sz(syoTgD>=9NGM zmwp~5>+1G;>Psj#xesV79n`|RjUG8+Be~iiMcu`;P@JOX#(2|-_@1q+S7Xw!@!ZTi zm|5hISkTL>Ov~rT5aOHJx~GfwGD|={ZMiubf#IlYV}&0LQfdRESE-1gzQco6O=i`c z6vo@Fm=>n1wZ9NfkU3_;tv_7luqIPaUOm(?)BAKv{nI%NO9%h5VPiFlUj4-2EU3>2T+LU%hfmc_g|BzgKjO4mU}y^n4#^6`J}_^DQEX4RGRRhAvR@5_ey!ciZPZAT!XD| zlqIeIA@s6_p;{?91*d;AWk57}_}NI#0*j$3hQG|t-917__4*;(1^?EdT%C6{mQszQC5BYg9nW<9#ZSN2 zd3r32OX$W8I<+t=YHFgv;*(?^#Fj0gM%o1o=Ljn{zlu4Gb`MqW(uVhXeXCvb?4cKS zGIKR|mGJmBBwC-EcnM*^Fz12vYn{99)=Fb;4bqtE`-{N(S8oWc4MZI=(ofVGhZ4R{ z!l8{8{Uls;@DG_yzU$~DeSx~{X)*rKHVRp*R^r%F6(girh%>F z`@-m$IfXUB=#)D*jXB2#+_?r$ow@n=Ok{PUfP`tYa^8XZV(W@Liltjs(W(1p9nMiK z9DHXcL>(dL!2Fpanm`A%(%QY}eXYLyXI>P#*gfxo!ZzfI>)*B?TYYrsIUsc!M#U-R zAe~d>huL`RvL<~+Go2^fBL~Z$QrId=RuOMpgt{$99)a$$HzywFC$czt^9<~TO(|YX z54c#zv$lkhn{6~=ZOf}_ zyv6le#hTlT+me1FE1VU(g-?aQ7P+R-)-Y1vSt)(&w0V`@r0>uLrU#Uk9k(Cfykg|D zah)+SRN!dAC;Gw{{4sY=45Ctoin}VitvbWSzUgFJ$;Bz2yM#`%65?MQ3Dd*xUsBcH6NEe8Q4Phzw_|y3`$mFGMU>t&%I$mQ>06jz#!#&#LpHd zN!!mXzo^=b-zj_h6K5fTNZFmTWivA_n|-eVWg*Si!niD9G1t@Jl)7?x63G|nupu-C z&Zi_)>D!i|W$kQ+AAjb*rhW0_bhxv(-)uF_P^OEgj^TBeSjLVyw3=(InsGJ*N<(_B zOI$YYR;g~R%B4A$B!uY)RmqG3gKrJy*I7(^cif%j`)EF;jP21F#jsd>!=4rLIPG~x z$eQheu;L3m#OSrO2YlSsR5LuVY|N1!(lq3HXtX3;`LL!Li7@yfYfGp3!e!gFhxUXn z*CkuWVWuaED9Om4H;IxG27-_ucis_XRnX~@_n9W<=qk{ktBzla+(V*BS6`J^Cz$zl zqtNJ7Q=uaExgHmYSa5~36W9AkpkF8jq4kR)R0^YIyil3Snhj=RK6}E%kjg(54`G?5 zh(D$*6T$KglgJe8dY=6L^Kr^VvZ;lGn&@n^)}WBSY-gk(Kl55)_F$_UL~mg}!Rj*4{nAve7M0Ds@qpxN2+#9aqvYt2oa z?{W3rEd5nkdc9?DV6%E_2f*!M+ZINy&EGiu)bsKIKkuCMXsV~|&D79xl-ot7zU8+7K zzQDjQo+)svKalGZ-kNZ4eg2aM+!Hf+cdmFOO4bqM^n|OMnXUA`o!XP=6_46pj7614 zP>%MDcveTf25dEx=AQI%Cfl|tsya0-_^as;fu(Sf$%kQComHR1bX5$}T7`^c-}W9qbN{FB%Z z)(WF@q-dcRt1cJmPRgKSS%Vo`oW#m26)nh2>V+xgW5-Yl}c=E;>rV_}1 zr$YR&9okjLNB1&3~t4yMgn6?ybcB&UtHb@|Fq3o``hsv5|Lxhr~?T}$Fmd(?xH zM=^!86@Eb{@xT5a59^L|k?d{-O;TYUI;k5)6K`g5FE#5XlkO8;H~zACp@TZh-8+;O z9{qL(86VwldAS&b29w6W0Ud(nyMlNPk3 z{E8Qq=SRGIQ#hM_0>sC->KDIqeJwRBo4z^jcCtJA>kb7De!)YjD+e996`$3P}x3jT(e6#9KGr=u04%3Il_7{~?1Dp8mq-@j7 zUHtFto`08HE*vx_w7uVv!aAp#^!a!{(UMo%ak0B$f`zSxub;G{Sk@R!)>h(TZc7T}J^zDODNSL_JcSoGHrEm##+dgNS=_n13znox_d=hMA zgE-a|zcse*dX?k2J@p-EJq=^dPh>)~vORT&?;r6yS8RkGsQn!$vrRf^(oAltlP;*1 z5@TIqUE<{#B8YpW{km>!`4|+m>JT&TZPK4-#(Xinop8gD=s2z!%8sR>E>q_N>(Af8 zFQE2Q@`&D+*Is;Q88-7?O6O&|DxS>Y_gy@pQ^JbxYMp2Kb99)$@pBmPLhDIGy$3G3 z(IkJlotEO)J5n6Xy}4&4R+?q~e|~td4@clwMLB=n2$U<@S3ihTJ^bdsz6JBbP!k^? z_eE&`IKw}F{PTmHmA-1@jzl2V`16k+ey|~rjEqo^I;ZjSuP6L_aQI|8wnv{d%$(4Y z`1NasTm*aLc#>66$Jr?k*(avY$ z!AZ03JNKWR;Vy0hb%=MN)orVqiPR;}S?IFsl2Y$4+NE6LuUTe=nNS@kEVx~`$;QrO zxSR$g4e9Co>p3%9&|iF$b?wu~y6;fl^5Yr(k6e>Oo53KU$nkY#cXYF-FLC4Ru-Qa6 z>Qx8U?){zq^nJ+#cjnunNo+aatkC0Q8!ucx?|i6Kv6}YYd_4x_n5Onu2}Y{HAM9F} zf3BqAOCry2PU#-4{Anwt3AGDeOCARP_f@^-HIiiy>#Eb?f?v0Ha5u2lRllFln5kR? zI^o-ENgq*3&FeD4dWH{@KQEYJiv8T0>kob`O`+ntb!|iA3R4d^X2WTUtp#(*-9T3H z3DI8no;Jz-m2yJ5ja=E8amv>FTg~)od#c{6F$wj1GchV=7-yoik(~8oivGZDPSN0g zk;i9_UFe5@aIs9@eHhX_y21w52J~AEcxmgIthL_{^q=2Tu!`5%>=WOj-(L=Xr+9va zGJUHhi~HVl5NQu=yjI1>b@2(+jQqKSbQZBJ>ggb5PU_Zx-N&@Fzgd5PsUXh^hj5L@ zdzy*f{SAly%BzpH-()3LqYC0*57onxVybwdV$~73KY6m=txarnr6j^@VW7x+;@qD+D)8h*X&Y$2&<+tEBZyS3)vx-S zuclLgJe`Yi`(%;B{9}UDXUo?0^{~++g^BItWz(nWGnh^c$acf|xaKZK<}&xaj^3q6 zXZQA{lv|^#@nd^vVJDA+ZaZ%$_UX(Rl~=o;m-PE)?7T0SyyUn&r{H%9GQ82-FivYw z;10v>-2Q8EMV`!}>DwrCy7dganUmKtZ13gY@&bNq43t1+7+D$Jpn6Ya*7TO*;rY{& zW;i*ix62pA5J1r9#-?3K>b)EwT)*Az#ML#1Su%qk^V(x$Zuoyz=w)W-e44 zWeZQDb~b*Z7!yD-Cls@Jw>wn5qralYCQxdMgKBXkoK&i%$lm);wuduppj?7AIGV{21B-E{E<=vuc=FJ+>0I_Rmsm@*^ZI(L>!=AjvSmNI=l!{l z_4^x&XfOb^(oat9R3AA)J}EDK`9@uIzg}6Qu26wba#q%u-sv;$HbB1I>rRwDM4R@Q zb?SnUAkq0WV|A>-?8T4rYb;q9v?)L;A*|N#qF~JMj8}iVQyVSv_4>W^!B@Md^B8`c zSY`b4IPr`ZPTqFDKB=L2*51fv?nlBy&DOG!DZ0&e%k5;;x`Se}NKukX`fEjlojw9H z({j6bGo!ja$3e(*AAlv@hx^1;n>R6MhNZ3J>^|p(*ImS3bGMO&s}{+9U;UlYFqv%YZyf5s1nn>p5MUHUkTNQD@xMY%y+0V zBc{Rf?0_!zV(M9n45e~jjuDtt(? z;!CJj5-rxdL`k?eJhuM*Idn-F{b-w&)#kxS3HhXzmH`1 zlXX>8_xl>hwIW@W&zawBk#bJZ@P~!?_A8uyu%TzT7sa@!1~<1g#eSLZZhVu63i=_B zvaToJ{W!zzTD|flp`@fkRkdM{_*4-BC7)S@+DSl##VD)3az3-yDqL3r#qn8hQbv7% z=f81VGAqmD_Ny*tb7YUIKd^5?!`>4_2JO;;G!4mTmT2DTU5O;(#Kd?4b(Bvy>@>da z+>KpXnMM1caXWG3=Q>aNtshm2@ZGxv2_Jr=i)YU{2G^fRHoR+jd$e`Yz1KrOo3fK3 zBid=GOJ7K=nCg4;P7FJOR)$V4k?QJW@Zgx*4>TM zJ8`#kXL9)xY4}7Y z0$q~QzL)338Fy=l^(7Sv&zfI|+}-0BrL;R(4wif$QcGE{_*FMK)hF4O(!S1Jz zY2YD0cJ~)DaBbao8DbV~cK(iRn>Qs)BStFARuhXUAh_`o;-{5p)W zOw5-g_OtaCiXDf3lVSul9(_?fkZGA~`ulz)`^v=!?v~WGUXyV4wP_MTO zRzmaHAK-o3$G=RlOsz*6)!ZOCJbHsDthsuZgx4d?l~sHy6)i`dj)*OmYh;(P$*NOy zSU^yz#B~06(5ixQhVIR>B>po(M0RE$`Y^oB`P%(4fD-YQG~3D2ucWxuRQ%Hjm{>@V z6nyF;&qADX;D&^yKsCd$S?$H2=*&-$A=2C44i=LEbIW~x++NsaDl(@`y;s80m8DA;oRKOj=#O29 z6lYQt@|jXrLe9hYuU8H?9JNv|uLhaf{krld{^UDG;im7lwwyL4YQIwyDM|Cx<0!=O z6Byp-L~CDWp+yC~+#@zud5d^Nanoz%kwMBuiLFM`p5ia!Yv=P#)ihfvO*5P?g_#)z zJ*^H``nlPLa2%hYOc)Yt&eeY8sabC7qe1kpDlAo$Ge^g`2d_yL6Q|i=f^pF;GYkH& z0%M0W);&9>U0XN%&CG05(Tb4^uAER3;bFo~nt880|1Bs)AdpX1q4jF!c2r^#|4FBy z)5O|eM4`V}Th=H2U(nPqj#@7Hd{pX$RhLCp=0qBs=EWgXiBth|MYV#IaDkPt?(!dN zP{(vey#ev`4yH%<;P`|bF+*_FmqxT;Y72A8B=KP5tz&JO}nCgYTt zm=LV~blzQs8bL~S7W3RB2N?p}ct^T5WSjU5yK3SSwnux+hml3HhT-6;T-Pauj0=~( zc12BRYjbZ_TO^PKRO_*nVc>#Zf&)a3(r-t%dt5(MHe);x+CE=&Q?qD^VA=Fa+8o&OoL;1}Tf z0c76V__}$9ZZ7CJtM&E5SR5Qm=Pn%gtAXXNU7o|uDEGcZNw&rU=Vx8rYk|E%4@}Cf zU(u7e#@;qBxBix&GkxcN+F7m|m2kvuDkrzBK7Jgnc`=)6YLi{hsfHIAgCRTiHw8P+WbH0S}QmXPj#-B0ThhiyP z+u4^L9Eg2+L>dFnE|){Yf){dh8c%}=hGNa&cOV{_NS-+t* z2+hd)Um~vN@!z{ob5?w$I8$Q*L4riBXQZ$@)o6AMiBl;q-u@XORY_x2OZT|@CFcw( z-}Rd`xZV*$pcXlSF2iv6&1%L&)T(^2#Buh7mBcQtoJe9U;@gJk6jf4wSt z_trfAtoXh(DI}yffu*t$eVVIyHrey1v+`~DME#b-elbl?vIDa0V zf4u)T#8=Ibl~rBvk8k=tHA+PIxGK9k3cn`w_m5$~8I&-16_rfO{~kOU@&p-S%J-7k zKS%v*23cY7sVQ;;e|*#L??!MjP>C!Wv;U8YQo#wt5)+NeJLCobF?cD%n^J7{pW4*_ z$3&$<$nD~IPBY-Y$I jANHr){Qt2JJ0N1Jto^3ulH+p({*k|?BK_iuq5uB_YFB!& literal 0 HcmV?d00001 diff --git a/src/burp/BurpExtender.java b/src/burp/BurpExtender.java index 2f4b88c..393d1eb 100644 --- a/src/burp/BurpExtender.java +++ b/src/burp/BurpExtender.java @@ -9,12 +9,12 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; -import Domain.DomainConsumer; -import Domain.DomainProducer; -import UI.BurpDomain; -import UI.ControlSwitch; -import Utils.Config; -import Utils.DBUtil; +import domain.DomainConsumer; +import domain.DomainProducer; +import ui.BurpDomain; +import ui.ControlSwitch; +import utils.Config; +import utils.DBUtil; public class BurpExtender implements IBurpExtender, ITab, IHttpListener{ @@ -22,16 +22,24 @@ public class BurpExtender implements IBurpExtender, ITab, IHttpListener{ // public static HashSet subDomainSet = new HashSet<>(); public static HashMap> subDomainMap = new HashMap<>(); public static HashMap urlMap = new HashMap<>(); + public static HashMap> similarSubDomainMap = new HashMap<>(); +// public static HashMap> similarDomainMap = new HashMap<>(); + public static HashMap similarUrlMap = new HashMap<>(); public static BlockingQueue inputQueue = new LinkedBlockingQueue<>(); public static BlockingQueue urlQueue = new LinkedBlockingQueue<>(); public static BlockingQueue subDomainQueue = new LinkedBlockingQueue<>(); - public static Integer subDomainCount = 0; - public static Integer urlCount = 0; + public static BlockingQueue similarSubDomainQueue = new LinkedBlockingQueue<>(); + public static BlockingQueue similarUrlQueue = new LinkedBlockingQueue<>(); + public static int subDomainCount = 0; + public static int urlCount = 0; + public static int similarSubDomainCount = 0; + public static int similarUrlCount = 0; public static DBUtil db; public static HashSet currentRootDomainSet = new HashSet<>(); +// public static HashSet rootSimilarDomainSet = new HashSet<>(); public static HashMap config = Config.initDatabaseSetting; public static DomainConsumer domainConsumer = new DomainConsumer(); - public static final String VERSION = "1.0.3"; + public static final String VERSION = "1.0.4"; public static final String EXTENSION_NAME = "BurpDomain"; @Override public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks){ diff --git a/src/Domain/DomainConsumer.java b/src/domain/DomainConsumer.java similarity index 76% rename from src/Domain/DomainConsumer.java rename to src/domain/DomainConsumer.java index 89b7ef2..e393e72 100644 --- a/src/Domain/DomainConsumer.java +++ b/src/domain/DomainConsumer.java @@ -1,13 +1,7 @@ -package Domain; +package domain; -import UI.BurpDomain; import burp.BurpExtender; -import java.security.SecureRandom; -import java.sql.SQLException; -import java.util.HashMap; -import java.util.Map; - //负责将收集的域名信息写入数据库 public class DomainConsumer extends Thread { @@ -28,6 +22,8 @@ public static void QueueToResult(){ if(BurpExtender.db.isConnect){ BurpExtender.db.insertSubDomainQueueToDb(BurpExtender.subDomainQueue); BurpExtender.db.insertUrlQueueToDb(BurpExtender.urlQueue); + BurpExtender.db.insertSimilarSubDomainQueueToDb(BurpExtender.similarSubDomainQueue); + BurpExtender.db.insertSimilarUrlQueueToDb(BurpExtender.similarUrlQueue); } } diff --git a/src/Domain/DomainProducer.java b/src/domain/DomainProducer.java similarity index 59% rename from src/Domain/DomainProducer.java rename to src/domain/DomainProducer.java index 0e55fd4..f2532ee 100644 --- a/src/Domain/DomainProducer.java +++ b/src/domain/DomainProducer.java @@ -1,7 +1,6 @@ -package Domain; +package domain; -import UI.BurpDomain; -import Utils.Config; +import utils.Config; import org.apache.commons.text.StringEscapeUtils; import burp.*; @@ -13,6 +12,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.BlockingQueue; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -77,6 +77,11 @@ public static boolean checkOrigin(List headers){ return false; } + /** + * 对流量进行搜索分析 + * @param message + * @param mode PASSIVE_MODE=0 被动搜索 ACTIVE_MODE=1 主动搜索 + */ public static void handleMessage(IHttpRequestResponse message, int mode){ String reqUrl = helpers.analyzeRequest(message).getUrl().toString(); List headers = helpers.analyzeRequest(message).getHeaders(); @@ -101,11 +106,24 @@ public static void handleMessage(IHttpRequestResponse message, int mode){ domains.addAll(respDomains); urls.addAll(respUrls); } - for (String domain : domains) {handleDomain(domain, mode);} - for (String url : urls) { handleUrl(url);} + //对子域名以及网址进行搜索,如果一个for一次是不是有点笨呢? + for (String domain : domains) { + handleDomain(domain, mode); + //handleSimilarSubDomain(domain,mode); + } + for (String url : urls) { + handleUrl(url); + + } + //在这个地方添加similarDomain } } + /** + * 提取子域名,如果是主动搜索还会提取ip信息 + * @param domain 传入域名进行判断是否为子域名 + * @param mode 判断是被动搜索还是主动搜索 + */ public static void handleDomain(String domain, int mode){ if(isSubdomain(domain)){ // subDomainQueue会定时清空,所有子域名会存在subDomainMap,所以还要加个判断 @@ -122,10 +140,62 @@ public static void handleDomain(String domain, int mode){ data.put("ipAddress", ip); } } + }else if(isSimilarSubDomain(domain)){ + if(!BurpExtender.similarSubDomainQueue.contains(domain)&&!BurpExtender.similarSubDomainMap.containsKey(domain)&&!BurpExtender.currentRootDomainSet.contains(domain)){ + BurpExtender.similarSubDomainQueue.add(domain); + HashMap data = new HashMap<>(); + BurpExtender.similarSubDomainMap.put(domain, data); + String time = getCurrentTime(); + data.put("time", time); + if(mode == ACTIVE_MODE){ + String ip = Config.getDomainIp(domain); + data.put("ipAddress", ip); + } +// BurpExtender.similarSubDomainMap.put(domain, data); + } } } - public static void handleUrl(String url){ +// /** +// * 提取相似域名(暂时没有这个需求,不要使用这个接口) +// * @param domain 传入域名进行判断是否为相似域名 +// * @param mode +// * @deprecated +// */ +// public static void handleSimilarDomain(String domain,int mode){ +// if (isSimilarDomain(domain)){ +// BurpExtender.rootSimilarDomainSet.add(domain); +// } +// } + +/* *//** + *收集相似域名的子域名 + * @param domain + * @param mode + *//* + public static void handleSimilarSubDomain(String domain,int mode){ + if(isSimilarSubDomain(domain)){ + // subDomainQueue会定时清空,所有子域名会存在subDomainMap,所以还要加个判断 + if(!BurpExtender.similarSubDomainQueue.contains(domain)&&!BurpExtender.similarSubDomainMap.containsKey(domain)){ + BurpExtender.similarSubDomainQueue.add(domain); + HashMap data = new HashMap<>(); + BurpExtender.similarSubDomainMap.put(domain, data); + String time = getCurrentTime(); + data.put("time", time); + // 如果是主动搜索可以直接获取IP,即使DNS卡住也不会导致burp堵塞 + // 通过流量被动收集,会定时获取IP,具体实现在DBUtil.insertSubDomainQueueToDb()中 + if(mode == ACTIVE_MODE){ + String ip = Config.getDomainIp(domain); + data.put("ipAddress", ip); + } + } + } + }*/ + /** + * 提取关联网址 + * @param url 传入url进行提取 + */ + public static void handleUrl(String url){ try{ URL u = new URL(url); String domain = u.getHost(); @@ -136,11 +206,19 @@ public static void handleUrl(String url){ String port = String.valueOf(u.getPort()); url = u.getProtocol() + "://" + u.getHost() + ":" + port + path; } - url = getFormatURL(url); - if(isSubdomain(domain) && !uselessExtension(path, USELESS_URL_EXTENSIONS)){ - if(!BurpExtender.urlQueue.contains(url)&&!BurpExtender.urlMap.containsKey(url)){ - BurpExtender.urlQueue.add(url); - BurpExtender.urlMap.put(url, getCurrentTime()); + if (isSubdomain(domain)){ + if(!uselessExtension(path, USELESS_URL_EXTENSIONS)){ + if(!BurpExtender.urlQueue.contains(url)&&!BurpExtender.urlMap.containsKey(url)){ + BurpExtender.urlQueue.add(url); + BurpExtender.urlMap.put(url, getCurrentTime()); + } + } + }else if (isSimilarSubDomain(domain)&!BurpExtender.currentRootDomainSet.contains(domain)){ + if(!uselessExtension(path, USELESS_URL_EXTENSIONS)){ + if(!BurpExtender.similarUrlQueue.contains(url)&&!BurpExtender.similarUrlMap.containsKey(url)){ + BurpExtender.similarUrlQueue.add(url); + BurpExtender.similarUrlMap.put(url, getCurrentTime()); + } } } }catch (Exception e){ @@ -148,14 +226,14 @@ public static void handleUrl(String url){ } } - public static String getFormatURL(String url){ - try{ - - }catch (Exception e){ - BurpExtender.getStderr().println(url); - } - return url; - } +// public static String getFormatURL(String url){ +// try{ +// +// }catch (Exception e){ +// BurpExtender.getStderr().println(url); +// } +// return url; +// } public static String getCurrentTime(){ SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @@ -163,7 +241,7 @@ public static String getCurrentTime(){ return formatter.format(date); } - public static byte[] subByte(byte[] b,int srcPos,int length){ + public static byte[] subByte(byte[] b, int srcPos, int length){ byte[] b1 = new byte[length]; System.arraycopy(b, srcPos, b1, 0, length); return b1; @@ -216,7 +294,11 @@ public static String decodeResp(String resp){ return resp; } - + /** + * 将流量传入到该函数进行解析提取域名 + * @param httpResponse + * @return + */ public static Set grepDomain(String httpResponse) { Set domains = new HashSet<>(); Pattern pDomainNameOnly = Pattern.compile(DOMAIN_NAME_PATTERN); @@ -258,6 +340,11 @@ public static Set grepUrls(String httpResponse){ return urls; } + /** + * 判断是否为子域名 + * @param domain + * @return + */ public static boolean isSubdomain(String domain){ for (String s : BurpExtender.currentRootDomainSet) { if(domain.endsWith("."+s)){ @@ -267,6 +354,54 @@ public static boolean isSubdomain(String domain){ return false; } +// /** +// * 判断是否为相似域名 +// * @param domain +// * @return +// * @deprecated +// */ +// public static boolean isSimilarDomain(String domain){ +// for(String s:BurpExtender.currentRootDomainSet){ +// //思路:考虑将rootdomain进行切割,例如baidu.com使用切割成baidu com,然后对baidu进行相似度匹配 +// String[] tmp = s.split("\\."); +// //通过切割的长度取需要匹配的部分,通过这个来避免当用户设置根域名为www.baidu.com的时候,会匹配成www,baidu的问题,目前直接取baidu,com +// String similarRegex = String.format("(?!-)[A-Za-z0-9-]{0,63}%s[A-Za-z0-9-]{0,63}(? runSearch() throws InterruptedException { + /** + * 创建10个线程进行域名的提取 + * @throws InterruptedException + */ + public void runSearch() throws InterruptedException { IHttpRequestResponse[] messages = BurpExtender.getCallbacks().getSiteMap(null); BurpExtender.inputQueue.addAll(Arrays.asList(messages)); for (int i = 0; i < 10; i++) { @@ -41,7 +44,6 @@ public Map runSearch() throws InterruptedException { while(!BurpExtender.inputQueue.isEmpty()){ sleep(1000); } - return null; } private void searchButtonActionPerformed(ActionEvent e) { @@ -50,7 +52,8 @@ private void searchButtonActionPerformed(ActionEvent e) { @Override protected Map doInBackground() throws Exception{ searchButton.setEnabled(false); - return runSearch(); + runSearch(); + return null; } @Override protected void done(){ @@ -83,7 +86,6 @@ private void connectDatabaseButtonActionPerformed(ActionEvent e) { connectDatabaseButton.setText("Status: Connected"); connectDatabaseButton.setEnabled(false); closeConnectButton.setEnabled(true); -// searchButton.setEnabled(true); BurpExtender.db.init(database); if (!Config.burpDomainConfig.exists()){ try { @@ -163,6 +165,7 @@ private void initComponents() { label5 = new JLabel(); copyAllUrlsButton = new JButton(); copyAllDomainsButton = new JButton(); + tabbedPane1 = new JTabbedPane(); panel1 = new JPanel(); label6 = new JLabel(); label7 = new JLabel(); @@ -170,6 +173,13 @@ private void initComponents() { subDomainTable = new JTable(); scrollPane3 = new JScrollPane(); urlTable = new JTable(); + panel3 = new JPanel(); + label4 = new JLabel(); + label9 = new JLabel(); + scrollPane1 = new JScrollPane(); + similarSubDomainTable = new JTable(); + scrollPane4 = new JScrollPane(); + similarUrlsTable = new JTable(); //======== this ======== setLayout(new GridBagLayout()); @@ -270,67 +280,131 @@ private void initComponents() { GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(10, 0, 5, 0), 0, 0)); - //======== panel1 ======== + //======== tabbedPane1 ======== { - panel1.setLayout(new GridBagLayout()); - ((GridBagLayout)panel1.getLayout()).columnWidths = new int[] {0, 0, 0}; - ((GridBagLayout)panel1.getLayout()).rowHeights = new int[] {0, 0, 0}; - ((GridBagLayout)panel1.getLayout()).columnWeights = new double[] {0.35, 0.65, 1.0E-4}; - ((GridBagLayout)panel1.getLayout()).rowWeights = new double[] {0.0, 1.0, 1.0E-4}; - - //---- label6 ---- - label6.setText("Sub Domians"); - panel1.add(label6, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, - GridBagConstraints.CENTER, GridBagConstraints.VERTICAL, - new Insets(0, 0, 5, 5), 0, 0)); - //---- label7 ---- - label7.setText("Urls"); - panel1.add(label7, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, - GridBagConstraints.CENTER, GridBagConstraints.VERTICAL, - new Insets(0, 0, 5, 0), 0, 0)); - - //======== scrollPane2 ======== + //======== panel1 ======== { - - //---- subDomainTable ---- - subDomainModel = new DefaultTableModel(null, subDomainColumnNames){ - @Override - public Class getColumnClass(int column) { return getValueAt(0,column).getClass();} - }; - subDomainTable.setModel(subDomainModel); - subDomainTable.setSurrendersFocusOnKeystroke(true); - subDomainTable.setAutoCreateRowSorter(true); - subDomainTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); - scrollPane2.setViewportView(subDomainTable); + panel1.setLayout(new GridBagLayout()); + ((GridBagLayout)panel1.getLayout()).columnWidths = new int[] {0, 0, 0}; + ((GridBagLayout)panel1.getLayout()).rowHeights = new int[] {0, 0, 0}; + ((GridBagLayout)panel1.getLayout()).columnWeights = new double[] {0.35, 0.65, 1.0E-4}; + ((GridBagLayout)panel1.getLayout()).rowWeights = new double[] {0.0, 1.0, 1.0E-4}; + + //---- label6 ---- + label6.setText("Sub Domians"); + panel1.add(label6, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.VERTICAL, + new Insets(0, 0, 5, 5), 0, 0)); + + //---- label7 ---- + label7.setText("Urls"); + panel1.add(label7, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.VERTICAL, + new Insets(0, 0, 5, 0), 0, 0)); + + //======== scrollPane2 ======== + { + + //---- subDomainTable ---- + subDomainModel = new DefaultTableModel(null, subDomainColumnNames){ + @Override + public Class getColumnClass(int column) { return getValueAt(0,column).getClass();} + }; + subDomainTable.setModel(subDomainModel); + subDomainTable.setSurrendersFocusOnKeystroke(true); + subDomainTable.setAutoCreateRowSorter(true); + subDomainTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); + scrollPane2.setViewportView(subDomainTable); + } + panel1.add(scrollPane2, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 0, 5), 0, 0)); + + //======== scrollPane3 ======== + { + + //---- urlTable ---- + urlModel = new DefaultTableModel(null, urlColumnNames){ + @Override + public Class getColumnClass(int column) { return getValueAt(0,column).getClass();} + }; + urlTable.setModel(urlModel); + urlTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); + urlTable.setSurrendersFocusOnKeystroke(true); + urlTable.setAutoCreateRowSorter(true); + scrollPane3.setViewportView(urlTable); + } + panel1.add(scrollPane3, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 0, 0), 0, 0)); } - panel1.add(scrollPane2, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, - GridBagConstraints.CENTER, GridBagConstraints.BOTH, - new Insets(0, 0, 0, 5), 0, 0)); + tabbedPane1.addTab("Exact Match", panel1); - //======== scrollPane3 ======== + //======== panel3 ======== { - - //---- urlTable ---- - urlModel = new DefaultTableModel(null, urlColumnNames){ - @Override - public Class getColumnClass(int column) { return getValueAt(0,column).getClass();} - }; - urlTable.setModel(urlModel); - urlTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); - urlTable.setSurrendersFocusOnKeystroke(true); - urlTable.setAutoCreateRowSorter(true); - scrollPane3.setViewportView(urlTable); + panel3.setLayout(new GridBagLayout()); + ((GridBagLayout)panel3.getLayout()).columnWidths = new int[] {0, 0, 0}; + ((GridBagLayout)panel3.getLayout()).rowHeights = new int[] {0, 0, 0}; + ((GridBagLayout)panel3.getLayout()).columnWeights = new double[] {0.35, 0.65, 1.0E-4}; + ((GridBagLayout)panel3.getLayout()).rowWeights = new double[] {0.0, 1.0, 1.0E-4}; + + //---- label4 ---- + label4.setText("Similar Sub Domain"); + panel3.add(label4, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.VERTICAL, + new Insets(0, 0, 5, 5), 0, 0)); + + //---- label9 ---- + label9.setText("Similar Urls"); + panel3.add(label9, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.VERTICAL, + new Insets(0, 0, 5, 0), 0, 0)); + + //======== scrollPane1 ======== + { + + //---- similarSubDomainTable ---- + similarSubDomainModel = new DefaultTableModel(null, subDomainColumnNames){ + @Override + public Class getColumnClass(int column) { return getValueAt(0,column).getClass();} + }; + similarSubDomainTable.setModel(similarSubDomainModel); + similarSubDomainTable.setSurrendersFocusOnKeystroke(true); + similarSubDomainTable.setAutoCreateRowSorter(true); + similarSubDomainTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); + scrollPane1.setViewportView(similarSubDomainTable); + } + panel3.add(scrollPane1, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 0, 5), 0, 0)); + + //======== scrollPane4 ======== + { + + //---- similarUrlsTable ---- + similarUrlModel = new DefaultTableModel(null, urlColumnNames){ + @Override + public Class getColumnClass(int column) { return getValueAt(0,column).getClass();} + }; + similarUrlsTable.setModel(similarUrlModel); + similarUrlsTable.setSurrendersFocusOnKeystroke(true); + similarUrlsTable.setAutoCreateRowSorter(true); + similarUrlsTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); + scrollPane4.setViewportView(similarUrlsTable); + } + panel3.add(scrollPane4, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 0, 0), 0, 0)); } - panel1.add(scrollPane3, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, - GridBagConstraints.CENTER, GridBagConstraints.BOTH, - new Insets(0, 0, 0, 0), 0, 0)); + tabbedPane1.addTab("Similar Matching", panel3); } - add(panel1, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, + add(tabbedPane1, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); // JFormDesigner - End of component initialization //GEN-END:initComponents - resizeColumnWidth(); + resizeColumnWidth(subDomainTable,urlTable); + resizeColumnWidth(similarSubDomainTable,similarUrlsTable); } public static void addSubDomainToUI(String domain, String ip, String time){ @@ -340,6 +414,13 @@ public static void addSubDomainToUI(String domain, String ip, String time){ public static void addURLToUI(String url, String time){ urlModel.addRow(new Object[]{BurpExtender.urlCount, url, time}); } + public static void addSimilarSubDomainToUI(String domain, String ip, String time){ + similarSubDomainModel.addRow(new Object[]{BurpExtender.similarSubDomainCount, domain, ip, time}); + } + public static void addSimilarUrlToUI(String url, String time){ + + similarUrlModel.addRow(new Object[]{BurpExtender.similarUrlCount, url, time}); + } // 2022年01月10日21:02:25 修复了排序数据后切换项目插件UI崩溃的情况 public void clearUI(){ @@ -353,15 +434,28 @@ public void clearUI(){ urlModel.setColumnIdentifiers(urlColumnNames); urlModel.setRowCount(0); } - resizeColumnWidth(); + if (BurpExtender.similarSubDomainCount > 0){ + BurpExtender.similarSubDomainCount = 0; + similarSubDomainModel.setColumnIdentifiers(subDomainColumnNames); + similarSubDomainModel.setRowCount(0); + } + if (BurpExtender.similarUrlCount > 0){ + BurpExtender.similarUrlCount = 0; + similarUrlModel.setColumnIdentifiers(urlColumnNames); + similarUrlModel.setRowCount(0); + } + resizeColumnWidth(subDomainTable,urlTable); + resizeColumnWidth(similarSubDomainTable,similarUrlsTable); } - //自适应宽度 - private void resizeColumnWidth() { - subDomainTable.getColumnModel().getColumn(0).setPreferredWidth(50); - subDomainTable.getColumnModel().getColumn(1).setPreferredWidth(385); - subDomainTable.getColumnModel().getColumn(2).setPreferredWidth(160); - subDomainTable.getColumnModel().getColumn(3).setPreferredWidth(160); + /** + * 自适应宽度 + */ + private void resizeColumnWidth(JTable domainTable,JTable urlTable){ + domainTable.getColumnModel().getColumn(0).setPreferredWidth(50); + domainTable.getColumnModel().getColumn(1).setPreferredWidth(385); + domainTable.getColumnModel().getColumn(2).setPreferredWidth(160); + domainTable.getColumnModel().getColumn(3).setPreferredWidth(160); urlTable.getColumnModel().getColumn(0).setPreferredWidth(50); urlTable.getColumnModel().getColumn(1).setPreferredWidth(650); @@ -424,16 +518,28 @@ public void projectDoneAction(String currentProject){ searchButton.setEnabled(true); BurpExtender.subDomainMap = BurpExtender.db.getSubDomainMap(currentProject); BurpExtender.urlMap = BurpExtender.db.getUrlMap(currentProject); + BurpExtender.similarSubDomainMap = BurpExtender.db.getSimilarSubDomainMap(currentProject); + BurpExtender.similarUrlMap = BurpExtender.db.getSimilarUrlMap(currentProject); for(Map.Entry entry: BurpExtender.urlMap.entrySet()){ BurpExtender.urlCount += 1; String createTime = entry.getValue(); addURLToUI(entry.getKey(), createTime); } + for(Map.Entry entry: BurpExtender.similarUrlMap.entrySet()){ + BurpExtender.similarUrlCount += 1; + String createTime = entry.getValue(); + addSimilarUrlToUI(entry.getKey(), createTime); + } for(Map.Entry> entry: BurpExtender.subDomainMap.entrySet()){ BurpExtender.subDomainCount += 1; HashMap value = entry.getValue(); addSubDomainToUI(entry.getKey(), value.get("ipAddress"), value.get("createTime")); } + for(Map.Entry> entry: BurpExtender.similarSubDomainMap.entrySet()){ + BurpExtender.similarSubDomainCount += 1; + HashMap value = entry.getValue(); + addSimilarSubDomainToUI(entry.getKey(), value.get("ipAddress"), value.get("createTime")); + } } } } @@ -459,6 +565,7 @@ public void initBurpDomain(){ private JLabel label5; private JButton copyAllUrlsButton; private JButton copyAllDomainsButton; + private JTabbedPane tabbedPane1; private JPanel panel1; private JLabel label6; private JLabel label7; @@ -466,10 +573,19 @@ public void initBurpDomain(){ private JTable subDomainTable; private JScrollPane scrollPane3; private JTable urlTable; + private JPanel panel3; + private JLabel label4; + private JLabel label9; + private JScrollPane scrollPane1; + private JTable similarSubDomainTable; + private JScrollPane scrollPane4; + private JTable similarUrlsTable; // JFormDesigner - End of variables declaration //GEN-END:variables private static DefaultTableModel subDomainModel; private static DefaultTableModel urlModel; - private static final String[] subDomainColumnNames = {"#", "Domain", "IP", "Time"}; + private static DefaultTableModel similarSubDomainModel; + private static DefaultTableModel similarUrlModel; + private static final String[] subDomainColumnNames = {"#", "domain", "IP", "Time"}; private static final String[] urlColumnNames = {"#", "URL", "Time"}; } diff --git a/src/UI/ControlSwitch.java b/src/ui/ControlSwitch.java similarity index 98% rename from src/UI/ControlSwitch.java rename to src/ui/ControlSwitch.java index 56f90bb..657ab5b 100644 --- a/src/UI/ControlSwitch.java +++ b/src/ui/ControlSwitch.java @@ -1,11 +1,10 @@ -package UI; +package ui; import java.awt.event.*; -import Utils.Config; -import Utils.DBUtil; +import utils.Config; +import utils.DBUtil; import java.awt.*; -import java.util.ArrayList; import java.util.Arrays; import java.util.Map; import javax.swing.*; diff --git a/src/UI/NewProject.java b/src/ui/NewProject.java similarity index 99% rename from src/UI/NewProject.java rename to src/ui/NewProject.java index e5681a2..0c7ba36 100644 --- a/src/UI/NewProject.java +++ b/src/ui/NewProject.java @@ -2,7 +2,7 @@ * Created by JFormDesigner on Mon Jan 03 16:50:09 CST 2022 */ -package UI; +package ui; import burp.BurpExtender; diff --git a/src/Utils/Config.java b/src/utils/Config.java similarity index 98% rename from src/Utils/Config.java rename to src/utils/Config.java index 4e470f8..b9016f0 100644 --- a/src/Utils/Config.java +++ b/src/utils/Config.java @@ -1,4 +1,4 @@ -package Utils; +package utils; import burp.BurpExtender; import com.google.gson.Gson; @@ -7,7 +7,6 @@ import java.io.*; import java.net.InetAddress; -import java.net.URL; import java.net.UnknownHostException; import java.util.HashMap; diff --git a/src/Utils/DBUtil.java b/src/utils/DBUtil.java similarity index 69% rename from src/Utils/DBUtil.java rename to src/utils/DBUtil.java index 110be44..a5cf5d6 100644 --- a/src/Utils/DBUtil.java +++ b/src/utils/DBUtil.java @@ -1,8 +1,9 @@ -package Utils; +package utils; import java.sql.*; -import UI.BurpDomain; +import domain.DomainProducer; +import ui.BurpDomain; import burp.BurpExtender; import com.google.common.base.Joiner; @@ -88,14 +89,16 @@ public void closeConn(){ * @param db */ private void initMysql(String db){ - HashMap tables = new HashMap(4){ + HashMap tables = new HashMap(6){ { + //项目表 put("Project","CREATE TABLE `Project` (\n" + " `id` int(11) NOT NULL AUTO_INCREMENT,\n" + " `projectName` varchar(64) NOT NULL,\n" + " PRIMARY KEY (`id`),\n" + " UNIQUE KEY `Project_projectName_uindex` (`projectName`)\n" + ");"); + //根域名表 put("RootDomain","CREATE TABLE `RootDomain` (\n" + " `id` int(11) NOT NULL AUTO_INCREMENT,\n" + " `rootDomainName` varchar(64) NOT NULL,\n" + @@ -103,6 +106,7 @@ private void initMysql(String db){ " PRIMARY KEY (`id`),\n" + " UNIQUE KEY `RootDomain_domainName_uindex` (`rootDomainName`)\n" + ");"); + //子域名表 put("SubDomain","CREATE TABLE `SubDomain` (\n" + " `id` int(11) NOT NULL AUTO_INCREMENT,\n" + " `subDomainName` varchar(128) NOT NULL,\n" + @@ -112,13 +116,33 @@ private void initMysql(String db){ " PRIMARY KEY (`id`),\n" + " UNIQUE KEY `SubDomain_subDomainName_uindex` (`subDomainName`)\n" + ");"); + //url表 put("Url","CREATE TABLE `Url` (\n" + " `id` int(11) NOT NULL AUTO_INCREMENT,\n" + " `url` varchar(256) NOT NULL,\n" + " `projectName` varchar(64) NOT NULL,\n" + " `createTime` datetime NOT NULL,\n" + " PRIMARY KEY (`id`),\n" + - " UNIQUE KEY `SubDomain_subDomainName_uindex` (`url`)\n" + + " UNIQUE KEY `Url_url_uindex` (`url`)\n" + + ");"); + //相似域名表 + put("SimilarSubDomain","CREATE TABLE `SimilarSubDomain`(\n" + + " `id` int(11) NOT NULL AUTO_INCREMENT,\n" + + " `subDomainName` varchar(128) NOT NULL,\n" + + " `rootDomainName` varchar(64) DEFAULT NULL,\n" + + " `ipAddress` varchar(64) DEFAULT NULL,\n" + + " `createTime` datetime NOT NULL,\n" + + " PRIMARY KEY (`id`),\n" + + " UNIQUE KEY `SimilarSubDomain_similarDomainName_uindex` (`subDomainName`)\n" + + ");"); + //相似域名子域名表 + put("SimilarUrl","CREATE TABLE `SimilarUrl`(\n" + + " `id` int(11) NOT NULL AUTO_INCREMENT,\n" + + " `url` varchar(64) NOT NULL,\n" + + " `projectName` varchar(64) NOT NULL,\n" + + " `createTime` datetime NOT NULL,\n" + + " PRIMARY KEY (`id`),\n" + + " UNIQUE KEY `SimilarUrl_url_uindex` (`url`)\n" + ");"); } }; @@ -173,6 +197,23 @@ private void initSqlite(String db){ " CONSTRAINT \"id\" PRIMARY KEY (\"id\")\n" + " CONSTRAINT \"Url_projectName_uindex\" UNIQUE (\"url\")"+ ");"); + put("SimilarSubDomain","CREATE TABLE \"main\".\"SimilarSubDomain\" (\n" + + " \"id\" integer NOT NULL,\n" + + " \"SubDomainName\" TEXT,\n" + + " \"rootDomainName\" TEXT,\n" + + " \"ipAddress\" TEXT,\n" + + " \"createTime\" TEXT,\n" + + " CONSTRAINT \"id\" PRIMARY KEY (\"id\")\n" + + " CONSTRAINT \"SimilarSubDomain_projectName_uindex\" UNIQUE (\"SubDomainName\")"+ + ");"); + put("SimilarUrl","CREATE TABLE \"main\".\"SimilarUrl\" (\n" + + " \"id\" integer NOT NULL,\n" + + " \"url\" TEXT,\n" + + " \"projectName\" TEXT,\n" + + " \"createTime\" TEXT,\n" + + " CONSTRAINT \"id\" PRIMARY KEY (\"id\")\n" + + " CONSTRAINT \"SimilarUrl_projectName_uindex\" UNIQUE (\"url\")"+ + ");"); } }; try{ @@ -242,6 +283,10 @@ public void insertData(String rootDomainName,String projectName){ } } + /** + * 往数据库增加子域名 + * @param queue + */ public void insertSubDomainQueueToDb(BlockingQueue queue) { String sql = null; switch (mode){ @@ -275,7 +320,6 @@ public void insertSubDomainQueueToDb(BlockingQueue queue) { psSQL.setString(2, getRootDomain(subDomain)); psSQL.setString(3, ip); psSQL.setString(4, data.get("time")); - // BurpExtender.subDomainMap.get(subDomain).put("status", "1"); psSQL.addBatch(); } psSQL.executeBatch(); @@ -284,6 +328,50 @@ public void insertSubDomainQueueToDb(BlockingQueue queue) { } } + /** + * 插入相似域名的信息 + * @param queue + */ + public void insertSimilarSubDomainQueueToDb(BlockingQueue queue) { + String sql = null; + switch (mode){ + case MYSQL_DB: + sql = "insert ignore into SimilarSubDomain (subDomainName,rootDomainName,ipAddress,createTime) values (?,?,?,?)"; + break; + case SQLITE_DB: + sql = "insert or ignore into SimilarSubDomain ([subDomainName],[rootDomainName],[ipAddress],[createTime]) values (?,?,?,?)"; + break; + default: + break; + } + try { + PreparedStatement psSQL = conn.prepareStatement(sql); + while (!queue.isEmpty()){ + String subDomain = queue.take(); + HashMap data = BurpExtender.similarSubDomainMap.get(subDomain); + if(data==null){ + continue; + } + String ip = data.get("ipAddress"); + if(ip==null) { + // 用后台的线程去获取IP,防止DNS延迟造成burp流量堵塞 + ip = Config.getDomainIp(subDomain); + BurpExtender.similarSubDomainMap.get(subDomain).put("ipAddress", ip); + } + BurpExtender.similarSubDomainCount += 1; + BurpDomain.addSimilarSubDomainToUI(subDomain, ip, data.get("time")); + psSQL.setString(1, subDomain); + psSQL.setString(2, getSimilarRootDomain(subDomain)); + psSQL.setString(3, ip); + psSQL.setString(4, data.get("time")); + psSQL.addBatch(); + } + psSQL.executeBatch(); + } catch (Exception e) { + BurpExtender.getStderr().println(e); + } + } + public void insertUrlQueueToDb(BlockingQueue queue){ String sql = null; switch (mode){ @@ -318,8 +406,42 @@ public void insertUrlQueueToDb(BlockingQueue queue){ } } + public void insertSimilarUrlQueueToDb(BlockingQueue queue){ + String sql = null; + switch (mode){ + case MYSQL_DB: + sql = "insert ignore into SimilarUrl (url, createTime, projectName) values (?,?,?)"; + break; + case SQLITE_DB: + sql = "insert or ignore into SimilarUrl ([url], [createTime], [projectName]) values (?,?,?)"; + break; + default: + break; + } + String currentProject = BurpExtender.config.get("currentProject"); + try{ + PreparedStatement pSQL = conn.prepareStatement(sql); + while(!queue.isEmpty()){ + String url = queue.take(); + String createTime = BurpExtender.similarUrlMap.get(url); + if(createTime==null){ + continue; + } + BurpExtender.similarUrlCount += 1; + BurpDomain.addSimilarUrlToUI(url, createTime); + pSQL.setString(1, url); + pSQL.setString(2, createTime); + pSQL.setString(3, currentProject); + pSQL.addBatch(); + } + pSQL.executeBatch(); + }catch (Exception e){ + BurpExtender.getStderr().println(e); + } + } + /** - * + * 获取根域名 * @param subDomain * @return * (用了新的正则后,这个问题解决了)这里有BUG,目前的正则会匹配到-elis-ecocdn.pingan.com.cn这样错误的域名,然后调用Google这个API就会抛异常 @@ -330,6 +452,21 @@ private String getRootDomain(String subDomain){ return tmpDomain[tmpDomain.length-1]+"."+suffix; } + /** + * + */ + private String getSimilarRootDomain(String subDomain){ + for (String s:BurpExtender.currentRootDomainSet){ + if(DomainProducer.isSimilarSubDomain(subDomain)){ + return s; + } + } + return null; + } + /** + * 创建项目 + * @param projectName + */ public void addProject(String projectName){ String sql = null; switch (mode){ @@ -350,6 +487,11 @@ public void addProject(String projectName){ e.printStackTrace(); } } + + /** + * 删除项目 + * @param projectName + */ public void removeProject(String projectName){ String sql = "DELETE FROM Project WHERE projectName = ?;"; try{ @@ -361,6 +503,11 @@ public void removeProject(String projectName){ } } + /** + * 添加根域名 + * @param projectName + * @param domainName + */ public void addRootDomain(String projectName, String domainName){ String sql = null; switch (mode){ @@ -383,6 +530,11 @@ public void addRootDomain(String projectName, String domainName){ } } + /** + * 删除根域名 + * @param projectName + * @param domainName + */ public void removeRootDomain(String projectName,String domainName){ String sql = "delete from RootDomain where projectName = ? and rootDomainName = ?"; try{ @@ -394,13 +546,17 @@ public void removeRootDomain(String projectName,String domainName){ e.printStackTrace(); } } + + /** + * 获取项目的Set + * @return + */ public HashSet getProjectSet(){ String sql = "select ProjectName from Project"; - ResultSet set = null; HashSet projectList = new HashSet<>(); try { PreparedStatement preSQl = conn.prepareStatement(sql); - set = preSQl.executeQuery(); + ResultSet set = preSQl.executeQuery(); while(set.next()){ projectList.add(set.getString("ProjectName")); } @@ -427,31 +583,39 @@ public HashSet getRootDomainSet(String projectName){ return rootDomainList; } - public HashMap getUrlMap(String projectName){ - HashMap urlMap = new HashMap<>(); - String sql = "select url, createTime from Url where projectName=?"; - ResultSet set; - try{ - PreparedStatement preSQL = conn.prepareStatement(sql); - preSQL.setString(1, projectName); - set = preSQL.executeQuery(); + public HashMap> getSubDomainMap(String projectName){ + HashMap> subDomainMap = new HashMap<>(); + Object[] rootDomainList = getRootDomainSet(projectName).toArray(); + String[] inSql = new String[rootDomainList.length]; + Arrays.fill(inSql, "?"); + // 还是改回来了,不知道为啥,下面的那个方法取不到数据 + String sql = "select subDomainName,rootDomainName,ipAddress,createTime from SubDomain where rootDomainName in ("+Joiner.on(",").join(inSql)+")"; + try { + PreparedStatement preSQl = conn.prepareStatement(sql); + for (int i=0;i data = new HashMap<>(); + data.put("ipAddress", set.getString("ipAddress")); + data.put("createTime", set.getString("createTime")); + data.put("status", "1"); + subDomainMap.put(set.getString("subDomainName"), data); } - }catch (SQLException e){ + } catch (SQLException e) { BurpExtender.getStderr().println(e); } - return urlMap; + return subDomainMap; } - - public HashMap> getSubDomainMap(String projectName){ + public HashMap> getSimilarSubDomainMap(String projectName){ HashMap> subDomainMap = new HashMap<>(); Object[] rootDomainList = getRootDomainSet(projectName).toArray(); String[] inSql = new String[rootDomainList.length]; Arrays.fill(inSql, "?"); // 还是改回来了,不知道为啥,下面的那个方法取不到数据 - String sql = "select subDomainName,rootDomainName,ipAddress,createTime from SubDomain where rootDomainName in ("+Joiner.on(",").join(inSql)+")"; + String sql = "select subDomainName,rootDomainName,ipAddress,createTime from SimilarSubDomain where rootDomainName in ("+Joiner.on(",").join(inSql)+")"; try { PreparedStatement preSQl = conn.prepareStatement(sql); for (int i=0;i> getSubDomainMap(String projectNa return subDomainMap; } + public HashMap getUrlMap(String projectName){ + HashMap urlMap = new HashMap<>(); + String sql = "select url, createTime from Url where projectName=?"; + ResultSet set; + try{ + PreparedStatement preSQL = conn.prepareStatement(sql); + preSQL.setString(1, projectName); + set = preSQL.executeQuery(); + while(set.next()){ + urlMap.put(set.getString("url"), set.getString("createTime")); + } + }catch (SQLException e){ + BurpExtender.getStderr().println(e); + } + return urlMap; + } + public HashMap getSimilarUrlMap(String projectName){ + HashMap urlMap = new HashMap<>(); + String sql = "select url, createTime from SimilarUrl where projectName=?"; + ResultSet set; + try{ + PreparedStatement preSQL = conn.prepareStatement(sql); + preSQL.setString(1, projectName); + set = preSQL.executeQuery(); + while(set.next()){ + urlMap.put(set.getString("url"), set.getString("createTime")); + } + }catch (SQLException e){ + BurpExtender.getStderr().println(e); + } + return urlMap; + } + // public HashMap> getSubDomainMap(String projectName){ // HashMap> subDomainMap = new HashMap<>(); // Object[] rootDomainList = getRootDomainSet(projectName).toArray();