From aaa46375bd9a79a5c3c07a588dd6b7055f2fb1d3 Mon Sep 17 00:00:00 2001 From: anOtherAnalyse <23277378+anOtherAnalyse@users.noreply.github.com> Date: Mon, 12 Jan 2026 13:26:49 +0100 Subject: [PATCH] Symless 1.1 --- .gitignore | 4 - README.md | 172 +++-- img/plugin-demo.gif | Bin 7445305 -> 0 bytes img/plugin_builder_form.png | Bin 0 -> 69826 bytes img/plugin_built_structure.png | Bin 0 -> 106971 bytes img/plugin_context_menu.png | Bin 0 -> 27266 bytes plugin/symless_plugin.py | 68 +- run_script.py | 40 +- scripts/ctors.py | 14 +- scripts/dump.py | 17 +- scripts/entries.py | 9 +- scripts/functions.py | 47 -- scripts/vtables.py | 21 +- symless.py | 4 +- symless/__init__.py | 4 +- symless/allocators.py | 61 +- symless/config/__init__.py | 1 + symless/config/config.json | 3 +- symless/config/imports.csv | 9 + symless/conflict.py | 39 +- symless/cpustate/__init__.py | 817 ++++++-------------- symless/cpustate/arch.py | 241 +----- symless/cpustate/cpustate.py | 1035 +++++++++++-------------- symless/existing.py | 187 +++-- symless/generation/__init__.py | 269 +++++-- symless/generation/generate.py | 354 ++++++--- symless/generation/structures.py | 76 +- symless/main.py | 9 +- symless/model/__init__.py | 333 ++++---- symless/model/entrypoints.py | 247 +++--- symless/model/model.py | 211 +++--- symless/plugins/__init__.py | 4 + symless/plugins/builder.py | 1084 +++++++++++++++++++-------- symless/resources/bigger_champi.png | Bin 22991 -> 36854 bytes symless/resources/cross.png | Bin 0 -> 1823 bytes symless/symbols/__init__.py | 12 +- symless/symbols/rename.py | 4 +- symless/utils/ida_utils.py | 467 ++++++------ symless/utils/utils.py | 9 + symless/utils/vtables.py | 228 ++++++ 40 files changed, 3210 insertions(+), 2890 deletions(-) delete mode 100644 img/plugin-demo.gif create mode 100644 img/plugin_builder_form.png create mode 100644 img/plugin_built_structure.png create mode 100644 img/plugin_context_menu.png delete mode 100644 scripts/functions.py create mode 100644 symless/resources/cross.png create mode 100644 symless/utils/vtables.py diff --git a/.gitignore b/.gitignore index 250595f..f53d18e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,2 @@ __pycache__ .vscode -custom_hooks.py -tests/bin/* -tests/out/* -tests/Makefile diff --git a/README.md b/README.md index 9546154..e01c6a7 100644 --- a/README.md +++ b/README.md @@ -1,77 +1,95 @@ -# Symless - -Automatic structures recovering plugin for IDA. Able to reconstruct structures/classes and virtual tables used in a binary. - -### Features -* Automatic creation of identified structures (c++ classes, virtual tables and others) -* Xrefs on structures usages -* Functions typing using gathered information - -Two modes are available: **Pre-Analysis** and **Plugin**. - -## Plugin mode -Interactive IDA plugin. Uses static analysis from an entry point selected by the user to build and propagate a structure. - -
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
j-flPCw>p?-F;l%dWfEtEr%qr)XkJ zRSK8QMW;!)H5K;~&^{_iw@1xS7v$5;5L@@XkV;mid{piP35?ATvekm>-v^oWYUgoP zXdunCI;}i&O#>mVN!rq9PtE4Hik(Hf)(W%8CEmRF=VW&oq1{meu0id*pX54EYh*Ww z%rztFsNH+Tq5eO^1YA%Eh=^C$sRgO+@%OB6a@7T$v-R`0BGtI_&e!v_0BYQBp7IE2 zpLPpjl_Y{~q(A5Gd;{#+bHg74D!S~e+DX>pe;70rQl|j!2Z36r8eE<;2_$rT8Iq2ED=1kkl6%{6Ic%?_Sie~4`7 z`*KNtb+sV$o3r+EOead8CWQ-i0uiWMDe>CsMP#iG2BA?)H(e{To(s1Niuj_UnfF OzDBlzK>pSzaF4pdcUHUs6(k%4aLwyzbI%yf#M?!bO}hEpt-NsR~3+8uc_(l zOzvXvFd<)C|9MHTb0zyf?Y~ `0m-jwuEz7;)Pr)mYUmFELfRxrK3M`B;P*bzzxhTf1GKM$QQ}QgtYs+CsM;Y! zoyp$9FPd)ifr=dr$=mg`2RLEHeBoC_%mN3qLKOMR5&2ET3OHDpo~THhsFXlYOtDQ= z@#Ump*z?A;ynm!AXN}{{08k!Dj23z>h<5|TlOy)pgLukAD*M1 1(z^9mJ1=GPNN}OJxayC3Q#mw(8 fXfN!4x%GX69ao+yhE~0DZ26_5Fb9hHUJ{a`NfX9GS< |WffgI5>sU0pdC|Mgz{?}OI__pZT=Xd<07sm&`38@ciPU{)zcj*h_ZvVk;2 zBo|xuTU{CP;(_yno6+KN-uS5bVAHZC^W TTorIV(08EEr=W zbVy4$x^V+(M7q@x(hVvI=tfBiBc;@VfP?|kh&T{QQ9wj62MQ|2AH>Ai!}IQ(7w6Tv zKj*%$>-zq_XQb`%i)Y|IGC(iALYH_BVrddrk3T)@rGrT@5Krk7rHph8N!)1|#WLs= z3#q>MTt!pQ5u6w0BYlU4AcTO#2$pD~{@`ut>M3`aM0}yBjlsdQh0(sXZ!2Rw=wiSS zP71^-NgbGUAB0OZ*a=+8sVLqwATK>_JbB9cv|-cP{-#31=JSTnWqM2Y_V%#KiWc{r zv~%x~zmTtTnBv4a_hJzvbtsZvoo`bvLaG-U2e@$7Qw_WQrxznpb5YXUY}m7_Nu-1X zazY9z`)zr|Yz)3F2t|!8-=Ex>n23J!$|=>qQ`E3fwEqjL`dsQtrd1wRj?Z!nzl8mR zD{3>!m;Dt!Ae|jqb5rYgWKmIX*Y<6%<8n9qM$c80FIS%UBz~dDX>e2giVG(_hjj1I zzJ+(W3*S!Nz0J17jzR$IlFmpEaH+9GE!yrz7ds y{!u|>6~ zKo(s(>xQpua;> om-SAXbQJV+*{+<+Yle4`2eCp4Wp8nQX zb<;vUty>gKdFnIS?~m+KTRo1uy#0GZ<@C!Zw;w&zQAW7EGWt$;xV^gHWbG(_a4p#M zZS>&Vlcw*^48A*S`o3`R{dv>%OM~lIOg|h-6;TD^e5b@{Lt?)4?m+OHJ*LO_V3#NB zzx|jV$HM;t=wec!nCFnVB;iX5;qebKmD{f_}q(Y-mAJ7?kcGBx^2$yv8btt z4KO_ZbUx{$XWZ(@acXdZvEtU;{R@gd PF+&krwd`t3W^Wtl^| zV_}htlf5FltrhX|b=kx3sed|CH-F!|f%uogPwK0?arxgr6}HMBM_b1sod@siME;Qi zXSk@xapAN(-7Of?QU!bVFy^ldR$hy^G;%;RAmG3~8&c&6-hq+tWJ%s%IXfyD%fIh5 zCY|(gc5F8b?L01%qdGTE-rwAAd61Dmjkh;ls<$Lt7?|f!XYlXy&9Idmte67tHOqun zT4=t#K!x5NoDXTUANVrmd{^sJ^^9tV$N{Q3&MA(48}T7!>(2I`&S(b=RLs?>-#zT> zWkVBhxyggtvl%#Vd{RIb8R^8rxg@wcPsrM+J$9v(WN1vd9g2MX*dt!*xTu3|bJv1T z82s1*>0mp43Nh_ye$D~^KJXFQ)lsHU_h-a{m+2DEdPJN2G246V;`G8&SgUl*0r=|t z_k8O3r(v}2{0BRepPq*4UJyywC&pp-u044fWr3b}nfmLod%mrIr996S;7@quTO?d? zBUl=OS9TChRt45RuoQ2Z=XEXC!_#0*-%akyo4^uR^_On04onxFz#^llrDIYS=QJzB ziYxopyme+tt6EveyWRyy#xpPYUY}@?iX?3Iy=pL-bM_9s;2tBVR(XBfOY5n%Gr?sY zd6#YBIUG==KB6m^uQD$EB%ew$USw;|)q95(o26B~@8A7bH@fxLLb)uXvwgHG{JMt4 zdzg)VMad!6iPf6RUCM83JP0`X(R{r@ Sl&%L1A8{4efhT<}#|1Qicv5p=WwF~;*SoOMOcC}3Wigv@fi~IRuKj6U+a{g3Z zb|cx`w)9%R`1`-xnB9Li@9jGy|83GSI(chJ@zvk&xA(t7A9+^@7uRr>$r4ukL$WMz z4Qfa2ulL90VSS{DvE5XjKhe+e)$ax35S4~K{nq@|wo=8AV3cF}xi4hiI4Bb5D=X#= z93{!gH^?cciNB4h(TxKOJgAUFXXjesq_;-W>*HB@tuVDj4I%#x2&sdFp!%|eJns7w zrz;L?#elg%uvyZ8;{~1K5VS{v0BK-xS^S*q-3r_diKi3+y@D%wi%q$r&D6Wtg|{8D z`UM4jGl<; UgD&2k#Uv8zgFrKg;-73EQ)`o^ 1FAA@>Y5+vw2aSWqsPA)+SZXW!GIB+MmA^ z1K#E8Y}APjV6#+)IhnQ_!-Tw@Ld+%BVV?v9yR#W7^ZR+W=da(q9Ig^-W6|$iYWDcD zorSXX$t6cd)bXO-`M$_=Irj6!a(Q1}|K-Y!>dzU|vm5=iMv26!S?zo#-d% z`}`3J{c(>56Ze4oAf9xcq-yehDc|qDnP@d_kGeW)Aa}Ow`rzHg7F!K1?Oit{`jz1K zh)+hf-t6@K8V;y4V>?OignFk>?_81%=32wt>eJ@mxrD3uT>q@wdLvVHUzUuZYegh6 zk}9Ky)}T3V%wq?*P&L3WlR8o-oS1E4hxz5ya9X>e
mm_byYs_FF$M;#@CHx9%0cZhe!QM?Z~}G z@2~WGrKFv%8xK?o6VI#ZTk*HA5@SNqqh~Y=IJ$PbR7`yYUvTn;HI&q>#vX$f_kW0G zE<&xkuvzMFO2-Ty#3r$%-empr9JkQbwEDypF#0*<+mmpNIMNmn2iA#rP}5QI_lryl zgvMRfo}4d~3Tl4oexIiBCGP#%|Kp3}yEAXRkK007Q1^)CJC0~uNj)Vm$6P1o6 LCXxcXh2hlI=f*23Nl@Q2TC{ zf9-RaU2?-G2fhB|pJwBIs+UYHyKgoaNACLY6ziht)L?z#z0I9m8{IJdmK<&QehKfD zzgJ7o1SiC1pRI_!qy$%?9Z_*lloBnscDoVB%#27*h}19FyM5_!M8s6`(x`5BU%+*E z^fRfo#kG^-gPi!_-^pW-)K6KZqQCB&@}2w@6+d|R!RKJv5ej;?uSc{P=l|@Fj4|TJ zgNBQ*FBJZL_j~Q+oyV!sXW1`aC9R4m1er)K-_VdLI7$kM# NZS!}7 zUrHz`tFMpz>pPkD`{B `t6;7=RkY2n_?Ub^tcS6okb F9i26A~HvVwse-S^`i zfc*(zW2geh*% Ek z0=H(uOqtLfMoyQ5HQ{3QxKKhY&V;v99zhAS@Dwh>mj)ryAgWxD$OWY+qT&>oCJo}u zg_>~)HawgO0F%&w$pKI*7o^Z2QcMEb31`KC**ZZ)cmUN2LehX)Q(*dBs2m5Y#f0wK z#MreH=rnPI*`1~jD8hsB0|98$CQb){p3o3AXqS|xL9}TQO8~)O!Zm4#n>hRqJL@{T z^CZ-iDV 6a20k|9mI;a7C&JcP|k+YZ+=27InG2|?6B2V#T%o(t-O?gS2f|v$LrhV7$ zcI-JPiU|#xh= Vhj!UJ?aGmJpdeFJoC#5)L6jJxI uh~e#$=8A<=pj4(T zKdD&pjuXUz2AyeF9Ez2d*_3x`Cw{;|s9X(HiBz8kBv1pfzNxvRG}MXLGU(7U+0vqG zX wTqtncoi8K@9wQ1*5QPVI=p}1GohbtUsE90@ zfF^*NqX?EW&~p^wQ2;f{6e_0(7So`<99?r7w3sKL&4ki8dM1ECF;AoyK$&sjDe=08 zxp03D{2z~4u#C~>LBirqd^j*m4Ok-uVMc+|7$&oi;NBF3KLD9ykW)Y;m4_) EX0xN2z4fRYzY(t5L*T`O;c&9NLr5ziP_S%;UTVaVDocM>CP4|fSwEm zRV<211W;j2!=e&{B&JY}i>)~m?o6S?^Xx8j5lY`oeR%p4OhF3ABzDW=j1C-GYO;@p zsNtA?Dm8(Z>PBlJ7D{M3+`oKnnr`M}2%CehDK)>qL9i*PK&D9mM`9mKNS6sgxF8&u z@TN_e0~ao*4IeL(3gBs{mPj4^D#GRo=yMUC906~RKm`TU%f+ks;b5X_I9)%n6Mp1w zKk0H@^ro~AMIa6+=-z|QprNFAwmjUffSUobI?hJjIO%rON3Mu16Xs7tg;9iW%1B;Z z#<&hi-d~m^eI=Fih-NZiIRFWyz=%Aeu^&j~VkVr7QkO~P%k)U5L$au=D1&@)Nc0~w z#9(vh8=;{_ft2$|y%f-w2}x`hm7x&D0Z0p1{Gtp7&lEC~k#t=KXdJ@XIMhpBNvTqa zQPysL$}(n@6_y7Io6Rd05rR{@;p@2lbf#=F1w#6I?AQsZQ5ng9w6OCuu_zfZkOEcZ z2q1a*6AN&40P5|BQ>B2PPmp_Q(Z5&{|0t4Xpzw+o7{=9@S_l{CLNYXzgy+SZhUlUk z32RWeoYFBz5aDu#6KZj`Uu4ali sc=_ln%7mJVqNu7vthO8)n3OWzhXQ%|k?iQz| z78XITZ|#hpBQzKXyqNH|?-( t;s}UA*HJ)G;JA;}`saL7ews zb|s-HoN#kL6e%I}wM$LcFVY_aQyK35{X4r1vmzQ4PVtip>&7L3l5MpTGk|alD7i~U z&Vv;sQH#vwLiA~;Sg}xVz$z6yA+}B8EkuQ%5+iI!y48jsG6)K1DhcTziu)R;mPC8G z;!!eXw-ZsuGPTm)%tOD3~W%H?ihrrF}e1uK}2#3mVG=-EtQr8s ^2S;~`OQ6&g=tz3yoI+lMJ -H4Wmy7ctC=ucvdLCP5&CcRQ35rE9Q*G(`gZ}kE1 zRG|!>>25E(=-5-ZzMj CIw`;+;uX-DK|E_KXz%jmfROm_&g&_W>L6FmDcE>;;rF zA$urb!EzQ~yy~KjSBIFVSm{$xm3{%IcjH9Di6Tx8nSeU*hvdp?c6r`>2^_=d&rK4m zlTJ81JD+`$KJ+@Cyl52UlH#jDJ81_%2Dv3=+qjURBs pOW=rje!zF~ z3{9*B9Ehghd!0~ya z&k+ApF4441!ZUBa79GHSC71K6-M}a@<81TV##_?1a1DeM?Xg&mKq6<>#p|k!9w@~_ z#>fa5GrU|D2n{D;q`tymw_pAJ`|7_%s5eEZDZg)%E6DNb7bC++2D|9Yg7Emj>Ec`I zMUWKQFrNZm#h+<5xgBp@mQyM5U8c5BMi|K$GyxEf9HUEKwtuztPHIio{-Vp!Sko+t zeu@15c#TO+ASyNZzhZhbC_Tpvw!3&jhGHsCb1|X7)5;|rUhcIRz>G+Yy%>1*jVO)0 z@HEylV(JO53kNyP*;%;|O{d}6TeJUpiG8O>*P0T{=ztOp%sMM-VgT~-9N47f=hP(e zIAhZnr*~_<42J{IG$&l>maDmTqKzM_-?#p_47r;oSiDRyyE!t$Y}ls(k12vFF`@kn zLU 4pGQxjk8vF*xbmu3|38BPJ2Jd(GOAna${>qp@ziiANb z3dup*a-mU9df_JEIFH;fF;=+rc>2~OE2;UyA$U2kq|>$f?0d)TP|K%<77Y&EH@4t+ z0&Q9{zj<(U)0Cj;@nY%OV+}p9?#p)*`p$u#WRp+@n$em9ApfL(Z$;$L<>qf@+HzN) z>{b`ZQ GKRFur3ppadwNMk+}G% zUH)O)U)(1Ru&}__76K`i$x1iK3Z!`=e&aAmDWBc9zNTDWUV!p9tQ|v(Gm#_w=gaiX z^5LV#<;Tpe&siB$uS_z7l6at?WClRTS*Q;2Z8a}*YVC9&u9x!&=Uip;Bu~}E+3F1H zd*+bIZ2%EYRCUVVcP1bA)UQqYvS9p~KSh>FsDzR8FtrFr2*RyG*Awz7mOi^%N}u^$ zQ{Z@lEG#r|3n^|r?`V$H?BpIpOZ?fmuQu)^s}N=P^Ba<(`LY =p6bNs#KxNaX~y zxb#qYV6o!^67P&QWX%R* Zk|iEWnzajm-#NJ-HDD1UgY|&1?OEEvC #>2{hf`bwqW}1+3#_$(E*{# zQ?tnO+hdE zo6VRZ)q5Qwj^frFi92V9j6`&5X3g?oih(ESXuAmepyRdq=>?;h+qu}$P}SL)Gevi+ zeNZ^Zn4#VGDmn@e3Ok9n(6PwfEde~M#D~agYb^ZS{)|0xW7g)7(=nhp#U3h!q(jEJ z8f9YC06R}WL7xRmp~IoO7nuU}X~Tq;m`qh;+pg=yV#Xm;Diabyo-gZ(1SVIJrZMRh z!-LBF+^G_O(osY%yj&IBpGSVkteYuT*y9IE0mCGAOxr{tpjlExlk$XGKB~wPv} +_Qpq&X({TpE;R4X8#WYFCG6Iu?tlB-7zN_v%(j 5qwMeCK#2t z%*0_oKuf^)$>@p9{WPwvT{a!1jfE?m$hvehH&k6O1|)?5s5}`Z*v4Z8#SErEoA#T1 zM)C5BZKAniK5q?6*f6B=5L+ry3Z)IWuTE?0$Tts*DTg4ujcXAaj@WkV?5m*@$FC<` zQ#tJ7s79NY$@1NtbOOY#Pq1UujPhHZ23J9R>5fhZyBN4rW~9*>U|2opD#FqNX|Di- zl~6G0c! G-OHd(CG_jtA z_RNAm+=6LqS__NJb3w+ZmD5N6_)qsU;ni*tsQyg6&H^K;>L5uF*gV*l$eWP=sRYZ~ zd&uj!B~&AuB^1bcwHnF*D xpc`c@;ejV5C&v|o7L(L8gnCsU?7@Esr@Gu0O9 zC3Ii#x2Tn5gQD6`ARt<*G+nvy?)|*YOnBo{Yz=4lj68^R^dHwz_d7Qi`!@B=CrChi zGkjHou761X>TcBf6B2RqOSx6r<$PwFGVerC)^ysz8>>% G^ zKMUOjf($>#omZo&auOxwr=ERA2B?zJ0iJ29NIlH-%KD!B({$$;> 5zwGF-cN$2u^!vFP{kZ0v7VI5xRXR)Sa zC0Ov0q21@&R(}O1y&Nr_xWpfzMoWKCimA$nDZYLfAF!^tcDm$C);V&;-5Sl+BQH_9 zkKUVLNY>LI`Ymz7X`BI+a-_lUo@C+rLR+4aX~f0r((3D6p bSN`zg+Oj~!n7_`clZ>>-awxsFP{A|2 z;r+F3cX1zB!>97{R2OtI&+Px)^Zuf$6xChOl1b^_z}~WwiTF(Z`#a{fr1Hx>L_hk* zg0Qg&?}Z4 DBJ+d>E0>eGoVy8J`j_k0bIO2N`pL7dP z1}l9R6Y7mc7|_JbInw?Bx^Y8sV=WM$?Qv{2dHHNgK(?pyj5A9qJ78IKhq<` Le_dR z0+8+#!6|R7_@_gA5~Y|BDixxH&6fY_9+H?5&<>WfQq(x+vEosAO2>0O{d`WitSRQ` zjpR{cm ^E+Gi`juE@Vu z&QBiwL6i(Je>GR~a!<;fXTEi8YBe$X$~cj>r|4dHIkqo7R57PVJbNxXx9tg`x#FCA zPP%=sYUo>0cXG5TF7<+C?v3&cW^jer8qvnjuT%Ww1rp1}BkE`-Rj|qP(!Ij?vg9*j zY_lKib@#%YvZ6QH)HU&nhIh Z?kwR0+sTnoV>NfH@@*+ z?U!DbV)i9xt5eaNfqCz8>w-_dwemnsI=3aU#xhHbY!a+Pb0ObrMXVshX1Qbj5h_h3 z3drdHMr;23ti971HTu)*U^7!qtk9B06q-mhK1I~@t}E3i3fk7=s`4(8!p&srt|mf! z&z8csW1|Diw`@{eeyD{ECEn{PdJ^o%o+a)jml}?oi%&{FX3GxFZ47N`44-U_TyMnv z3ih?GIWYqh;d$IhDlVa`&sinYE5Qh*5JN0<$8P6`g>Z|aHMgS*_2MzP(MHN*c-KHF z_C=$Ue*F_Cs=vEGLL7Th9A4R6w5Gr)sXUXEO9_iL&l)ceeVa2Dl*TsTCudlvj(eq~ z^qiRyzx+avur}Iy+b| &pqv9rp5hBF4hzPUp(!&S zk be1;%4DDvWPQ?UhYo$?o__rf^7;t zXB$zcKu2DV>F8;fb1a)y%&6%nBp4Lr8&m|LD(=@+ye~7aLTFjnRyfF1FIQde-fn+s zn5y6d`LWPy@w@5%o)hZN2;I$>_KtM!>M4HUO;8$%uF4|JB3jIP_$4R0+GFn#eiB)~ z6i%#%o_1Lz%%1A}IT2QvQ+{`>&9C~>A4E;OU5~9s+oE%uJL5`gck+ady5n~>$P+k| zg7Djbs#9PZjzA3q$?No@>M^Z0!&Vn|L>8^qvE)i2=mSAT85MS&K!1r~9#WGa_pEDt zxMlH*lWj!_BbKZRq;PYI$S=wLi_V;W*778w-;UWKRGxuM4f5{NY`QXXD(m2~+MrR+ zr5}XeAIxma{0w-Cv9+HPMb+n4Vs4kQ#>Q2nU~-5}nXSe(Ka0~wBl0T8iFbbAVr3F= z6SwY5*4I2qW~{b9N$#&+D69E>y=%f^z}oE4LiTmR+Sj&xj^%pAg y+g0}1i3unua!&efo5=IRf=2OmZ`-wd|khb5+YHkgZ z@502&kEoVcUivj)SIs`3RLp3;6}*1W#CIUV>*`_2fKu;M%M1Dk=()LjOJBtilt~TY zo9SGEv78gC4J~I&H)S7QX}2EebMWvzmDJ^?-|Qbexc|$k@4n;gSYp&t#qbw`uQ5bl z%H33G?x54eBm35rw+%}tlke+^y;-}am^!I*Zn7(>2NTiuY-Q5KR=urU^{G&lE)}NB z(B82M>(FwUE0K1i5DFGL@-qi@#kj%=QV#OHddm7 a*x|d zKT0)Z{8*n3pcgzyoKx5a!SP&~HllCZ6Ip8Hr>v$9D^=jEy>;vfv!UB6L?{&->8L>M zIaWE-N|8#QGb;k4x1uIR<24ir2d<_rl;tb81ynC5<>j8fSyQz(1_=y((u;(S#DU^% zN#Wvpx78A~)E<5@KE6*dvFq31zT^(u_O>keNLOWtjZ?X2^Ei8=ux6<)>)uJXl)9ME zhI-Pg|Ncf5E)mC`n}7ZELdcuo_nyziq==>7>*@5)vVKQU Z1eCgUP z#gE{TX3$jKSK;H$r#(LvK9bwwnP$X$1vN9KMDv!9LuhqfZ64OXI61Fw3NrE}`)miX z7<1iocE?`%&n=b<$G6!h@nD+F)D30(iyT3DnpKu76qOG9a2_wF9rW!Uc>ILCT#z-( zlCHK4QDa!EE&nI>IWjmlkbfOamh*?YK&>hMnlm 8zP5|3t$^){}iT1K)!}g~eSu-p>-#EyOLOfTt66QBaT!_lO{$qL6pwgf|n3oO% z+Rp;_5cwN?(*Pa76_Rf6Tqv(gb;X^L&ldLYlk@3=xr2}K3yt9W1&A#Bo1^@9>7!7? z1)D?m^Z;>zqjD~CA@4&s9AjzzhZG37JFt+2&4jF`CE{iRe^c>J!~y=-&oHl`c{&Lz zd2 O2 xif=|FhIUr7Ijl+4@><)>>rkzjO20R_B4o9kEO0F`H$d7B6Y{P*iJa^v4>S zC|5B_E8&UZVCiE?zjZe-!x4k!8Bc${J=DJ6H$rW*b91g3O>kx-acS^8f{1HmeL440 zZ*0%ZAF1Hav-q%wEq}e@RGxKc*r|7h$Sgl}K6G^^&9`xVp}4!HT;{7hba<-zA-2WL z`7ZPY(Ol2eusino&HYPZaiK;CNPdf^Z|O{1{!*I6QPMV7^I>^ujD1&v|Y9 zx3>J#!fpYoZYPr#6wqx|8 |LB^I$cj1!31;9~s8 zAsEVEU@jM0g-jp8=<#U7n7KR*9cDu^L#cdJ8iLFC^EfRy$LwO5V1hM;kcr+3G?3G; zP|DJfww0B1GfsLV>t?zF>4GvmS1PizIK09D2k*KH!%I$?5=Z}8tCg1gqYcj#PDTtt zZWS#1Wa{YG}kN94Q{5cG{ Ji2x4bifCqxykZM10Pn-<3f&JL|G`z z$JtVz-1)chrt(1F&k46^!54dHOVDB`P{R5%w5*nvOkTw+%DwwWle-L52p>-Tww~Qb zi2<`n&Y!*&!qC#P${$WcIvp<;v`3+=4ZQ1Mg8uqw2e-NG71>y)%a&zEd?pPcLh%IB zgyecHsBU=DqY^kVvH8L1NIH0SKf~?V!$I^tPFCN5p|bEU*KeO?CofJUkQ;dkm3kj2 zi_3Co-wjL#Mt2b~fj#kw=Kd*mKNZ@zy2YLNVXa@=^3$3bcUP#jTVhDD_T$qJ@S%%g zA8y!isOw5y2ua(HRtKZ?Yem=JrFY-W(nP2-=bsfQNKxk^`AS01cm6K%rg1L}Z~v*T zKvS-5SwI}C=m#TNzj=~o^xFHAoE&M52hp7vDV>#<^W>GU;uVk(Njxw9D9UWpPAPc# ze%ED<^!`kt4|rxIitMfA2huJ8A1mx(!2J2^ o;mtc-$-R_l zCYF tulsQ)2(s3qs`3Pz`M1OvZw?@tRYi{j-Nj zD=u77ip>H0s@Yw_N!AAzu2>~?q`%yt$;nn;qooJpXL&Byupt!KQBQMedmWf$40Eq6 zsd~vjhN<-!aB=T+6KaC=>w*ZeGqKYn<;;u{P9vZhbNE0a1vFpHJ^7k;)-3C$WnqXS zVN2qX#>__FGPqZ8>=u-WD+6}PG0<6tB=z5nR(u8*j{A)Y{`tlPHk>Ih$PvS%A<`dG zGIq~<4$GpCHNkjaFft)8G fn*Cd7croEfLV7WCUw_LK ~uLvB61koDI3}h$Z7%L;B zW82gw>ZrX(hYbj13kds5tOMd)CgMn^LYZ3q>46o0m=eG;eOGY!=q4Q8W{6z6FXVjO zFl!& LPW(0 zWyUZeZmfoPn%~ayB{l%vBS~3Ohi9hbRXKuV A20n<1N73y+z1ceR z*WO%9Ii#tie)TZns|ak6E#Q;N*=u=Wv0?PUOy;5)P+^;Hgu4el`A-DpdbM<4NcWZf z_7zagW)cS7VEb}H+~M4*7tLY)%|*x|h|%ifUfNX&xeeg1L=!0B%yr+z-Eh9vEQsEF z9wPXLlTVN%B#Syi*_JvW2_T?Wb%w5$t}>>d-n2R;o>`K;MnC!Wkc? Seln2D0lT79l=DvD+ocZe~ g9T4)^}bh*BmnIXqC^tD-?ZZeRq6*dbPM9$~eCOTHe zO6?_#u3t)d)FUUzII!U7WoFZPH@%S~dyzsH5W%EZt(KNasH(g@cMwes3PrFy5~dDm zmkh!d&4OOv54`*H0C2Ln`FtfRr>@|2ROCLtT#Yt6jnDPi@+0#nZxzdyskwbz%*eR- zJ8n6j9`}6J!A(q%HEpXGHw(AsG!cJtcjllVBx3~+^DItmtVkPj(g0I|AMz>Zd`O+V z9{$mY9=>mt88U`Px}~{Ez7pKTmV*f!8rcZ%Q8W QNjFME@)`}b%Kf6p|fDhh6utouqrjJ;Hos@w_g4ugG=at(VU|^e&O-% za_ua~kCtP{ZSRtd)2DYd1dk<1>56QlEd8XqV@W4p76*p2 @*RAUbn%Ei~}&T1g5za zF#(L@AySOaMkpvwgX{}I3v*0`%phnaOOyhxPfCaJSnp*4NSoN@G+@CS5QqWDT)@Z| z2(2yGC G%|*{9CK@grQ}_Dz_gw@RMd;5q7U}#f4S9b zlu{v~q)OoAl6sj?>OJ|KzNyNwys3)1r^S9(bJ4wQ_$~c0qtRBXB#8uqbAZdHB~qU? z9;-qaXF{xjpI*g|PireAg=hUqXXmsZIUNw-Fv*Ydt$5 nOJjR|&Ni z*AKv?H?!}@7+OkYGw<574kTMGPfYH(Y&NYsAI{53T^&J_tjHlK9WOi>$J#VJk7I*G z##BhHy%4_%*|CH-^tT(WCyI|xw)x^+Y;0%fQ}`Hr^ Ydo(K?yl!^iJv&Z@*H7*2lKL9`5_K1D@8$eCf@6IutepAbUq_ zM|N(3MoE_Za&h;>P&1OP9q4pORn-aKz#9+~YO5Nq%I(i+6_Ig-<=EBQuxH;D?pz$S zooM#N3%5y(2!fc38o-Z5lxI!0%ht97UyR0->)E}NLlVtXU}cpk1BB?PYNpTbZ#f|1 z>9i}U)hBdBq8ZsB%kGw_LLCI3WU#KtIC6ejNiN%NvgMfQE4fsR+CgluE%=pheU W@9f}8d&L=s{6AInDI1T}iHaH(E%_;d z!$lsq-F)4yUifG;7z@aARXc64O5~d1oWd~rc&{^L_Xd+hN~^z$oNSk(?VW64JJ`46 zUTR$kQ?~8E%>tE}zUC^-IXfVy&`|I(yuGl02!lgE9-f=)9k7$WTE0uo1LzZ^rJ>cN zYlbSTd$lDYdu_K9wVDGuwke*!u#Z2MGAC43Ytc`B>KDfR1!SKY{^HR7R6H5pTV<+Q z_-CWa?H~(M?94h2w#>*~ik&xYk<{&2{DG7!k=BM@So-x&wohj9A%8`p>cvvww<7s@ zN$dXp<|dWe=Z3XgfIKyW$_6Z+nT165o5{0SHMq#zL*cidey?XwzF!Edm6A; 9@{x%`Hu5qi@i5<2VAj@$xB03K3`{?x85D n6}Fj?>&&p?lC%xKLJ+mHBA2P!rro)AK5lr8;iebZ0OQVwHk%>4YRwZ z=z#?bhm LBrh2yjea3j~wKV;LzO`ft!6Q~XnzLOjrOp1Ow z4?9Fn%lWp8bC*xVF_qYsBYY{=e)*X`WyulH(D{N?^0~r2d<%)}F3EajY@LnsWhcz@ zbJe>{s`oWZI`5G;Klm!|(IeEkVyAO26Wo@pR$tNM@q6l9yF>f0*u0Vvel&7ZuD8;b zyN#(|GMwHc*=%>TMQL)2SNQD(4@$JWyV+`Vkk>Nf1rAnyow0fG_t46@Dki+<_`&7p z_c~r48%Bu9NqOOW`dzM1LH24u8y}llYI$gFy%JONmklyx9qwpoUQpCokk?re##IUD zyy$9vHgWKksGkr2AVbaor_(Nle2M*Xj5l4jBD6IBlLU6e+U_E(jKLp^j$X!xvN=hG zTZvOTc0MJ?n|9X}a^)$`r`Vkr>a`TE%IIRhEWVsD;c4(+GOW~J-Km-(ZA!SwKl_*I zXaCaI@<{)a={NSDi*{G~U4k7!_AT2M+r-=hX%$c-YKDR}7<}wygSM8iZnf;-Dh}x( z?=GQm8f!0zb$)^Ux`_RB0mBes*f=;FITX&F>k#(z-JW68=e)U+gxA{TQs+CTtKfls zhySMZ!l(ml?C@$py6D&9YsG_Jzj}RCMt!@RiQCv3sm8(zf|=Dz#&7FaNM$)UwWEjr zy*+rn>c-z-`|n;>+b?97CsjpUdTbZ_@3W{>s1X2DQ38XzaI#nJ9LfqE1`E5%f# L+g$BGcz6p4YHeoovtJ4ftsKl`SP8%H!Ap$unP@)z5m{zfWOh#8hTSpYTHJ_< zj`Fx55?Z9*p WO5tjpa+aRu17 z7v>5r!@7=ycSnWyoDT0T_|UsDZ?*bnc*ONiaro_*;e($)^nYENsPmJ3&(2H7>*l%q z9=A{#hpb9Nq_VXpXG5ooFfJNm_2q?W2Yj?-J>Fc6=toWy==ZC2*)uy}!}zMUdw@)a zhxUnn`r7*T&zIN8YuECsVa+(07v6tuvU)JL6^ZpjRFQFSWZc(JeOpA&I(OZBzI>ts z;yr7#e);Luk1=!09YgQ`y<1;d``Ac+GreazlAoDh8r9*RYL?dMCFrG9Nhl0`Q3XML z+R}A&e9+M%86i|#{f}C>f4Y!JWfQQsh)z!PQK8UZco!MYQ~^fTTx)8S`w-Dgq=Dm} zcDalqQL5&A Km @{zm%#8mE8t+#vMkP8I~B&SN&Ss$@qFDyof*JTJrn60B)Al{;T< zS51n1#xyq*@rCR^!b@Mizx_FS`B#+O )?bZ`QYBYa^@ab zqdhJHSMmzCn=Wfh8mr6S{Ls3uHgfl!s?#6GpyV118!Li5%$6)5VmYlpqmj)YdL`KZ zj!0g|UF?mUhYk))9`(gq+w1=q3on0s-7Ns?aDtFn$kJY_BP4VWyf1&Oa@qIzh59|_ z=UR#P>fdN%`q`1s)#8`BmYyCvd<(T%JsNs^zm~D+|0p{9xEA;Sk6+id?b`iXTdj4! zb$@T&s3crlrFEwy31O=wNmfES;o4faiXlnIVI`d;SvQiK<6Nr{!Vp57r8uGEBzK+j zb@bcspFJM?V}I;=T-Wvad|t2D`}t!1@t36|2{*?{zPs_5{iZsb`@Pv4qN2_AXZ?X% zVPNs!*Fyj2674)w`ge}~Wx16awG@NJrTN|CzjFjWW*U%C-vCE+*{KwsE(%Za&clB| zhXVeoCKgqP|6|=e$el%wWbMgU`~fUYlRr pDAxaD`^5B+75u8amnTn^lLSGGFnB$0Ai_pndx@>%WrQrHpHC| zIaHjl$(nlW)!{X1G>|cKYvB?%C`vK=Q@0YVdb5J&FmpfSV1K3r`huR{^NEXrUn=D@ z9>yU@026g#)sy_2e}5mCExc#6OJ}?5{+wM87VUZ%yK89Ou19A7aR