From 694ae332d06f4cea682df49ec33d9ef1d1c52758 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 19 Mar 2021 16:36:57 +0100 Subject: [PATCH 01/10] Add first draft of the Attributing DNS Requests blog post --- ...-23-attributing-dns-requests-on-windows.md | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 _posts/2021-03-23-attributing-dns-requests-on-windows.md diff --git a/_posts/2021-03-23-attributing-dns-requests-on-windows.md b/_posts/2021-03-23-attributing-dns-requests-on-windows.md new file mode 100644 index 0000000..f830dd9 --- /dev/null +++ b/_posts/2021-03-23-attributing-dns-requests-on-windows.md @@ -0,0 +1,84 @@ +--- +title: "Attributing DNS Requests on Windows" +date: 2021-03-23 +author: daniel +custom_thumbnail_name: +category: "Dev Log" +--- + +For an application firewall it is very interesting to know which processes query which domains. +This sounds like an easy thing to achieve, but in practice in turned out to be a rather complicated problem. + +When we first looked into how to find this vital piece of information on Windows 10, we found that for some reason, all dns requests are sent from the "DNS-Client" Windows service. +There were no dns requests _to_ that service on the wire, just from it. +Upon further investigation we found that Windows applications use the `dnsapi.dll` for taking care of DNS requests. +These requests are not sent using common DNS packets on the wire, but use a RPC call via an internal IPC mechanism. + +This means that we could not attribute DNS requests to processes out of the box. + +### The Quick and Dirty Solution + +While researching this issue we found that disabling the DNS-Client seemed to be a rather much requested action and quite common for Windows users. +Most often, Windows users asked for this in order to work around bugs or to improve some aspect of their network performance. + +So we decided to take the easy route and just disable the DNS-Client upon installation, because it's only a caching stub resolver with no other functionality, right? Right? + +### The Bummer + +No. + +Apparently, the DNS-Client is much more than "just" and caching stub resolver. +Maybe it should have been a stronger hint to us that Microsoft removed the ability to stop it directly - we had to change a value in the registry and reboot in order to get rid of it. + +The first reports we got, that made us aware that there is much more to this service, were about VPN clients not working correctly. +Some of these clients wanted to change the configured DNS server in Windows (which is a good thing - it prevent DNS leaking), but as it turned out, the responsible Windows service for handling these changes is ... the DNS-Client! +With every report of another broken application that we could attribute to the disabled DNS-Client service, we started to realize that we needed a better solution. + +All research regarding to finding another way to see the DNS requests without disabling the DNS-Client turned up no viable options - we dismissed the crazy ones: +- Hijacking the `dnsapi.dll` to force the `DNS_QUERY_WIRE_ONLY` flag - we are not malware. +- Directly replacing the DNS-Client service - replicating Windows behavior is a nightmare. + +### Biting the bullet + +With no options available to directly get the needed information, we were left with only one option: Working around the problem on our side. + +Until now, we were able to directly attribute a DNS request to a process due to our "quick and dirty" solution. +No longer being able to do that, does mean that we loose some information, and that we will have a slightly less tight grip on the system. +We will need to find a good balance between control and configurability. +The easiest way to keep control is to make previous app-specific settings global only, because then we just don't need to know the origin of a DNS request anymore to apply settings, but we're not ready to give up configurability so easily. + +Previously, we made decisions directly when the DNS request arrived at the Portmaster, at which point we had all the necessary information to evaluate a DNS request. + +Instead, we now return a valid answer to most DNS requests coming from the DNS-Client - bypass protection being one of the big exceptions here. Just as before, we remember that a process requested a certain domain in order to match it to a connection later. In order to correctly attribute requests that go through the DNS-Client, we now put these remembered requests into a global scope, which all processes can use to match their connections to a DNS request. In addition to that, we now attach various information about the request itself, and DNS server used for it, to that remembered request. + +Now, when an app uses the DNS-Client for resolving a domain, it receives a valid answer and the Portmaster can then attribute the domain and other information to a follow-up network connection. The decision making that previously happened directly when the DNS request was handled can now happen when the network connection is initiated instead. + +### Positive Side Effects + +Not only Windows has an internal DNS server to take care of DNS requets. Linux distributions are starting to active the DBus interface of systemd-resolved, which in turn also hides DNS requests from us. The workaround presented in this post also successfully works around this. + +Similar system are known to exist and are expected in other operating systems as well, so this change will better brace us for the next systems the Portmaster will be expanded to. + +In addition to that we also now have more information available for network connections, which will make future features, such as the connection history, even more powerful. + +### Negative Side Effects + +Because remembered DNS requests that go through the DNS-Client are now pooled together, this can lead to a wrong attribution of a domain to a connection. + +For example, if two processes use two different domains but both of them point to the same IP address, it could happen that the Portmaster thinks that the first process is connecting to the domain of the second process, _if_ requests are done in parallel, or connections are re-established without querying for the domain again. + +This also happened before, when a single process sent its DNS requests directly to the Portmaster, but the impact of wrongly attributing a domain in this case was not so high. + +As a remediation to this, we will start looking at HTTP headers and TLS handshakes in the future. With information gathered directly from the connection, the attribution will be more accuracte. +But this will not solve all our problems: +- Applications can fake exposed domain information with a method called "Domain Fronting". +- TLS 1.3 introduces Encrypted Client Hello messages, which will (partly) hide this information again. + +### Changes to the Portmaster + +Here is a full list of changes that this workaround brings: +- Domains may be wrongly attributed to connections a bit more often than before. +- The Portmaster will active the DNS-Client Windows Service, which it previously disabled during installation. +- The DNS-Client in Windows and Linux' systemd-resolved are now categorized as a special "System DNS Client" app in the Portmaster. +- If you want to disable bypass prevention for an app, you might need to also disable bypass prevention in the "System DNS Client" App in the Portmaster. +- The Portmaster still works as before with a disabled DNS-Client. Whoever prefers it the way it was, can just disable the DNS-Client manually. From 07e4fffaf9b159d39bf8c5d734c902b026604f03 Mon Sep 17 00:00:00 2001 From: davegson <3080765+davegson@users.noreply.github.com> Date: Fri, 19 Mar 2021 18:45:08 +0100 Subject: [PATCH 02/10] Fix typos --- ...-23-attributing-dns-requests-on-windows.md | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/_posts/2021-03-23-attributing-dns-requests-on-windows.md b/_posts/2021-03-23-attributing-dns-requests-on-windows.md index f830dd9..20b5957 100644 --- a/_posts/2021-03-23-attributing-dns-requests-on-windows.md +++ b/_posts/2021-03-23-attributing-dns-requests-on-windows.md @@ -6,11 +6,11 @@ custom_thumbnail_name: category: "Dev Log" --- -For an application firewall it is very interesting to know which processes query which domains. -This sounds like an easy thing to achieve, but in practice in turned out to be a rather complicated problem. +For an application firewall it is crucial to know which processes query which domains. +This sounds like an easy thing to achieve, but in practice it turned out to be a rather complicated problem. -When we first looked into how to find this vital piece of information on Windows 10, we found that for some reason, all dns requests are sent from the "DNS-Client" Windows service. -There were no dns requests _to_ that service on the wire, just from it. +When we first looked into how to find this vital piece of information on Windows 10, we found that for some reason, all DNS requests are sent from the "DNS-Client" Windows service. +There were no DNS requests _to_ that service on the wire, just _from_ it. Upon further investigation we found that Windows applications use the `dnsapi.dll` for taking care of DNS requests. These requests are not sent using common DNS packets on the wire, but use a RPC call via an internal IPC mechanism. @@ -21,17 +21,17 @@ This means that we could not attribute DNS requests to processes out of the box. While researching this issue we found that disabling the DNS-Client seemed to be a rather much requested action and quite common for Windows users. Most often, Windows users asked for this in order to work around bugs or to improve some aspect of their network performance. -So we decided to take the easy route and just disable the DNS-Client upon installation, because it's only a caching stub resolver with no other functionality, right? Right? ### The Bummer +So we decided to take the easy route and just disable the DNS-Client upon installation, because it is only a caching stub resolver with no other functionality, right? Right? No. -Apparently, the DNS-Client is much more than "just" and caching stub resolver. -Maybe it should have been a stronger hint to us that Microsoft removed the ability to stop it directly - we had to change a value in the registry and reboot in order to get rid of it. +Apparently, the DNS-Client is much more than "just" a caching stub resolver. +Maybe it should have been a stronger hint to us that Microsoft removed the ability to stop it directly - we had to change a value in the registry and reboot the system in order to get rid of it. -The first reports we got, that made us aware that there is much more to this service, were about VPN clients not working correctly. -Some of these clients wanted to change the configured DNS server in Windows (which is a good thing - it prevent DNS leaking), but as it turned out, the responsible Windows service for handling these changes is ... the DNS-Client! +The first reports we received that made us aware that there is much more to this service, were those of VPN clients not working correctly. +Some of these clients wanted to change the configured DNS server in Windows (which is a good thing - it prevents DNS leaking), but as it turned out, the responsible Windows service for handling these changes is ... the DNS-Client! With every report of another broken application that we could attribute to the disabled DNS-Client service, we started to realize that we needed a better solution. All research regarding to finding another way to see the DNS requests without disabling the DNS-Client turned up no viable options - we dismissed the crazy ones: @@ -43,8 +43,8 @@ All research regarding to finding another way to see the DNS requests without di With no options available to directly get the needed information, we were left with only one option: Working around the problem on our side. Until now, we were able to directly attribute a DNS request to a process due to our "quick and dirty" solution. -No longer being able to do that, does mean that we loose some information, and that we will have a slightly less tight grip on the system. -We will need to find a good balance between control and configurability. +No longer being able to do that means that we loose some information, and that we will have a slightly less tight grip on the system. +We will need to find a good balance between control and configurability The easiest way to keep control is to make previous app-specific settings global only, because then we just don't need to know the origin of a DNS request anymore to apply settings, but we're not ready to give up configurability so easily. Previously, we made decisions directly when the DNS request arrived at the Portmaster, at which point we had all the necessary information to evaluate a DNS request. @@ -55,7 +55,7 @@ Now, when an app uses the DNS-Client for resolving a domain, it receives a valid ### Positive Side Effects -Not only Windows has an internal DNS server to take care of DNS requets. Linux distributions are starting to active the DBus interface of systemd-resolved, which in turn also hides DNS requests from us. The workaround presented in this post also successfully works around this. +Not only Windows has an internal DNS server to take care of DNS requests. Linux distributions are starting to active the DBus interface of systemd-resolved, which in turn also hides DNS requests from us. The workaround presented in this post also successfully works around this. Similar system are known to exist and are expected in other operating systems as well, so this change will better brace us for the next systems the Portmaster will be expanded to. @@ -69,16 +69,16 @@ For example, if two processes use two different domains but both of them point t This also happened before, when a single process sent its DNS requests directly to the Portmaster, but the impact of wrongly attributing a domain in this case was not so high. -As a remediation to this, we will start looking at HTTP headers and TLS handshakes in the future. With information gathered directly from the connection, the attribution will be more accuracte. +As a remediation to this, we will start looking at HTTP headers and TLS handshakes in the future. With information gathered directly from the connection, the attribution will be more accurate. But this will not solve all our problems: - Applications can fake exposed domain information with a method called "Domain Fronting". -- TLS 1.3 introduces Encrypted Client Hello messages, which will (partly) hide this information again. +- TLS 1.3 introduces Encrypted Client Hello messages, which will (partially) hide this information again. ### Changes to the Portmaster Here is a full list of changes that this workaround brings: - Domains may be wrongly attributed to connections a bit more often than before. -- The Portmaster will active the DNS-Client Windows Service, which it previously disabled during installation. +- The Portmaster will activate the DNS-Client Windows Service, which it previously disabled during installation. - The DNS-Client in Windows and Linux' systemd-resolved are now categorized as a special "System DNS Client" app in the Portmaster. - If you want to disable bypass prevention for an app, you might need to also disable bypass prevention in the "System DNS Client" App in the Portmaster. - The Portmaster still works as before with a disabled DNS-Client. Whoever prefers it the way it was, can just disable the DNS-Client manually. From dcba1ee77eb41566beae701b22e71068b51af8ad Mon Sep 17 00:00:00 2001 From: davegson <3080765+davegson@users.noreply.github.com> Date: Fri, 19 Mar 2021 18:45:21 +0100 Subject: [PATCH 03/10] Improve a header title --- _posts/2021-03-23-attributing-dns-requests-on-windows.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/_posts/2021-03-23-attributing-dns-requests-on-windows.md b/_posts/2021-03-23-attributing-dns-requests-on-windows.md index 20b5957..befe125 100644 --- a/_posts/2021-03-23-attributing-dns-requests-on-windows.md +++ b/_posts/2021-03-23-attributing-dns-requests-on-windows.md @@ -16,13 +16,11 @@ These requests are not sent using common DNS packets on the wire, but use a RPC This means that we could not attribute DNS requests to processes out of the box. -### The Quick and Dirty Solution +### Disabling the DNS Client Turned Out to Be the Quick But Dirty Solution While researching this issue we found that disabling the DNS-Client seemed to be a rather much requested action and quite common for Windows users. Most often, Windows users asked for this in order to work around bugs or to improve some aspect of their network performance. - -### The Bummer So we decided to take the easy route and just disable the DNS-Client upon installation, because it is only a caching stub resolver with no other functionality, right? Right? No. From d2953263e9d0b7c4fb9ffc58c99189e0da7dffcf Mon Sep 17 00:00:00 2001 From: davegson <3080765+davegson@users.noreply.github.com> Date: Mon, 22 Mar 2021 15:07:33 +0100 Subject: [PATCH 04/10] Add devlog default image --- ...03-23-attributing-dns-requests-on-windows.md | 2 +- assets/img/thumbnails/blog/devlog.png | Bin 0 -> 90172 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 assets/img/thumbnails/blog/devlog.png diff --git a/_posts/2021-03-23-attributing-dns-requests-on-windows.md b/_posts/2021-03-23-attributing-dns-requests-on-windows.md index befe125..cbd060a 100644 --- a/_posts/2021-03-23-attributing-dns-requests-on-windows.md +++ b/_posts/2021-03-23-attributing-dns-requests-on-windows.md @@ -2,7 +2,7 @@ title: "Attributing DNS Requests on Windows" date: 2021-03-23 author: daniel -custom_thumbnail_name: +custom_thumbnail_name: devlog category: "Dev Log" --- diff --git a/assets/img/thumbnails/blog/devlog.png b/assets/img/thumbnails/blog/devlog.png new file mode 100644 index 0000000000000000000000000000000000000000..d66025badcbae5ddb2363fee27dbf9dafc23742b GIT binary patch literal 90172 zcmdRU2Rzk(+wd_nGeSmX%Q~DrWIJTfV;v*M8RoHfk%n0sHX&rMl96O2E0mO#tdN8d zLXvt<|8?KbefNLr^FGh#dEVD2`knK=uIqcv?{$5z>lbHge3G3-kOcq$u2#Sywfq=khMG#663*fE4ny3m>48i*-f)zmDMfwepNcaoRC(zIH zx6O$JMUp3pLh=gmr^15&f~9K7$mlQdACjd|{(|-o&<>(<^oMLeg!adV`j8aON&en} zegu+s5OqiKKN<56Fem*(HNSvP1^)}#$JIN)+uzmuZTEAIUMA`^XaP#_3TIM^Se_)X?_yCfM*mt`F!5|u>AOwO1LzSq00!7Px_m)3_y@_t*(4T@52})#dKMJ0zXEzGo zg{0`?RYwk^aQTcoPD@`@nbn-@}3EO`y{FOL;BS6XQ$$Z&3jszW5I~3m z_v{ORTY*ZlvXV1g^&%Y{Tetrf-o?6lyAyBHlp#OI6eLp4s*DUo@i4b@=ln6!=fJ6d`n%Y5lBG4HDfm2gE5{g74-~?yX zzem&Gl_0-#?m?(^NC($oKhnH0a@B7QH16#unO z`u#KJ_XMKzJth5Coh$vQBKlQ7q?YSS)PnLSB_ z5ct0GGi>Tb$Bjr5!Hf7%3miNlR78Y&(e=T5h5ilAzlZ`vWkB%$A75m?<+s! zUmOCV>c;2q6hmG9DG91-DS=*Y0ihz)tCou&$=_c@#L|a)uOZ*hC1} zudw?!ME?t%{{QYBB07F^#euxnC=e% ze@6R%Ut<_;tG{u8?<+s!-_Ydb-(Y`V`HuZtb^3b&rudKa_a92Me|-ICk5Pl#{rukQ z`%wX>3PK|=S|9{O6NW)T5OB1nCLD!=!!C8)`BY&j5Lg2V)?_3s!M5DEcDfV3c5V2qX)0)y7lKx;#&{XdMBHkevi|2xKy+rMDAGmJn4 zfq-Zv2@gb4KLDKx2`PXTosTWox3Ic>ujR2(f@JK*Bj0^^%p(GL> zO88ES_{)5ephN^7jRqp{)V?2?2y>>AL6CrOJd8+{l1L;F(7#TLNFb9)WGY`!Y99vy zg96cHJXK^60tF&EBatA2^RLo^QZF*jcmjed8IlMjgJ2*a9!*smn%X0R!VzF+G8p=+ zv|wNo2m&Kg`%5S&9!Pzpl0l-OKm?MEr?xxEBpCV!9{giF{>mNeSNTGcP*eqzNkAyI zhXN!KsC?le)F(W(sSHJepm1kr$S>0(gCQUo)hCc>Fdj&a2QG>JrwAuey_-xO z&OqQ~Bm_!CqKWul)faWN1ECrW3Z$A7@_ky02ciiGB=t&5EylU1*i7;(O?3Y00$w6WcUwa=+8kDgc{0dsv>~YV53euNC;{-0Yp8! zP-Hw9MMlE#5W)|n`V$)pp`Q2z(sx5s$6ZvrL#h5qh5)Im03k_aXKI7@2Xg$0{VS8A zf7imF*l0A0grXV{2q8kLqc$+rwkQG=1$3r*9vP3M4sP&-zsJTyP!Kd4j|4hX#RMXp zsV5=|j;3~~sk1gPbtHnKM$~_T4Ml?>P%w2Ugs1KegHv^mhe4obzL0b&iY=JlxLbU1>BUhYqESfwgEw;kr!c8oR&H0Mj8((e!kg<2zGp z@56&EE9?B`#l2`o^`P9a;627XUa! zA4v7(rj=~1tN`Am4kg?_TJVAgr>dC3 ztr0K`wej1kr?V|9`*P@H#F4jY~ zT|3)jAK}*JHW$U~#LfLD@Q!%rx zGFcWe%t3K6!WihOzwQvh+)PZGN3$?3^bE9=)uf!82~)<>tMc^OZPZyA4~mbhaYZt> znPpFE71sK0c=TN!9lnvkr@^-~z0=-GShhr1TJ*WLvt@v`Mkx#_DA7KfK_4V+j%3bY z#uqCQTZftwUo@&2RePRLHd2B^Jgw>*3kV+kw1IPQU>AXu4{U(HrS8rfM`f{GQIQw| zO8895Nh(-!(&#>v2+kfnE8zy?@d}zcVJao6L1RY$P>Yu-(t+$I=g;iG*kw!GKT75${mX`U?V`Lsn=tqj;-f3Pdl+z0|^(;IukQ>Hy7*XuJAYIOV zrCIWYt{v@TBU(v@=H~3%3;s;A&2%3=+;QwKqrsNS$}7xe>3jR_bDM*k76t|J12#TlNwT>E-7)(!A08SOaK3AwYd28~kK4x? z50h8Jx_nrealL%EhhHdDx<0leaJzeFb61%bbyIO+^TAF!`Q(J1 z!Cv@@k5|k5lpQt6woN z_)vl!aVMOPJI>qAP--Jl6Kq9`gH$=@J{?>Su01_z0bFH z?G!$6xHy-{UTp}xb<2Womg#w8PE;(G-T12mGyFuyi@4Q5M8BH*1LG_>k}ldw(1RwL zrIL}|>mbwJk11ZeiI5!Q_JT-Rg;BTd{7Bi-L|U=7fCL8l!hZfpHZ94HMIJ77*>@F| z>@{Vy^_0&J<2x%}Y9HBa%(ZNbOSqkK2TU0g4d!^BM9&r&*0?==Xq|X%$tpkbx`_$n zbGL&mm#xE3pJo-+FBNpZsitx^EX*al;yA>SYU=-kr2QfAdDmp^_ED@iE=JCw-Sr zdP!EOy-!Zu{5IYSn(q?T#q0634O_E@LfIA zoKL|rLC`QJyWH9BL}vdh0LnSvk(+g$*ZB zWo)vHTbe0IMtb>aeo5I^iN^Axm+Ua(*mTYcx0jr;6@J$;oR~%KxL@9Q{N`=_TH;I< zv0Un^6wj?fU?T+?w=}Or=M+tw%G{AOs&jr(snO7sEn8G;E_8zhB(L7Fi88*vpcfo1 zf*0(rT2lx0oD|z@D|x+iUYGlEOnXkOaq-Se4DG9W>+54ifLJySg79Hy-rW+c&!YG_ zdYsedmSEMW1?=lu_l|UbQv;yq#M#DASkNJ^GqI{%Otc;wyT_)lSK^#tj6ZT_uml@|X$tgxK2XDB~J|O~x1b%j#qBP6m~N_UBoz#O7fKWs?GS z{Z9aTrqa|maJ@X7(sFEYfTN=cy|S7b+kQlVi(HG_&6YD#=Jv&<&UNocEi7rV33X-; zI;5P;L>;uK;F>Z|_~@0vhFU;1QzU2ebk_&PQ>qspqj&cA3|@$khBg{Zr8F2B3+~?x z+}S#K>voUTbLR_hBSg*#t>YZ+FRk(=4m{nzyu3DKIoX&}vT+MOad6~>Sqj^oz`cQ( z=7!A-gs1uA#0RFI^Mv!Fd!24a>Vzw@;&kN8533dE$({$;6ejajPdvM{JX2I>(H;*2bEqsf};ZmBjj6p=Ds zUuukE;Vflw(|`A3{Mf`jGV2oU;_jKy5Y(BkA7wO~LRB65{m?fBiy}rpp)uYjB92j^PWY%|7%s)UPK&igTOes=maO9+QlwJb2!lq*g8^p_DYGcWf-S zcZIH$a_QZdX7x7_W|Eg~_nK=7%$MoaWez`}$O0YPZwtw5IkfUVH;K{@Kw9b3% zI)H~7-%{+$P<*UkaYmHYXP5Z)%XU+))=sWm^mV(L>Nn(-tSdvg)s$vt%{WY_RW^Gh zGny?USHD9wgv;$d9K$l5u9JmKwS(Of7D%{T7Tp*pN6{|C4Wxc-RKAtrSNLuH0E6@{ z5aXM3G|@DYxx+IIq0zw_${q**^<_0wCq^pV`}JuA6}y{B6Y#Da#t^%O~{&L|r>AP?x`BJO7=(BE->St(iw z+t+&)vi>Y00GLbe1j*Ug&>j~qz4PLguzI2$#U|WRYl6M&S=R&3qoHao@7_)~hT5J= z%Lxa;Ws9uu?Hul_{!(iWUo_y(O}^3~?KCl1&YCx9^HzF6$6+*kXjld3=p@Z1;87{& zD)KfNqN5+FZkfv_WwkK58^S14PUHIS1S2$~3&s$Do$1P|F>`VCZme#0SSM48WVFcy zAn;J+?)xu14IbnD-0DQ9l`7Jz61x~6>71CZbfF3UV}8tjzqy3BMR8d+q` zc@B6l+H)AyIDB#0tdvl3jUUkN-18P~f0BbC85@UUftY=KS#b#)nH-Jh7?}6NG0MX8 zh%*==3`V4ezPFa1J1ro9*D{f3!zG_rPQR+5|3mqn9y0sXC2y`rd*WFskDFh3%awn{ zlB^_fLx7o)^*c?4XR-4u(DG5{gu4AI(IO?rPr;gUm9YVHnKm{P>ZCwgmm=bo7o3Tst-`vbz=J2?G zq9SnDaHzh>jeSY)1xMfTji5PX6hpEh**Qc(02#4nxusa3p~9(=zXnHHzXMBMERgiR+o~Q^hcK~A`fR3eTZnu zIeC1{S6sH|!K z#PE9-Rb|z0y9M4Xx=L4#Fos$E&S1d}Zhd9`UYFHkh9m?^9EuD;)uki8!UbF4t)AGOfh1OZs z)GhO@103XnA95Hk+Z#H@;FPxT&QYy=yZbz^X0Kifr+L=}*8#x!heii|!G>5E%@9rs z&(ySYCpC7AlV|F5Pt9#l>@BR1haCbl5x*4D%>DRIl)Aa<{0n%Q9dj<`x}<1n0;>$C zrYZY5Y1gh3S)@eiw{h*KN8v!OQcY~e;yQlexG0TWF@ujj;Bpi_+%v9c`(vyMnBjn5 zgMHC{p0_K1P{QUaB**$wZopx^7?!**cJe;it981T+Yd2UtSp_+zZ+ef<}bMZ)qvEf z-%pcSM6r|8IA2hDlk6xg zI=J3CW3p9&(LsJE>2u769ryVdw7v6akGKTl40Q9SLyl^^i%~GH?;kDS(PymjPqMG9 z2GE)hV6c{wAu2h>YYTlLITJ8Co*|EiAXwWn>PnrQO6cP_CPR=fj}48bmGjH?ucD;O zWFw)ZiA(7U^UCZCyZ3x6fb+aY%~|yp(?ZD6IH-RaeQ&QKK8?f#7zggk+!L@ zFtw00-q2$yYz^|Njz0QDl2*Le)X}k4dP>eOsqP@k81f{D%OF zwAhAf*W30Cl^(G{)*1s@o~_RXu-}Xtycm@8GmPT>x28BMRwu*w=*%*vhDyp9SXbh= z8yzasEI9k*aQl~5T%sNct_CLrbKiPa#-><1Oq5*3!m zkvulsv|h3!4d0lSXiB7O;k3KOx}>s+e7pHV0JD|CQHIxN0E>Z5AYGcZ&O6sdlCNpz zOPtFNIh)dQPk!>90(cs8{s~?)R{9o2kib?g$|cZUo_t?I7MN&y+Wv5DB&AH+l36#C z3lo&#Vh!R3Gpu0<^e45qlul`MAJ5#6Iue0<;eDFx+kJOr8*Yhyt(tNS)4nYqmU!lmnL4FxNJPEJ4`xLfLZO*?0XU= zYiAx`-u|rii`{(ZMET|3rX5DqM9F>F35wmJr1>@Y>AkSYF^;N0No22i-~Q5dUQZ3N zDl%_NeU9|tX)Il}C4+(OVvkTz!wD;_T=8W~=FWxG9DNlo>^mJUg0P|b6FHeE!-#-3 z(J^tL_96e#x_D5+6}C z%iQJZZdgXU#K7R9ta03(agJvuH`#0-29Zsi9z*JEZSV1ZvocrTt$x2P|2hqTn{7x2 z#uWM38GG>-bj)Wez8LWldfxE-Kng=?&KT~A(AOrygRigiEp67s0ksO%FH9T1U_Zke0=9e^ECWjOUJDaEnY=8$ModFxY@2K(QHNj3GoDiqpS~cCTDx$ViARj);$(|; z!X+n3_7Bd_QB|`U?QFQYBdk7B}{-kKdYM1qQhFKx^XpdTWcw;ek$}OU}4joyG?NQ zz+ATOwM^5x!{Uy4!BhJ09y`P8NG9_c(RzM&3@ZA_wf$q&+zhm9L0k=wIhfdE# zj~5;1XNWERgsHz(#=>wx$&1lFn0TWpMTnB2lhk_mN~@Q?T-Yu3@`elvGxDn8$9Ho5 z&&`Hk4_|ma+}tdDfquC5oL2vyl+=lU2ew^vi_SPzw$tV`m#ZaY+30znb8ddf3v0H2 z^nO+~8QFe+H@#7-|-S(7bm;f(OIxKkzwIe6*|SkyxC?>jNK6BRv(wR?m(1>rewH}>@2wsktQA;~x9NZv05H|8LX0%sXq48kdskxY_O3%sOYvkxg z@6&T8+P4e2_C+Zq8iGj zMw)_?XfCs~z;jsZ^dfbZjLAU1=b64AjB8(UI1Ss1MYgfqmdKt@Yv2&5eNkTUYPF%x z;aWzIvDfxoSJ!g=CzN&H=~q+yuPvEy)~%5b9j1la>0_QL4mg3d-v7=ky)j92h05ZSXN)SS8D@!`s_ij%yuIX*xB1-ime9G$qog?UFpy zO2p1!S{ncK#&o>QK<2BGm6iBnFCCL*5=zc+^ISu|)rI+LL8*5|*~`VF`ZIHqt;+`@ zK0GP1V$dB1?Ob4Y)P7SXRl28Jeh+EXIs?Qqel21a9`ZkVo9{vBTHTFt)^RR?fspJd zFDcqCPTPEJ3{$Gae5B^Et_2Pkub`{ox&9b#L?|(PdYVE)I|Rw)89`;+%~r2pJYT!q zMcS*#1^6zp$M%4#4<8ThbL~BIyv$TBdO&a`vp+#xfK3aUaFCw4Aip!t6fO#PGf-m4 zO$o9UFpp|#70$SvSL9LYR=F+}duS_d_u_p%?zN`11AC=sTO5m)&xq17iy62($U>4k z0oc#UH+1Mf3x!CN&-z=A|NyaXm42!O?h= zGKvUqa(meL?(+==hp(IhB+0ycth?0Lt&F5`37$sJZb%irzEWv-&B)N1AJ~WF6yi#Y zmV9-n?ZEWQuCn#E3&{^haONGI`8Au&o{?ArzfEVc1H>6D!)HJ$&njyU+?dAMSj(MS zvMwv;^|=NpiJrZ7Ex(nCg+D)6Ok658=ot|Z4JO|soEM!Poaf0(G#aZe15{>33hmp~ z&q#~cgyJ}{7le32BTR3;vIvXFHXbxI8dPt?5MdXu&5K+wU14ljO0d{Y#pXTva-B^i zB)D5gFcRQZ;?4F962~}fIvUSCXxM(MPkqST!8Q%HR$|;!`r=i|`=h3BP2-NrWlmIo zGazt=yVjBJ%gtbA9s~+3e#rbhdOpnH03vGN$;#q*y64N+IReuWE(k3S4SohjhQia&=1a4rhUKon**on|F67OqfT70V%p1b}G+?!7zX??#wA-(7Z=9EoaE_ zdP%xN9dw2rvTY1;QTlBR1=x{m+Dt~M{fwupI8jTDR z=w+I?+}|7#;1)n#?oT_JmdAR>4Q&<-UE&(#KItBx1oD|yO@~n zZLXNnO*4%V2+h>}xxJ_avuk-@eOqgQm)@sm+w3b(~q&MByN zzr)QPxSvCNXVzy@IitLMb;)l|C*=zO16;G#57)4|*K;l^p=MUQF4!gzsCnaRVB^mzD-TV@>95Juo zY02DZRd_|9Z2N7mE|EjSo^NEfQhL$`J=FMy3SXvNu2`0P(ju!$i^o|zykFyRm$&$k zV85^av~wv@(v))@1fzJ9_WO03{D49#)JyQG(zvUc&GL(eQ3^eCaD_gVVk3_L_!G-! z8GapgrC_nuARF#VKZXFUJ7o*9vW`YtJePM4no3E5Ucb2hkZ9Ry!%ELi^Cm-3Ea&a+ z$B2k8A0HB(i*}zfXH`5=`FW7*cB+X*KiDC(lmX z3>num>4vTsxlu3NW$$2$86l(tq56a;F3$Ru0{pSlL@0xLUlZ&PX`Rh>JKWGD(bykq{~@4?l;M#CWCIXUJwA za~P%PqJx@5jfEu{F=LI#$~~V~#s#QmUGdi7OG|x23R+KiJ*j+ee@Z>H zvER{!vs!c}MOu1h0|8H^xM-O=Z$nJ1r}IM5&D>lUD%^Hrvd^;De99XW*cc7HJg!sH z5sK|sAIhh#mT2M=G96cQnCz*w?GRV2v7wf{XTl>z?qWP^+odkmLwXi>gr9ianYq`x zfV*3@@!(=r9sc-e&7QAsonx~{|FWZe(1JpBJXfU^GbOCRlA>PJk!iX-o9JZgs>)F` zRbuJ?c$=@WvgnblpkE@Nhy7Viwy5*``WT~jZh(fBq}Uahw{~W48PCx}d$t;`f^tjR z=ivz~^!e9ZA1-Uh#hs}gzRioZPzYwBwJI6i+`U`TC$27<#1fUiW;tWe-`J+gpuz7V ztQ>~0USpq;y(R2_*Dy8L)h-JE5>i@n@If}~@z_`A01Y9=Zc#A5&AOEv;jM=o`e2O) zES|S_ER52EH^<9wNp5EWcJs;1`Kx{^;I*#xrAHNj>%$^#d-8T~IyG<_Avdn1$F-Gd zzOIMMo^P;ZHN0S~eSs-9_<=_AgT|iRF^-tQK#Axw*4Y=T3X+Nn&#&=`K2GX-e`=IL z*E;XmBU<8D)wse}k1A|(xgTDA-7YLs+W5p07(5@g7h<+zDIxm#c4N!B!V^LR`{Y1b ztR=hJh;uEC_xwt}(w0`?EkIc{ZR&lSt&Os>*_69u0une{*p}T^Yk7o(G25*4j7gm1 zU=tr>hmJCBhu~e{UPhb%M!zk+p+cFmWglaIo=GS=k|}jXKChbHH?!Svj;EtLAvv+I z_rc+bD_Rm3{e_j$$FG)OWHRV&&blBYvz7xumhGg~i}y)oTd+askwuu7i4UyF*<5jP zp9Y5)D;_fCs`z+hM23%MR~=T95$M=zmvB4xV>dIsk_5`i6+T+QlVj@DhKap&!AQea zpjkET8B6WPF!%8*9}Oi>t_!p)zsIdfam~XIShE)xtp|=Gp0*!#SKzRYgQg4y*iPJd z`g|7oO4_J!_=e>U7MS|+$?5Sq%Ez%6t&k(E;>9+t`Z@|_fq zcP-JOb*Y}8~|wUjz{c!)YVN(?%c<_2Tl34ScYYu$H_+*F)Ov+tQ9yj zYNxh0b4~~%L7zY8cDcleuF2R@Gp`pyB+;Zu86Df&Uh=6`f@lbSIkVw^^z-vtEiKUt zM@+o0a&WY3-Olfx19Lw+;1<@7ZhUIUovcCA5&flt#by=5m38(+POL7E!=_J&E7pna z%bS*)Eei+=Jp7Ruc+F@|Y|fQSY+vk7{+@n8s*^N~@miv6L*4r^{YvdhUE@5L&p{r8 zX?Z0sbhV!)!#{CVjd|Ws2h_S5wt95+Rao{;F#1-cI9BaB8kKh~ZqrpxpOVFuspruho`XXC00qiT%SE2_(02boP4Y}D&x?%_J{hNa8KsQ5>=G|dREZ-gA(cI zV=>`_$F^72QF4IjnIM)lQm$X0zNhC4qLO#6?P&_S~$LOmQE$WAntrRQA{}?_Ag)gr9ghGkg1Da%3X- z##>&_MFrpfJC^3W&a|$2_JCQhpe-xQt#=*Bt?k1^x*Ml)Nfi+xQFHOqla981l#6HV zK2KWr6-cQG-a18plyTW1{iJZs4X;Z$j#s#pfii~Rp+1$Nk7oUj8;5yX9NvUGd~U2| zLK=M4#Yh@noL4``k)q4}t>Es9Gg1-p%x|)8$xbntD!W?=ME!APJSzYR)w3^fP zWllw$c6Tp&GXZ3{@J&}Vv<#m(LpVW$UZYoUu?l(;!qW*pkhgdI7$4Vi72~?6NFp?4 zb)BoScy%!ZFxP;0NLrWb%na4;08j25Do;+9GG2yH}Etrw%(B_t15d3)!r1@j#8ka(H5 z-}LQr!v}sx(Nut$hVF;~SDIFf!!%&!^RtnUALbH>MN!$2vHgIJw_gHYs!+$2^ET#O ziA^5L;NbbMLqZ?#-{-lM=0liS9>}p0;nl0%I?y>XZ=LW(+|s;=S0IHahtPGWrY$aZ zgl5eA6AR^SM4^s#!Y3a~qNP2{5Z`GWr^rwaJv zLs?7l7UL5gQM^fMO*sSJ({`y|m6e^_&)pkFT}l4oJp3(Z?|tUgwUsdFDK!{^)lV0o(a}fPZzd~B5~HhGBLsA9)PQ7Uuu!*HPWi}vBYHS+hYY&_FT!w zPXK+zFEY{2EgiKt+0?xP3=AKyJ9?-p%~pkpm&wY$$ai`r=VtD}y}1lFX>uT_g7hZk zd9;m%D=WYW6cehPFnMrq8~;XJCNrn8-*sS_zvHli*+`Zuh$L(ehQ;f_sZ`o_8hXT%2u0LBS~UU)&KlUwqet_8I0e+_!~ zxxO0a=Mr7K(0qPIvwg(FzDhe^zubqn6mo7nX!PEhmLts!v!R)OETHXxWO zS6%xIu5D{E_$F0yVYAtlZOD3LvM zdsli@hY9)2$eZh)d_YoT{@pYh^J`_7eJd}Kd2lu=N@;OMT3$Sgn*-b2$?Bpdc*LEq z4V2Myuas<7^*+t~0@GMxwkqzqhudicc1$2|0K*WQbV(>~BV+twX6s{z`9Nh~Is)X8 z_>|q8aNVu8#jMyVe!x}}W5EMDyZX{P#s?11oZzl@d)r^7RG+R&NVH=xEa#lReP|f3 zYuoJ$q(20G;izvb;M`NybH;KPFmmIoRHK|*mV2|q)Lk`|m6yHImxE+W-3fx2p$( z4;@ZV2`@}H9EZz79-xs%cMli!GWM#JH$_!nNYRRYvDR-AF$U3N)*zh00LM_fX2NF% zYex`efm?7dUD~mG)?+!hlCF2&gbp2 z{76B91~rbqt~!U)tC#e{n zGui6**IIGn6?E>+r04V`Oekwv&d!*Rv7Jm5^wBbUX4IX~Jo!~wOSdd}AyM&UMtIpKrM#cAtb5Giq&PaL?gJ-Dg$zy-jj^mOxMS<+4-Pb)e`juz{K zHZA}i2$*Qfnrb~Z{qowPx&N_a2kDzy&K$M`#SXlzqI_B(P*qc{Fe?P(-|)UjORG#(rnq;F(NQ9cg{c)xG12n>%UNUhj4{lSFB2 zYmQ309Tz@=vFrhHZ~&RB!CGqk^{rn%_9@={MjVScyMIigDpdM}iji( z{YTrOvEM$tcub2C7U6ouS5dCETeoLlDKe6G&&Z|s>kS)&scl}*@qJM#S@ud?ty@=@ z)AUq}MMyu25$09dmZ1@UvA7O#3FQ66B9*!4%4BX^tNeV$1jZ?VB7+K=L#YnlJ@!RBJsDTCTug5Tae@EsK~ zd&plN``~fsXnec2rKqTZnSh?z&2On9E1#V!hOo(eN&6S`mRoQmQ%(YF2)&0WIlTpFjR*RVtEK-=ei%NPtRLBqUqc0 zj=UD1^n#EdanFBqQAtX8`0Iy(bVd#){O9cz;K>}g-f46<9mAZZfPh{umYFhm>{xII zhpb?haQ7l4n?M?Tq$~HP2hg*JR@!T_08FvLvL%xLp5SAW5*3{k9d&Wyzd*&((J0 zovc>c2%iV!wB^BX>;x#a)4i6txp#(RU7qYxo>Bj_@qUtI;gT-_P{I7|6(8FeqS1yXD-&#jDmrnDmY00!EJk5k3Ik`4t! z4KJ5v5d4R=v8)=S{u22uYnMrDkK_-T8V;5nHr5VcJlDpCJ&q%4O0LL79=~RG#l@wI zC!B%yd`uA#E4zPTXuDIg?ijF_?s@=|rO6xlE3$hQT>T$RA8P9!txA9Y38l=Pv^jVA zd6dtc2WvA&`Wv$5_*{6{YyADQs%1oD>D4Z%yKW$i=!fy6{9XzRhe-ZLvZKrE`{ABK zbWZC{;+L$Hja3YuJmO_7mtjg<+~3&3bnJPlu}yj*8$$h-E*Re~)-%aOB#a_8fXhe9Xz!UtB%SvDZDhHO?PUudMu@qrWdu ziQy>kc*o`goT$){R7L1TNOGo2Fql(C2qFMW+^ zs1i=&@ic;SVi9K-b?%T786bTB{&E=hwl|IKd^p3Xum+VpaB2(PZ-&+AvI9n6SK+0H1$y*<31C3F`1U#x` z2{#4j(zE$nl~-MC;+|>2`)cWIE!_8P^KHv+f2!0x==LWn60=y21z49knl5)rNj5*u zS<`a%oylsBvBpEu1LC7YAX%|&k;-HPDZT2pg9^X|W^&>hW4XsP2HTM_ObAO=x_*x_ z>^hK)XQ#E2+g{5CWKrGZ6C>&+0$PZ+z=$3r`m6mw}k}3gGf`kIq4u%3hr{?R7x8r%Y>s!;Q>J<|bAVt%( zZXAhXP(F>!`RZd;0v&d2tUbNH`Yc*8ES(NZjU*)9A9`c#uy3w&S`2M1^}U@&??W7l zic71GQ%ox=iE@PzllF|AXFvrWqOa$X&N2IhF4M_6uBX(@ETY5=!sI4E4H+Uh=KwL( zKmjnrn3m2j^Tka+e|`{>5d5MCG-nk?B3D!MlrUX*uC`&xcx4}dUY%LcN8I>sBcOSN zs@UWmhTRH20Zq%pp*_D%t2L~(z2Ch31N~8#TVan?OH+5t!nj+3$WN`*-x7SvXY|859i-~DFjUaxW8N|7=^ zF;3Iab;GW`oM){x)~1KLSV=1HVkvIvZnPk%zE)ilU8ZH3n-xAKprzEhGy(__l31Xn zhCl*w2rfrrqTX4y#aBSJ8~R<}za8I1v{ zK-+bfY0Tu$W#{21V87c#!|b*A3nD#&&kGS$VPLEgy%r~cvGnEBCt`be(0P1+dA;5; zL|Gt{P8!-UW#Y8jQYbMoSVZE8&-3UAwPQj=KMLn+f>LAl#?myOL_94+1r)PUMRPWCLwP;X>Icn( zn{jHq7}RxU9_)N^>FteRZ%pi(uD5rWnQ|$vQlJaCs6 z<#_PANg{)(nOw5j;N~0DS%W z+iq`nyU&(KCt4l+Rf()hJRO6Xi!Zx8l7%RBL`9Vp1WnGmn{;@Bs!r4C{U~08LXBm% za55t9y;7-}iGPyBB+tjJp1Pkhj8-=LMq#i2Ssg=El73oA8^Yqh~2iq{{ zak`9OUw)Sr-(};K*(nb+DyVkLeK(v}IE!evv*N-$3*Vl~{!y7fxR!?I{*}7ZR3^LY zJ}CJE#YLdXKT>t7?1g>@s?^wO>+?<-0_iF5=cZ|BF{)DjRjBO@5l^EZ`i6VVSEmHS zCY~zirnEtsAtnP>!+n^po(Rkwd?VSJLMltF>-UOMOLSP;StLe*w7y2G-3Zcb zJuUx@>D3wBtt3%%$xHV&nfLg#h^nf!t@o~SvLa5_C4{~+KB#CQvayK_7L-h95V1hU zODKurQAtVAyt26JZ4!l?wHk>+>3mRV^7?@a^2|J&QEsiCQ8|Zw4!&Gf5CY1s8If8! zc{di?lFi$8q{0G%g>3)Zuo<+m^DvTeDs-TCrba8>M#h5X&FFr4dkRlZ^Z2(Ftly^~1d`GGwz{j0XB;6JR z(~uFB7=RdtURB3&j!+}k5=4wOSwB_8PynhW##}KFRpXSAEU`{qwd?FTb7+zK?EazIouP>h4CZP-}02lJ2r@aLZnKNB%P3=^?SMB%D> zJYA=Au)FTl!zV^H1ujI7#w{nON4_hdW_d8TmWlelF^#$PWh~rT$<`WhuP-VtvUMza zDUh=8Qf8&n>gq$qD@Au$+JcIrn>b5UvIpjh>wklXlVR<6=D#d>|uS#1M&%({}_Hxe86cz_D`QVUpnUxA) zqqq(*<_(+c#f{hR4-eLuCWPzr=eDtj$z9LqQC#$dD3Li`Mi+2Ao}ZsSGb03aE!wsN zsA*2)RCyRm$I_|h2{_)x=_{+g@NCL}a*td$5*qJw&sW0)D}hzGKb zX>4#4f@<7asfY`Fxc>J0Z~yT57j=GglQ0OzQv3PoiJ7jK=`_AOofz!p`t5!COZ)RY zIZ61VFjVg2O0iTDvIZli!Pe4lXHP+6EdP!Ms1V9JD7zF`1U32ctEB^4qrQT8^ZR;J zAD)>Hmvo#X;2FsU~n6D<`XBxi&&R3RY+z!X5*7P}fq%9HF^XVY{KkGl{; zTxho$$m$bqJZDKHYZM)q7Z%Qrr*`Ghijgm(xGPH27{feDR3zCns3f!>&x2>C5Y#p; zfrH0&bY|~{{;=yFL3sK8`{V_xwzYhnhk?OlErpK8yISz%yt(kFFI{iDi#rRHO+$n^OaPTU zY0bf^xOYRTB!8kb2ddWNP(d(ICJcjhF2sEjs-avwmm3Die6YT&%bl$VFTS4mb8+gd zi>V8&ytNi9WPL~UkqMm!WK~R=jOVvEqq-8xoDK#=hqypZ>KNte#!|ilX#qXu5GO_T zq5EO)WSp--p_a^b_F)cykFM9rxwv#0CK?|CVY*&94Hyk=$CgBN7>4V0j9DVy`NTKK zmaz1*C|O>*RA{AnPm@fPr2k`DClj?`CKl+N^WdSXs@B+wLJGi`vL7XgFpk#{T$yU= z_88q|cnV{t*56)>r0Is~zRdiTOUZF#Uw{j2|NNFQ=#yb@=9Cz6zveuBL z$&GQ$iR{z97o?lt{6bY@IOH`yck8#FSi@}flc0J8(9UE3)9Nm8CcYE%OpjS+j;C+~IN+Ym0I==*_~t${#^EELSdfS01# z6bb`?;|1H!W$yBDeYLQtn?Z(BCQiU0R*SP2N2+K z8ON^WhO8&AP=bkvQ!-3YF9he^fEEBJ3hF$CuCuN0W^BO#v?4_liv`HFuSO^~dRZP)2ANb>0EklFcSbH!?eiXWj{*g`0)5{-9-a<6 z&mdxb`+n+LFtreQ{_+K6Lbw9h_3h*HX8;oX-m+1X;G;(m_vg1TZFin#n41FVBR0RMNTSF4k z_Sf-s+fcabZ^vH`%>&}DGOD}w;rY`8TZ|X?{q<{rTLgN&Gxm~eN$7^gIdM~1TA7W+ z?VLA>+$JP;Uvk$RaT^s*nmZdI6lIarpRK8Pk0ImMt#z_Z0WQ&t!K>Vm8aP&c0Z=8B zDgX^+ZL0_+v|e%X(v9LvtB8;@CZbmG7~=-61OjF^selxutfH&{Q)MXu!1|a*M1*+?#AtiVlTjr$P1hOcT<~+8b!kc7)fLRE6>pyZ6$@R@I5)}}^W;p^M4k2U z^kj+W>vd6J1STfJuxn4Ju|N*3`Cu8hBwVzXr)(hdu+3R7+xNG&Wsvqgg)#dT7|%aFwx$;qKObLSu3nINnYN<E-w>^b`Q<-aCo`A%AyG(qN~R$K?B1y?3>^;crm7JZ9BPB z22RMSOj|i#nPIx~M3p+7EfPV`u5&Bf~0Mx$zXAx3H%Qh(>sN19%zQR1mt1ORMpa2^W7hS-e$ zg6q(Bjl0gwq@uGpR%+4#gJ$S#5be5Ft-XwAW;U=MJ{<``>y|9zREuhs?eb+!`}fm{ zqu7yJL$mkC>lHa7q>A(Pde{%erE*uz*M+A$HPhr;mtk8GuWHkxK`1RdzEfL*EOC`Q zxJ)*-fH6KhUi^4{Ax&9I^LRDZMgE*;XfxhVYYHjQ!W2?U6DuI(B_HmD;QL(OSC zx!>HUhuzcjj$ZlQzdk)a*@h1f-TT|*$FMsLZLaf$dgylK(*DUcQ!LDo3AmXEXw6w$JG7Jp05)xhmaS85&=e`vJ42&QIa=za zy4Y6>#0o29aXbBm}Z^s~)w?yZ*)~5bjwRsf_%Vr{{t>D(H zTPle2nq+)xl~klTLRVfepsK#UO~4czI!$31{L=V{fIuQjjJD~#zkd7e_;BcmqaOiY zrj}VqMdr5aKwh<|*F23u+%FS=eEt2~G^1his&8*EPoJJ2_MfeJ{rdYUi%=B4lEa!t zt~jc5+o<@0vqMkfO|O#=?h@WC!C&2V&&{9y@({{H>@(C>TOe0%@;``h@- zFP|Tu`_tE!iM$h;!qZQk8W5?mSQQm_*N)b(wcn+}8ch{<#7H-fk>?N-ag z-xb(GpVi~(?mFa^6l;!rsReC$zEVj^vDA}}wdGmzR+eslq)!TApvF>|bUcmSFeD_L zMle~#f-?$WVPixjhac*o*qZwJ^CEHzH~Xe-lBQRI=&)~8)lUIXHt{GX7&dWK*pLR; zhT0)+8cHJGk1{kJF!7+uGpVIJzX9 z*~zl9Bo&oEBKs;bm>qJumj6P|<^Q*wSA(k!T&WOH61J@P;!8}`P=cl@{Px>d%B)WS zh*czxnxRg`JK*IsMsoi2)6h11AT$k_t@Bp`9v=5W!ufnH0b3&a%Rl^?nE?0nXy0D^ z6coVaJYTMV`_rGlIPaDrP(-|b*mZ86os+mifw-(Bk3CAn&(uc2aLsCqbh`}Fg_ zF)D|yZ{pXgIx%wc0ksxhnJSq9O12`FOy55E$-p`UZSk#i}1vE`-tx?tM<(%ib zDgPwtmXe#21|a5D0if$N8Ee@Z30~A+rm(mB>*cD*%k`lOWoC_M_o+(I^L#?g%pw5d zoNxE7h+NNCQCW93k%6gE^`apYgqUpKw&QdaNExq^#hNE%Ig5;dxJeL^_x^OcOw$!> z9!j<80#C}lJG=8FEU->6S;u#l5lk+Sq|R${t}ab+;tkMQ8kX-S5zy?MD-m&|`G^*y z7Kf3FcZK88*@fZT<{$`P|Mp@nK7T%h5LD51eb;rLo&l&2({F$KuA=|++h2eA<*7AY zH~jQVN5{9{k7ut+rU!_;3q^?#K@?rbpTGP(Pw&6~?G*sC1|TQYmIfrbDC)IVn-NSc zHwX$nPp3#hCzoG;ojx6&+kNL}_x<=9bUdBy&wqM&?!UZ^Z-Dr`{h){}*dVFKoK{}K zEkM_{yMulG=HFglpC2DO+t1GDM>J{3weDGk6zk&ir%kP;K42@(ckkOpHx#e%ExNcVPxJs1S@X z3=6$TP=Av+0|17*Vb>ZaK(FU>5ct0D+uYY|f zAg>mR(^v9R7)N8?`lsi;%KYu?n<(~sK0F@2zrBZmhG?E-GeJ!ls|t?_V$O0@1(x0ixIGvV@z` zCt4(AJCMtjEGj7{AxhCxQGXqMEGQ-mMg!#h80V-?C+khOYdSP;a^pPq&CoO)#_TiP zP#Fr4u|^f|$7^eCW1D$$L$_~x1JTxWa~MP1ZapKBthe>>@L-u=Uteiu=wb&GUb;73 z0ScsvDSNkh*SEAUXtuUUnKmHgc@Ng?P!*-AzGb(^x;<4rHU5f}uicwk9!jM~36;dM zn&Zl(AiTX^?a%$N`w8lxEW)4=%lES$XLo%08UxbGXqvqS&kCuN_bdY(TxuXO0kAFG zb~lf&UKBvLvrW72cbB0VTD$x9+uyEEZ;4lbU8Aysk~QCR;q@01Y*pWp;|T6EcY=7El6y+QHBlxY;sGlV-5+$E#XVb+jVWA zv}Su0Gf$_h^ANtOk#`zf_W8%y;n}b!F zPE~8}uw*%i>n2LpDJA|d>N)jHb>Zskbh?hj6jQ6&G(5X7yZP`iG{Mfn6)z2?5rA{P z?aa`1)9hyN6mp#|wmmSR-?bgu^ZD$8H*C_v^Bm}#$GJW18pA$>VmFYTQ?!!$&DfU2 z)ir8aaYr$u8JO2bp?PM2;sP z^w(d%6TpnV<7tvIQgM}bT;r_-Vla%vg;m9A47E&zxWH*iu77$yK=t@KMRE{nPU0=;_@jPH#UTrD5!9jV^KNIZ&|7c!1r&jzx?S-Rcs#O3NL^R z6ffsj==0%I|Igen|KhK|ItiAU484B6c$puDU0nIj)I4-g-M#@ZUM|P+xKMi;?FwEI zN{6?xlplqngle#XMpIUSGh5BKw5`VQ;`ySD7v%~dn%)&Ku&f<20~>VS6a0w*X8AU5LdNFu1MLz z%a$h65nQekmJK|q(!2mbhKP-qc);=!>1>%* zeOx{lMZ4)~Xoh(_O)mAhwS$Tuk4hl#F3xYl<5bnN?OzV%pz!Ac)F@72MVIZbk~|SH zk;(Rzg9soJLJ41H35?Y;Kn-=z!_P|gZ}35QR7&M8Z7#+0Ou6a3Hiz*Vxvwjeh$D4^i$Dljbd88K&>r zu50$YUDtFu$t2s5JbsBjC8M1x7h^p@Ydd_$%b*hJc$qGj>xGJdR*wwBpwQEFA%kJp zM^<4IH_eY{e-n`A_aW#F}t^9gk^|Hg#h&!MxL%rN|oxc);Ljd+cBDl-Tw2J!!N&l`tzUu^wZNXacz2(9o2ZWT~YaWJ6my2 zg0*TRTB(%(hvQoc$=5ws2;F&Z^D}`743HCNjU`ZkpJ!^jhRDp51O!nu+4xcWlWTt`>1Lrwu2MnFaX5`_d)rL& zq%ne@H*0x33^I#~mTd%?DW*veh36M#`{^*SZmwzu6rEE*Kv#|G!cNWe>+AUu#-(yT;lfwPqDN?~rj9sUor#z)nPLVR!o zb!h}ZLER;u=cWMQobURkAtPR#xa=$d7M(}I2Zgxc8d!!=3d|IbN9~91dda?}$no*5 zEG>12N7D?5N;k8gY>mn|<@=~YB-o~Fx*Y>SbQ&k;=gakM*bH4SLB{#2ssIPC##+qD z=}v&EI++z(r&JhYA|4Q3cvMT()wE@~uT-&fHU?!_vLNOWqJ%VZr>HhI%VWz>ZsNXM zL%gw6RS5u!yXMxNR);n3Tdr){7ae!E0e3G26G_NNk>(mzq2hfyW*h`OJ?&NL_%c_W zrXXqV`|EGtkd|wfB(Ktp)R01Z&flAc9}j=>;d*@ieQ7dj+Z#WLgcPw`@Le9*Sk5$E z|JA?zmkWLKh%Mb$0g+00AOB{){<7bhy-z1YZDXyq7>37VfO> zR!%yKVaJuX6$?6}lHgfc+xr$`BhZ!4b*a2QVznNOZJ`U|STqF{{`^3P-dt4uVakyt z#r|=4etZt$YK?uroB%-8bkujd@$%-<>CZQctHv9&Q6*F!UcI2|oB+WrEm2WzJNnbl zzl_(*?|*wMJH3^ptU`pM>Nj;$R%Dt58XzXq4K{@N94>M0W{kf~FFLjTt|8*wMl7;6j&qJhZ(>SSI^U~-15s$sJm`pfki#50?8ia1L4Mf^W^ zZD%Zr$oX>K0QXIL9swdUP1nUkk0lxrv!|VmuWwUpy9jIJhJBe0HLjFZz#3ByEia_X ztgVK*V~Ze8Lt0oGiKZpUn3mP8EIa{9c|UB;9<&U{ZY6S&#jR}D5?(8yZ6OP5tkWX% z{mQXjwR2Ng&199a`C~9r6H2v zPZuBx;%tM9KOVojlx?C4(A(+s<@3WYfB7W-(M|6A+ncD8Aq53UOPy)ST|I$2(;p5^ z({_Lo6OCXr1Y?=ojt%#=C1@YM<1&wp=^JBbKL&}JQE|WcA8C0lSSEXGDM!WYCG2I@ z?~ksmF(|e*$3-&R67pDODXUwi8p3=&PcicE!qli4c0CmH98`j_Hsz;QS6mbtLxVwr zs4^Kr=$qacI$y7r8^bIbT$mNAD(CUN63# zgiy3S0~qI1qECXHE2mvaCaS?A0WsM`<7BOhN)kxahXA5-L^&AL4~?5-o&vIk^5OKi zZ)0z|-O!5!0M<03Xm{;H_}umlF;3%T$UZ%HP9`*;z<|%l2|Mq_JN1Fos$jEIANtS_H4`fZo3`RaoLgV#Bo0u&#gPLp!Di~fp zCwVPq#VnBz6-3wTg~%`<8W8QSp^YU?!HSg61QjqDCd*9I6c1rDwqY{14bAy_PNK*$ z2{w8n;Jk1gZ(empOB!Z$a1QA4u=<)FZz~yq)yew-`S@CrR0FMCi z1^|&!>P$}xLGT)8h%aHX8axmU?S2>6^G_?} zLaRqM&(s{ZYIvE9QQesjFIxYY`6anBvM^>Nk8BxpUR-f7N0Sp{BPnHzY~0uK;qY)i zk2PYdKgOm`lmGp%f4w?c#+%VLjXEUUA{&tM#*Jz=Ah6|P1($eb!=jx%~=#IPYl6B%VV94-> zAO+v8Nw&<@iy^DblOU9RC1yAIP*+llC|@afwZu#f5ygOx58^_A>TcH>qz(I+S)@iB zOHpw}pYSqU*z)iXattcMCEP;v@bF-mXE%8fPK>;k3j!%Kn&S3(-d-jQ$-S%8dz=ewu~BO@-DNBWr?0dA6EGK_3f8mp3>36L`c!( z1@+YKl8X~Cm2eaT<5jxWiBBsPS0q`wo;3pwU(UNxD!l}tYFfb1-@g711SS>@fD%|l_n+J0`Wd3y&@59*E@VXiG*pWf zHEa%ja|kUAxG}xyZ6f4mL~7ANW{5f%x)qeN$w;j-?(7&qFxDDobZx^BDSP+Du~86~ z+{_C9=C{kh7m%C?uK=WMBbZfSM5mP0lZpuUmaTDxgH71!Hg(3DD2*gYwo#C4; zT9s;5I$Z1C+`pB(T8rgd1TDXn=di}G58)JdMaxH-)EmA+5g=m-Gf|_&OafTg#|?v0t7CkwV#Yhld`3pROAP zur4i6R_ZVr0O0gKpU;1bDmu+mN`zFZXwO1SAdH*!* zta=e8)3S&L6?|R>1kR%jzD`D_jI zor0dq2yQ9?0Bc$WG&tnkH3kKBAPYi_ytcL>L)WWgpdW0An4c63jhi%9x;`(WTe4mw z4b~$`MV8}s1X@A!8+rkxZ?CVhu!v6Uo|PWuBqSZPo??VKTw7RU8dl@fI}L?7k=#ti zwhY13@Z`KZ`%{jAqnIgGRid}o<1asbemLxp@26#*#74eLAC`O+T~b>l=y&FRv{6Ar6$ zb}G^`_xmRJS)}s3XBc+6em{?SAp_-QlMt`d>-G0Y4|AdzQk=sWq+QN=Q)RYI&m!{s z%ZsT01z%tgR4uJIWNTgl+#&Nq?f<_czVXd~Fi*1?42YPFLejBti$Yf=VyGxu(=eOa zP5H1($~hm{%m8XGV8d-|2`#CH5XN~_Rn;(0GZ6%$fT*%UG&HsWLE<7YP@W3rjw`@W zf(lAbB4uL&+KNn+(x-=q(T&&3ya83H9xk7#*zb+jDPK7)VWDI*6$%eW!EyEYLWH!z zb$Yme?C>rZcTOsB5#QMQAgW#8<9MoF$f#;eJ*{Rj%haRteJ#t5GWAwtRAgxB$TGEA z8To`aYa;#Vx~Dic4=m8B{&kgpuwj4Dcs;$sAKzY(ZP+cYspIHre`cymqpVMK$$E{8 zfjIAX6U$n3kSfFM+UM?I+$oseeERa}zq!d@4cL$BgCtj>tlU1iR_R*n1{u$;G;E=dJa8kZg9-6uo#wTrMY4WJ|r zVa}5T-H?$~B-F}bLl`O@p`0dAm}<%P$s(UiDKoyTu@DkSTTdfZB?vK{PG=|MLwIU; z{rPxVP+W#uu^HEK-Vd#@@%-W~+|G=l-O%rMgP+IK`6_FRTs~+bS(Thy8nq3XZdBh* zAvubEt7v|36-2NB7v<*)_^li&kH>jL0b#l_s};Mgl;fr~)ru7Yv}=c^Y0j5p z-blNO^CdUlVx};~JeN#HRj`4o z_mUK=RuYsmIB4Ol_4IyY@v3mv7Jn^VUB#&Lnd?>i4`}KiKw)#;SjP0 z&26d$^6}xp5Vy8%o9^q&>taN!4lF>bezQ1aR~dG6rzxmm%ipCs>bdbob5WHYOZ78_ zi%W}>$gfmE=~JF~X#RY+8OvKMv{!du@za-|+TMJTr+@h$|I3g)uhkeUfeG?43T+aIEFaH38%lY(j`i_)WimdA*KdH5*+gtzUO3w6RiYg0H(JqoZ zf_>GcxZIK4lMu#VfB)BUi&D!iTcg!EYik;8xb@DL_+gzkl9Wi9G;jQ@3UFf@03j$_ z%W)Haf;jJFcH#m_V;U&jB+S$gU1QqpB)3HQ2$7}R>z3cSQYtd#Z3GI1(tQFTUM3gj zn9>8)X`H#?{b85Pp~RiK(gx~=xTOw+05|LGHLuPrq(*dX`>v;U58~u@L=j^og;mSm zqPY`Km9#OfpU_RO7fztKD^L*-fuE+Z+x4B zBT;33+*V5E^QLFja>?s717HTT43mH|=^b?Ov`sWIFz znNl?6dYQpw0SxW%__#|1rVK+Wa%Isbt=gq2!=N%1l|HFJ2Xg9EQaoDOB!W)!2%`_5 zdSy9Z&qa|{14XfWUDKeXtx%ywA!P2LDkL3#zG=zkBjsMLE~l5b>d|{`LEY+U%wpz>bV8@vHkM=c=+k($AA8x`e*;}`OkTi7iOYi zXsqSUc;B>{qA)~OkmP<{(UYPKECwJhVOLNLE~?#7e+x$b;3`Ta&QUhgoXw>GobzpC zjiGUzV2q(844M?7LX=wWxdo!jfCvb)Ou-F9XN_?|N;@^Lj!7$LOXgT)2Bw1eP_kpI zg_ujr6xCg=?vauv4<{!Vu&7K#lZJ?niqxgDRY7PPQj*KNlDRw{_Gkb>f8dUKCVQDr z(^*h?-GGX92>{GMhIu{*U;*LD$VG17xF3>)P%)TF;&ps^87WVQm&JNTe`T|2tyNVY zN+@cTkRD%;8CfArh|}ujsN!3dQ&BX3PdX$HP&Fgk>K5b&G{1JMf9_qCB(C(pVjqfo ze$&{ck$TG;QN?3PeTaYm0K-szvqC)zkg?_;|MC}R9xrb(oI>${v5b*b!C=d~FQ1-Y zzPH!#HlM@pQ-fDyjb+B=`VOces{s~WgXZZ|uL1w+U;Wx~_xbbV&>e;h98*=lGH2?pu9R@L9kVqsr)}yEhFqww^7(fUr0p5TCcnL9}W7s%9XEupAL7B+Ff;1qg3Yb!| z@Rnb4`eJ5iTAs;{!Sz+F#UgRh%90|Tex$rs_R)F6L|!};nv)yN4h{3$`NE7t-_B-c zi~aEMemo{FQ&3KS2BB%W<8D4*%E%NAnAA=Y;FagEWdEi;?4l}+dz}^#u^_nADPrch zJ;%a03qKHmr_Y}|Ylz{UODw-3RweM+b-0j!C7%_WeS|nD>6#VcKT;xEPaD>3nm?}t z!?eQg%k7*IbHAdZ`R+}}?t>s&KcQkxLrn8L{r>xlC@AiVSLx&E&x&D`KmD^qxaNX_3}@riXttr&;sfRn$FWpB)Es#Rz~LLL%jYTCo2kC5Os!Z zELJp(b4Z4q5_{UtggL~H2nb9O1*UBq7h#IWH4#8<(~>0urpY@$f~&*?)tJ^3>A{tD zt$G&s!LOJr$H_X?w8qTRO70%lez zKeWu4WL8MqvH(F{!+n^-%hzMun0{!&WS9-XyiM=@rThGOFSCqc{%smb5Er#&ghXlW z6#$S_tITsVQe+}FHExTIDsv{IC?KAv_ea+c#<5_HGM%Y)hul1=h*_tLyF7nTfKopH zJo%xGG#ITZj?>%$d*wU$6}ysp9fGt7Y2BxC)4Jv|Ivv!gkj z=P{_k{;}`46P*Zp^=SiyIN69juB~OV`ms-3_RCB%2&NKPR8=r?GF>!{$zFf@^r>m> z?A$cE?J%d>RDsL!wK1RirfC>+NL#2N{ z_2kl?O`<~4zq!_1MYr_%UM+glk`+6kMq~_ z-v|KsbUlhTUOhqWz+_ZOW|^qj?fU+=%deQqPQ;|}Zq|oqGtT<{{-RBw08LAblfyVN z3sKYAURCCB6%9!c6qbkQ$HV1%zRaiOR$KS2CYmi>yo*KtVC+_MRL5@qU{eyqHYEwK z8l|cM)L6^&?3>1#hNp4zGuhTOWF?3TIg>Xs89@Qdt+l2#wvu*OW*7#vG3|IAMI@da zUZyHr-pOWTxl>#JI8R83X%!aR%8P;sr}H_YM9T&+P?NMicf=7sOM-@a2b(d36 zLGwrro0B`L=tH*)asJ$(>q#8kq>I`>Mgq~^5^2sAipqtMm58Ruf69Kz2D-$~0nD>| zeR)CMiws!v&6s&f3h@G>vMBH)_Q*wlKBHP=q-+op-zD6lUi%p}*y9JM*;rJRB?$ zF@2gR|MlgYAg)Zc5!#3fS3%OK5UYWrgh%v4CGvM(S$!z}=oFizU)Z2*L{gg|gd&NUC+~GX9(sChJ$^4w4xFuTu%;+VK6BN zNkELw@GRH)UCBUOkpNg64i*Y(ct6;;*K?|x^CE=8gG5Z`^YfEHUtYe~?SbZfPs)lI z1tOAD`Tp{KnHOX*Q%gwp=xSpvG(mdy9&54rWdpRZVB6 z1RRf-Vb@sGxZnWnA1ndy^LS_m;tMGV6f|T*ry9@!*dP=kj<$Dpg5 z=F8IV=jTUany*(R${1^V!$=P$MVYO>E`7{s3^_+B{g|hZg{IJmatM^q;?2Fji!Rob z$)OI=BKLQAFI&0|i~JCeEb}$oGz1$%P$i1)PKw)@3q`jeMW+U4z5LV5886%#BO(GFc0Hgk$D<43FOQ!ecZZkr zOW(1ZjGLD{!x)a3Cck@V9{0ofa(+Kv0)nVJzMot3$PM?0wtxC%x=t^zuU^E^pqMoZ zV|3*cd5!U!!u7Wl+Y_riaF*acP@EWZxpi{gy?>@tX5|jRl7p|L%X?{^$R*54XerKmGUK z|DXRN0O;E0fAQb4|He-i=r_;&JOAsqfAL#7g7bg%-+lV$e=@h_{5$`fxBu^NJ__;w z?tk$4=cm}~UH!~||9?M97~YT90Qukkx4(ROxU(J9|M35C`F=v*T%8U7!T;#zp}ix3 z|Gj@tUQhG+d;#$9|4)A2b>*3TdFH?Nzx;k0(@skN{{Q%w_>3z4-~Z(P&;Qrc|KtBN z6_(Bp-(@1AfT8AL=uXp=D7!Jr*_L9_Ta{j}#cmN`Dl)r46a_i|Jr}LpVQ}j+a+8rW?fjkoQ`R1(^5i>pbtDpNHq>aD035G6R_9JY9BeXMcbF zoeWxQMU|-i^89%kXOY<$I*%u>4uHR28CeJ4qiWrw%_H?VNZy66+^b`~c`6Mu)EG`V zteiQF^4P>EeX^MaCugE%vg&xf1`Ta%_xt_O4S@PEoiFF>cpb;l1xGO`qpJ~NKvg9= zJSpXxh~lr`?oY%lH|a&cfTF4$J6I* z-qW<_gKMyTMe=kJ;Xn6}&HwDb^6B6F&veB;NSRe6UdGG!Z=$k)eA@N>o!s!P+%E8S~(vS5iuIKO$&%^%zn3r$$+`2t7M*vy}G46{?|Mq`j_y79W=C9uXC>u&_IT(X-j46$k}m8H*meEO%NRM4(sCaD{QSuWe|&w5@T;@?{h^&MzTX=^%j@Oc zvVDHszaLL?+y|SAD*)E=fAzn(`?vqC-T&qPe)&KChwp{Nw2V!L7fC_qp2Qhyy@G0C z4qYC*<)(@(1<-GbF4>1_R3lAgQ;dZF zcm7KaGyco}^ULgIKlJgiJqc=!3BiIej&VOI5KzuB00DwHyEnYBXGE$?8)(hTrQz$P zddTNaB%PvAAWS%q@hmt8ML5IR>C@vQ2(ugCj}w$g8|G1bo(TfXOhn?nB4zeQ>vx&Y zS4Wl`fEbM`@*=FvW2yjoFaM|i@bn-2-_DbZJFq0frmFeG<~R{1V0G>{>6*RQoTQaQ z1RD}nyi}>wg@9BUhrdIKXie-DY|f*U3cIn1+p#K(VSl7Zw0=u}*f!0~Nw?3{>ZH zmRpd7plrw(YpoG4#N_;p_12*ZvTVD-UN57hNmEkhn)609iT0XB7FrjJs^fIYc25al zj;(A43u1~>#t=edo5r?KO~+^vf#JO`a2E*#$vlT#P2Qjz%M_gqF~!qlb9bsdizVHs za&tY@QT8Wj0KqAo+DDoBtlv5ij=R*W#0Mc1Ix->X(Qs$D}l#;6y zeT5Z65eOT3s1)rw1vN3(2NJt@9cq59AJ`UFJy9v3lxTww=QWEf=LR!>)Us8BR9Elj zrrdd}eqfc6knU_Bx>YOD7DO_?UtUj_cf-x|?xC^t_|x9L@z=NSK)Aa1%kS?5wroXQ zP$42kxSr?3bN@wtI$n+{&LgyznE>*rH)N)m&sw9#JFsM9VNrdp@0Vm&MzLWVqNq9_ zn%4B)KoEhkfMFuT!~|_;KU+4$9D>g{g*EM%rt1Q;Ax^TLLpP+i^;UW7R9g}NrX^^R zaPs28jcs`vrzl48tW2p?fD(ciZPf=5REhTcK6vMxNOf++Vc%PBkMD0$0e*UZ251_m zalG6Gs0GAovCawVC;{Rz#pBHgDmb1_hyDKX@T3x$orj7<#!4q46OpQaKV6@mcAuUe zzrVc$WGsQy`+%U`zMZDl$=utaZCgKwF9?VFz0Iu+-)Xx<4Va)=ZQxhTTejVh}p zXS-HRRcF!N<@?1#-w^4?;#x|$!@`^5@2QzTzLJcrT5)TBKWro|p+LQTx|XM0<{!xA z`l=pY#4}f<1R^$2aXNiHjRc%dZv6jo_UA#jE!kZd_*{2-Bf{PN!cXQ zB+p`gba&XRU~r16jKSalMnEJ`q-Ha53YV~sxj*EkUYWYCnzj=KHBSAZA4x!n`P(6a zaDV7GtFG-Dt*|>BQmoS%8D$1?5!!-s$st5w05|fZ-DR|#^qW*|>-#|g1ZwN`V2}6r z_U`6-)vONVL2F_shiNZl?z$_8ZdAAGIuKR0>A3lZFCPH;%Re+RyHsK)iv~(lpJ=EE zfUwYI12UB&W%*4x2ZHl*9s#P*f+^oif}9*Ta;p6n?0xdl$C3&QK-?Jwp*s%=`=BNG@dI%&1(;?cil#amR;=C{Wc_K>A$)JiRxNzBo`#gKEjIL^<2#$Ri zl%!-E3W<+^Q56x`ibj;|SI+tn zBo;o@TFG4Hc6o(mtN@~8e;5WHCO=xAti*T2NVcOH z5za=f0H$`kol?{_Eg+uVG`eQ3Z||bxi2zlRcb))EI(m7G62|(vzPVeg6p%9Yu4zoI z*S9xU>voO6cP9#yVo4{GqNis6w&k*}t@(49pTrLpO~! zM#sJ9!fQUu6oCg2)5(Y!910u9@cyV@)U&sroBW>lx=IOhCduQKZ4qVs0tfWX@Xl$i zX|%R(Gyz(Z%l;OEA`&lEtst131wa~p^dpb0YK;kg+~hn>{!+w>AAl5&G8HBp+!HB=lqrSUC}y6yM9r-MAQ7b$KWxML?tou+E?H%=}vt zx^e;l&P70FsXJ|#j;=~G7Q}1@uR>K&r zfolN6I96I;UpLHf7*8f%uI61X5Kx zK$m0RtEgo}0IigG4C4@ZOeL?a0L-FvLE%C^)TT9+7RQqxJ;&JjxWfxAsOTb2)s#Vm zKk%paD8y%&O%_kZcAtcp+0^>>_SQOk*dNLbMR>R}nn3B?oIG-wtSi7qjI{vZnCH7n zFG#wV2`bHEq0Q2~r2wjA(}_4I=$Oa*d!ZPsLx8TxSr@$KjOpodD{ugqJO~0mS+`nM zden|4?fiAhN30byGd;9>QJ~IjSo0 zWArpjbRz@l!xR2WZk-eF=9^YG=9^0ucL9JdNsF@^UZ*6Bn-`+wjlC+?U>2I?^_qw2 z&EKEBJXze*r$H0VLZlc|m>3Z#G>vj2Iaj=7vAlA}GZkm+fIt*9fV!%f<#VYU@Ve2R zQ9JTPxuaR6*m#~u86w3ZDu*wm<*p0?Sk)Z_c63gh5RoEyXsyKa?8}(t5(&eN-c+j9 z?Qu8?iB^?opJE&GVHGnC0sQ#Sxjd#UU6MH^aS6%(uvbTF+a_16N(&-#g!k-aQTJ3J zM5jvwB9*BCa2fSm_$edtNQx7%&VUQeyO}H{5tm|$c1%Ue1lS+86swRZ0G=%=2+8P< z({>Q>IQiA;_U^44Fs30A^2|&xp-w=Q(;7@((lk~aOAIW_zSMc&Z>DMB*aap<*2+~ArCBj-MhNR<8A@LAa z*wJ~owrWkIW$+|oYSsCc6vDwjxi2Z!iiDxHVk@Rmij-&Hv~}j7ap+k*Kn&rzR_*Kx zm;pgFJ}*>F5HZK0k8hMzVkJpwH}P)T0Z66H5}uj$U?i8(TCzr_G=xOHaIA0G7V_*= z%l(MmOY4dk#!X7Zg=8HbR&K0y5Zu$6Y&;TGs$9=z|X47q+ z`lo1&n)PYefhq;;j@Isvt!cujudY_cD3Cm_p6~m^=!U#?N&W%|=<4dat?SQz<})lz zsc>D%WEp~=pxcubdvcX4dH$s^uBWb?-d#$BV7Yp;5J8-}va=Vuk-8vxjwCT#Tt!ky z$3^|V#bDEtOTq&)doD1PyxRlNRuaFqIFE>YwB znn%3+rL^Q?eU4Mz1pxRz{;R8B_p6#Wkmj#^{}I5S z{JtS+xq?{=D*gU%sebLRP{8vy()slISN_n;Kl<%AANhhsQq6z&*ZF&Yd^`*XE{qJZ zK#c+kzUaCBFaN#8i|)7n_x!O}d3+`AvOL*gA`ox`V0YY2GIGyXH|uINjy)w?Mizs= z|F_Xczf1ug&;j`PC+qL{(+~F#56^G!gqaMj*K50V0BYS@Kd|^{Ulu$*Jbd5-@4vmd ze)afBz_0&s^Wo30zy8Zs&#q^c_Jcohc=yr&sqf#VYDkwCZE+DnzV5^Ahd;0WEnj`r zHM0VH=f(8HKhyun&-Xw6&Qv~-rE(%k=I_hqkAiYI$48gp(u`r3Oo61f^59NfxJ8?V z+&g{4`SQ!3#5GRIq+fJ`5;zK?q^b2-sS_(n2^%CSyfcw0#f@ZMBk0cy5fxZ)DGHP3 zNV0PNGFM2;ze6bk)WVmO+Ocl57K*e|-sOX(fVw91N;@rP*@` z#d6k9b|4$yX^hcYhrad4p22_k+ph%j2ma(9Iqzb&*8cNd-}3dV@b6#w{^OtczP=1D zkYbl~38Q`v7vUfL)A2-(eBpC8b!Db{;t_?0%G~`Mzx*^c`A0rJlz&Q6sY(9;z@Pb> zdjTdl5Ygxd*@g{U1QTJyBmz>JmbuyiTR}$moy$$~Ay*`E}QSyr;&phT?3xtW;V0MmuH>YR z1zOC%zTWXe04m)WRpiv1fgAx?oMoF9MUK2C07lnZRfxO|0M0RKs#IMyIx&MHg7*#z zqDVkmX%;xghyK_fdx2EC{)!Ljul$f%wJQ}1t_otS^Nbi>-`w1U(=9)j>s!8l^2~!8eqy97Fp3FJ zNM1zbFaF^EFa5oJu%QUpx&Z)@1`xb`lD17sFDoPv0TN?>nNwB`DOH77<^9us9461f z5iXN+U-x14pZ>15FA9g}fAXEk z-oiA*`CCcw0ogvH-aM2`W4nNNWbxTtc(2m6(xQ}ZtF|yArf#Ji(o*{63ZVJ+p+AB^ zP<3sp+VJ2#{OE_N2SAt8t9m{T20Beq>gL&u-Ko{9V_-|G#;BI0yjm z-TlL3ZEE3FNt%y;!hXk}+-90nxm!C04frR&;7&xtSA0nSopor9^wTFzs7yd9CI(2BMzc3K>XwOu{CwqwpTanE3Ertzd!Cp958RS z1c0#P$@9uo4f!!pTWcjsSe#Nh9znk7E%R^uhVG*j{g-b3$X|UpdFm@ZSf2}#@BPu;pZz=A$0LUue(P6l!Y(OazyG(t^?UyK zFP5Lon4)y#T)u(?K94|p<5jFaDyDqiHe6Uq%bPE>c=BadfaNlx6ZDe=SC$k}QP+){ z1`=kqw5S$UU1n^xG>lU=^M{Ym(Z_p%yYpdQCI=C;QsgENMpbE!8ym@+wxkVn@Y3uK zo{Kf6#sz+u#$$gB;T|fuJV^i#B6jw8IHaSiB=;aVVi-`Qo0ZO8^G*P}tI7cMq0c)l%l4x`XRod|&+l%Z-95XzdDfX2lZJWz z1cZOYQ%>5OXIKEGU}CAl@bsL*P$IN5qf#ydLFIOa zKL?x0S@+LH=jqoZLe6<@R981C0+TAEs-{}CP1klnI0cJmljeoqgz5Kz&CT|#i7KwI0b=BZnEBr@T={sr~OkP01<)cqhGqf z6!%;A7ykYM01H1nK5dVEd;OYr960;>tq02J@z5f@?vb3eJ>S0EJe^4u zF_D0UOs$kw$<=TcACvNxm))NGRhDi;fk$3j;PW-BHNWd@cp@Qd&{}UAqg4e$IBgS- zhklsG2_R#du3fe5s?nW>QBYv8XTjx(qB9H9>!veel$g2%0U!H_nY|6ieTu+CpbU-E zRAM@2f7aeC6WUH+Utew3wbAr&kiYY>1+#w5m(&1mZf>4Edv<+&eKvqIeT71CWVDn1 z{(C<&oye(w;RD)GvtG5Hg`F5vGw7>7bm{^5k)O2!kRtC3^}ZDTs(AAaRqL3>9FcJ@ zt0J#mH@WT-h4l0Uzl6mT#ZxatBP_WXT!*EbZp!ZC>Od;dv)@|th? zn%UCvrC+dU>Zjis^LFNBm;(IB&o8E?Yt$FLbvXj_wOX+R@#%w%N-p!>BB1EakUd}X zy#)?Ai2^&5EQ>y-f0DmBMX8Hm6dV;#a&TU~S0MT03Q(CxKQ**vhi7NYU^d z0~l9jp4C~u2#7c;xtKN$;P?OW9f0HLGyR!`2u^J9p9d?6Kik)^pQ{x$&6;6r)7Dp= zfPe1O({C>B{NVe{-I|{Ehpz4F+URq>r5X5Visl(l2`2H@hlBj|C#KTc`s;sH`zO9{ z(i+>tp)%E~s|TmQ=8I1^H6MG&)w(9a`f62;<~SWW9kMaMR-g+oRKcV~&xI0-`tkyl zm-*-HeT?iEU2%l3{DP*85CiaYpP7UR&|OoZsrvpf_;|*!5blrs&I|j&x91VP?d{6k;JN9?{kz9wkNCYcl)oJl8;T1AJ zpAq7s*<8oxJ!Fv-n5JZ;^9;Z6h0J{vrC@3`4Pai7qClo+;dgTlm1rC}+0m$MD^W^c zL>Y@g=RXOjLL|IS#29Luh7@`413`Te2ppofy)b(bCxh)ZkpOj7tyiliL~uws2FkeL zl&hD23m_sYJAD$E_}O3dKl_UjYZy~Eb*BtX<0N6L5023g7p5RWP^F*<{h=TF9l+yp z|EaUm^S|~Zm3MBx-?2a2+DKyM*U&ZRrsM~H=%*H2o35b`f1rPSdSaQZ8-(Qj*X;-2 zw=lB)@W%&;5E*e`%XL@ZT;CwgQx3DI5`PL)WQ$p{1kwj$3eEv8a$6~UN#=3`LB5QR@ zF<$t9P8f6X^$Y__tw1HBIGyEqEw=-d5KczxUJA zzcor}{`l$-RUiAr5r7x}`1JTqUv=tF{oDU|0+BXKz>mi#KC-3|aYXYPFK7lp!8mb> zz$trNq8tc6FWN_924OyD3t8tUf`Mpr7Ie1lWBSkjI5u_X;=#93g$nTEX+hF_BF}Yq zy6@f%b9sk_C^=`-?CU-Q2#FMz#X`BjN=)%uJW_l+-*K`UgV;Sy7Ce9R$^Pk_jms#H zj6tYy>!cS;%I2Y{5z?9^tti5VQ?OKkyR1^MfGB6D9RVdgvDPh<#!p^ArypFTXTrJ; zF7T$clXX*^ViKd2XBm1s4%6rc07`{3GvPc#aPI673Ingg>A9zaPRE1>IHAIcIfc1! z?yJZ!9k;t}Z~KxhRHaDiY{EVtkufA-76+)YKLU6>oZhu*i#dEl`qyi&d3yi|@G#(~ zKe2Egf6W&+@dknbzvfF$H#I;1(gC6?A_YyPmI2+_F+@O%2xJ&MkZYi;;N1$Lksvka z148NLAvy$rR`qpb>REFp2$20-?*reaSY*P(VaXf<&P+ON(<&Z6_-)z>re;IA2=y2nS;?JPr)n&b3x*= zr@_8pj8aQwOUUIP&X8BJKX_gJk(^)iIx%w6UJ_&R-&4}CFo*$G&`jb*k_9uy&KN_A z40~qgu>BAgK#bC5u4Fm(%2ZXQiHJS-!(kCgmmCsG1nJ}i6jtT`_CLA?@W1`PZISb} z1?4!$X{su-xwlY?qN!gK`z2{fq+)t~fKS2#N_f)JxR-b`3Z0|_-hE~Z{f&}uw~?$5(CwVFon zoY$4=+J>M=lQN{qXrszfgfjsE?|A6l@i;0Xtqg!#wTOQR6BL%i7NNM6_+P48 zXI8;?|JZoqwfWkQ)Zy>1`;z*^Fm&>7{pj$0Kf2Q}H4HrS zS%(RLD5%poHzM`y>dvfGU9}<7WM0%#yyzk@5FEEp53gRulJ`hQAzgapetTi%FM9W0 zoI1a`_+<&I-?M?sR?EvcJpBkrB=BTJf+*-h6w814+Jrm=dG8r?w4B{q ztY}%1v4BVM-|==^X+QRFyVHg-URmwD(RoS{tQVsj8W#X`Dtyn#ISI zq}Q9Sqez}D_(4q5rO*!oz#4b%UoKLThf5LvppL`0< zX^JJ=;&DTzBOz)90!N$Ck9~anXpzqQYrmxVo*y3t_{x7_0Y=_=*Zs4XxrQSpym$%= zq81}@uoYDz9`FS6`RuVd);eybH&>gJu_&dLVYlb1Gi$lp_uFJ7&NVP+YLwR(y=8vk zrAx`g;ry92YK`LUi*>a&Kc&vww>2V6gm+lueo`-14!`~S$QtLmzXv;zu>gx zLYai#pS`beaD-A;u^i5_$#MXc?+m{RiB=TO#x9s|CeelD^#oi@*?9UrC;LX(rW7e6 zz6AF&n#vN8KnhAAE&^!~pcEOSvqQZ&##TVEZuG3{%4i}xj$XV2;GkVNe%Q~_2w^oy zrCU=eJFti}otXu&$T&@Y^uf{FbuD|4f-sNMKywwL1@##mw}ly#zZbMU_Wi2sZf+Dr zMA$i8uTFV#-wP2;WnPo+7bcWy(k57hgeT%jSmts{Aw`rby;^T-rSVhm@JGLVZsLo- zunvuX>Di`c*0fO;M1Xv0G#JEbrIZ)}h$vP{OubB$0)VEvw7KwjI6Ro%Xrn+RB8oJG zIVcn&&;?`1?W)p>m>sg8CrO`R=6(BS@vdXSV%z@IHFni5!udbF_WnbMIgfYPU0dBLL)&#s@ssWFn&Cp>&9 zKr*FBkq8UJvel$T#EXX_0-W<+Y=lFk2vk+%94n)=GfrGnwJftkKD4Rgjx0hX5SdCl z=PnxQ0s+U-+i5Q(b*0#f7x^X6PL<~m{`4dwMr(NkToyQXB2tCkl5$|Tyq(CbS2Y;J z!G8Zwn}6dQXRl4y&{upxwLQuQ-?vzDfBPR#GZaX)4zxY#iNuT^`Mv+^mIQz7FFk1{ zQmRNGPdrH^!Yq7}M#{`ESXJwz-Fd43XjNaWHdSLFvfJ(_KS1!#{pqgcm%eZH>A|p* z-F7>;L2}Wr)cjjZgUBb|jb`RgoHg}=kVp#x`2znlq(h5*{_LMA0kn~V6Xp~?) z_Oof)Rk!Y%E`)V};lzTlTDMJWKoD>cK4tJ_IIC$K>@Xe<$GvB3$W%tRZBpGrnsf?E zjzkXK+v}T)9yv<&9fWBd!||K+t3GtPvpCv@NNJ_m`^&a!AtGv3+o+C6 zd&tBtjeyej3JRJ)Lq8qe-VgpC{oFzufBly=->|IMmOM3-TcQB`UcXBqqK|%Q`?bHK z9e_P}FK$Ar|Co9ct)K;5j)M?C?*00ZWdu>n&KWZ>|(ofcmLVRVT)s zFL>@=y?j!Jnz~7x6O2(XW+`u7(n$(Aw-oe3<2X)}1yQ?d z*Xy-X3L?k;a6Ia=qpixLG)}xU-gmY&f=d=t95&KcdLzJzRYGJSnJ3`F9Sn}j3F&R#**PN zOtFW%h2H+LpJh#2gej#o7M{wBKj)1cLxe&!>k_(4jHeMf z-BS?h?fAI6?{%wM)e&@6spEEdIzGO9dbN8xuyC!`H`kkg@`(lW|N1ZMM3^1hX;`Eb z2?+R2Uv?S}^S6Ftp17a-1|^sZ35H6mU9vD^G(FrGraH5)UL#QIImuPyKK_91h3+$ni`Zh zF!ceRPt)YxM9CSXNCS|#Dv6eb54%I(AI}>JrWzJ;A`@gUZZFeOJSS}vxqwM)1%*mi z>-CxxecwOwrDFf!`^<^Q_iy}!zPr1gmUjqr^2Nzj zww9IcVkdHndeb?D7hZZ54SOdn!sR7qh5|NNL9|*Dj{~f?Vn;Qh*c6 zmgTyDwNv^dP?H2AB8mVKB~&-cjo$k4-~P|r&`HOxLPJnZRWl<*oocPYqFw`WMPb#g zG}O~}8|+cv{*CQ#{?&`LvG4td!!Nwc1Y(iVPOlBXk%&p=IU$hD7>|H#HJGf|jH*`5 z{9_-VKKkYJUZxabKl4fV&pv%mq?A$++-$COt%Su}cNq4TT|yd>&JkFhO>4O(rTEu- zpB|kbxOv{PYrNypj|>5%t-9Sb1&cd@l*Vy){Qun_e)~JCk9=_6t^AIUwjY1j{)2}g zAQTG|X+Xa7cU+%Di~Ns2w2N;OA)=4HGkyG>u`C_%FMsvbyHD=V|AT$*b{HgquG-Tb z9p!Y`GfW{k`v{8#bRs@px0yP5MlvZ+FIu4R;$h0)elB2yF#CZ7m}BBoiPE|0IW+AA zr_N0waK)*^x%gQ!g{T==EXKe9+sRFnwYJ=dF7EVk)2%c}Q^q>81OOlqV+@EyILNe` zR7<)gUCSIU>cPUCd0GJ#R0D0IR9ud7Nre;19)YpIx?$)Kb6`hEI)w;S?`VGvzcWN? z(~`n8Sr&mnDe`VEHE`h)uy_%C(^obB#kXIDQqTFif8sy)xBC#P8&Kryb~RD=rnjiF zm~*!I(Qznyqwas9!quDeZjyKZh8eFbO`1>f!;|L)VU-|zUA>fiaz zS8uH=5z^HCmM?$%zx?*k`*q7AWzq&vad5VV-{7#L^0v=qUvp99EMU#)%Xl$ASln<)5`~3xx)72` zk(138lI}W3EKfz@w_2&%%g6AdUagIm4aEh4D0!qr`D@9l-sdU8< z5z$0S6vGQZO6zz=w_^C24OUi%8%mf8^uw>8J#v zLivisHA!lpfb}R!vb>(Z0n}+Zg^zqe^{4)K08BWBqPS-9`d@t)|HH999@M8^Re$jZ z`CC7_P)NV&tJlBjtJiqV_09|T$G+zvP|0H%m&`A`a{t}mc>H(2`B{1MSAMAb$`5tl z`MS0M0QXxLiVS4tk>$SN&6iyIlP-M~@n&M%{Phg;7@1yanRg zPex4=nk&a+cEclyOUmC$mPonp%NLzkbBlonIg*dOn`OsxbuPq5iL?YUqO1^pB1D>$ z2M0dZnj}Pl!YcuYw5S+!1$Zz4nv8;<;7KT*Yrr1f6&-K8R%?AY9OjM)7RP_(DBJ`| z;-Q>TZp!3(yN4pBNqgb2qP!E+khNoSG6{&-omU=t@9P&|%K!Z@9e&|mPlT(hO|aJ< z_xsVF1;u{O7ZC*haO~IX7NGvnd+}N|KlGFG4PSLCM}F=XWmL_xyJk2J`|)UWMVcnI zL0-sQ${qlcMuI8wYiK^Ucd<4^gcJo%dylNLOV>C~rmfzp-zJ6c`f+~su={tu`Q~$Z z@SPX-5B~+L+q-A*sv-eDKE7h{K|Fu=KRyuT_kHs}$EiT?yqNy;zw+vFkQ3$!{5!9> z*ItW9E-tG1Di&VYc8DxQN1+`TS7PKe14X39{QSJTER|j%l7v7~oTQOO(_GMCnZhDL zvcv##np=$b$&!DHsI(wQO68zZiDgb!j9G}}v0s+H1jOW8na4*|Rh7U4DjbiiL_BfO zn3zG0iqlHa(7|S`L;=y)QB{>OhM8yaT2Oj%ohyhEF9BZozyCj70r=Pd@Rk75BrIMW zkZWwiU8rF69@qc)caMMRAJ)gC4~uQP-I}V}tks|M)bdcwkhz z`iW2C8@}rF=AZg!{^9XKC!4!~30SQ=9Le(N;b*)NI7^^_mb8KSqyO)1xr;w_`XZE} zygc*od3heTk5jj50ofgP-}SNSo%`wAzTxI0AAHk!5#ROq{r~H4-f!ybO|6U(=e(|{ zG1bxfJcRH5$Ni@s-u>3Ez52=zo%(l9u2)<4JwLqr^Z#HUSB6p|jAGYG@qcd~-GTyd zx-~{ZEw--Fb#U^IWpXrTvM<-|;+0bVk<)@G|A7ES%5tlz2Ox-`%X zlz>z(K3pNc6X`ID@U{yGg`i|M@Go1YC@52wu7HTNR;p%UFQP%7AOMprqOHP!2?Ckm zT4)j?A`KP7#_FaPk>l}Lhz`l`EXZ`;EvQ6@1pjE$5rDSts!Bs-91|E31oI@Hc{g8o z{k6Y0IqUw!_w{W@U2B}$)BHuk~L|G^1~;A@~?4WzvsohKMdPle(R5a z(*F3LdG$5F?D|)KN%w0$LU)^aAbjt(HLwJ<+zpGF=4(L~vI5Ptdb zckIXh!s8dcwf~L3qW+a%cv`ph2Y=%5*(dv>KR7YAA5DgZ{Q+q;d{Mu9v;5gHhwVB^FjOh5(F%2=^31v#}K z03#Rx6O^h}t7aH_Yuy}%LV33w#qgO>i6jknqX;Pp0RGy4b_?LQ|AB2|8qY3SM!-O2 zs@1yNZnu#{N{GW+CV@bq>vUVM_xr7Na&yxV>Fv`IK-XzgHM`w0t8xMEZf@K(?T-i0 z%te&RKg-@k{Uj!fT%e?L!U-dVFDySUq#)RISMbxp9%E~QRkLpD`f>Lp#EMjir8vnu zHNYCGLIuJk(>@&ULq(TL6)dQm=H}*lx8DxK0G@$yY?hEhxnwyhlzfb(9#bS}>(%CJ zH5|u%zr9^OuRDEzf7oxLo? zPQ_yYv#kKUSzT|gH*Rvpil>vaTKoNq6l|_!nz0(aBRYdYcghv&qjYpmGcYNDM zu>LRpKZl;J&&gbQ?uc0A+4DOnJl)@qlO-sS62i^;>TuYP5~{tY;ZX3ArKHay9rbhs z#iV$)uby7emMSs~FAz;iRdA`?S$=TId&2D5qONL8s%<*BP;ElpUEehwK`?InhyGC@ zEPR}H>%IeV)J3cZf5ff%PH60Cx0f09!XiO{Z$B27fz+hK?)Dph4jVH(_A zb8?AEW~@kyAH&cOL!Z<3QoIsE=-c5iDm89aozk_l{n&>x(s{%wfF?P7T{zb^*%!j4 zfUrx?A|fuifXnD2QH%JY*x#_)qkInFQe^H9dmg2aui(_R z^ziVsD2Q{J*T`ETQ8lf*wjK_{$RnX04)(aWM&bI|x|xmx4@63#(v`Af%q-0fzWMA_ zntLoKF>LwYH(e*npcEPfKtLKN&!Xgl*jn@(c~M+=V>%--GG!KL;af$ERp2apH`hZ+ zWJynA`HEsT&AE14aL-~dGv|^^asT348i%!3n#>6VixMP>0K{C|0zLs&JP@)xBu2_B zqKqoyt|kdcf+F;81f;192wG9oRz!gEbYgcXy0_YN(=>V;gK;S*OD&iE2^4_9d+c^S zqfdfd7TP4vKB?DKFe1c&WJ95nengCFo&cJ`2tko%=HOhJxiPUqW@+XCt|Ad*v{7Eq zgjkNCm<=ZJ?2OVy`PhKpf}qI6fBZ7>T7*52^g|o)^u(#69>0VY4t_X4o}<6c*y5(WqJHyOu&E zlod%_yZ|c20ph8RG}-0dGWF(EUlNE*c^(1?!L!$@lKBBjREe6_vg>L+ST{@#0`JB8snJcXo92o} zJJ`O61x|1EY`eCT#vk@W(IHv@za;!98ZbyWm^CwvD0eGSAhLncI`Da)A|-2_wKqCE!`2s%mAuOD4wIf}PqApVG4N zps}O)H0o7<{3!{Klk_vKbOaED~W%E?5FfYj~nZQW?^ zgnf~S+WMR_=T zbU-X(C+|I<4DIBXvn%V_)7!EQo1^vsFNKJbh0)}~TNBHwwrQ1CdH<1zzO3PyjWe`fqlLOhX{#9MqO;vBYbzK`Gkb;VN z`Z0QCF(a8El$I2qep}8^kVat!udl9~s;O%&ELo$a<&?C8Kx<{FR$>U^;hhLkI8QF? zUZV{4{dlwo@3?L2+*Xvw@&CkW|93iqrLdRclVqWX2aZW-?Adz6YA&H4<+MtID5ONl z?T07t<@WjY#$0*vq^eDKy}4f1ZFP5d{nqXCpt==w)C@6Nk`ITT9j|XT*WJ48TXxY( z*t$a)^C&?C;rsh{U%h;oMz>ydZ@=&Pv%BXySmkAUdH>?Y%NLUjp;F{HFjcD2>+AL! zA*&b=5v?^dCT~@WnF?>5RSAXFEGw!yQbwY@R)mU3r>(+?W<9%R2$D;HL>;_%W+6m? zM1qUWr61=nrNXTgHv4k&;C$ZY1T_Tnj?01Ga=P{KONax5tJd20LqST}VsiaCzLS?)|%t=Y?z zXCOvch2&ELG)OSG(GL;n$wPOzg5i#3x2K;VH|>$R$SI|9N506bOrX%I-u zIZw!p)@OWJd{N9#xm~)L@O36iWce8-i6o1Sj4XK@0N^}NqxUYCPgSG_h2mc) z{+b0r5@5L;*_q&N!SUst0;4N!Xy}L9R5_?41bgNJf2Bm17`mC_a}k3nA}h0u!&HF3 z*%8Mc$9=CVR7MZe6zE9|fU;#+DG-$HV-2_W->F~re)VHN=af(`G9-kmBO=&g9!g{t z0!VV$m84-ST3Q~GZ~E!!31=0aWu{fe6J$j!d5D)ZgF%!8g`u<|P*YdhkRKg8fuPcL z(^Zd;zSfP=>M$JvD5FHMUav^4+%#?XJFRNZUdX2-jzLTz#U=_7RdA=^6EEB^d2X=W zJZGsVpyRQ>xw+C>ImZO5^=h@MAGS}2@z}1eYi&Xh@b>r!FoX8vfka)cuT4ecb~0Uk zcYS^TXa!89YSlm~?^vjO7e!MPLC$@j0U*U~UjP_B)tXE0?qo4mfRp2kmq!5<>DDx( zn*x#hVQRWnS8aOxB;YK_sCBBw2{Ra z5bPtV!R5DUC7qUBETYj=v4c(_0^xB1h*;QEm3W#`v}jW|BIMaCh|Se~;~R;9rtTm- zP6H_M&@5g{AUJbBC9&@(@y_K>oJG@Mvsrs~!*R^vPhs8vAO5xVM?R?k>fay#hrfeE zI$ye8t4eEt+f6mt!S->u(Z?a7R8;WG()INfgm?QrEyE%#{SIT=>L=7z4`6Grupr^1|j|bPk(R!T|ed&WPkL(=U=YB^=t2NcKzwU zar_^CU<9en)#i78z5Z?gq5+TtqAk_D+dcBSi>}^5g#N);sqW!xM8E( zYl4-@afZCv2uP&b+x2a?*2H+<```EYa=RVwqplC(lmReMj)0>OY@5#CNS65Ic@@e@ zv!GKz5qg}Arzm1#l6+mDU?7DP5VJVv$H95)7vW9m6$^YpiOMH@0YN$(sw88aq4aO8 zlUCFSK1V2s@GLq#%L8Em3Um#`_8Q#fov|zZA$77$r|JcvE|M*Yuf94ncEc^(Xj6gP>uFj5n zikAQ^Rn-`!yno$xj}&Qz*R-%~4CnK*9J=*AGgszvnHcX}NZ}==UsuDqpZfc!`={-b ze|_fR?M8q8T`&YPa9rzkKlGf|VNZ%>4NHaGYY5!~J1Tik`o9cYV8V zt482OP}i*>oJ4^f03<*<9f$y0H@EAnW_4XZySu&Z?h;$aL@X&aUDVq7BSJ=-nE7E2 zBADr%)`k|42z%#kia=VB9fD5Pm2N0cZk{d&FDs7L^g5;Fw$P1Nq7pJQe7U$?8BJBCeLSjikp5IdmClT0qxS0Yu{oiW5Lt92s>wqlji!gEYODWp$CNx|hs z9CTd6aWIaD?P19JwlbB`bU5}3)Lpe?HG{P#+q=WCRTK{jB2uKN?P_~yET&8lD&7d7 zBU8Z$j3PJ6H1{|8l=F}QH#p~^nTu`$(PP@9kZZ;Jd$NkZAGL{pO zR&g;YqX@@-1Y{V8&8BH}H?q@IHCbm7;)`Kkrs8sdV-P=!3 z+oLwbN--c>K8S*aX1sA;S21kZ(v#&X$bHNRMWxV^T(n|FE?R5HqAYXBprSN# zVwM<;q!cMlwXT?1z#+=OSwG3RYF9>S%kHcTaj;3hWKeqHzLFNX1kbz-2tx1&-qR4I z@z_t*+FWf`LcH$>BGOcaqbHO`*ue%Z?b!kd>cD6K*d2GRZlbYF5xX*%cJddJLCWF8ZGxIT(jx9*_X>a^?Sos2NQC>|Z8oM>-M~ZicZBc` zKm?i;fW{~Y`@uduJSs(A94}Zr<%cKBK>~m?gP-;^5qH+rdALbw=i$rJA?+YN{J~E) zk{Dr0b6Cbf^+unEB1KB;_F5kwZLoV=wgOz=+>ZBhy;|1|UOc=IDDkWSUF%idZiguZ zyD8F|wC71g!rm^)z8DM_WqJX?3ShSQEym>n!PaX%TgUx=@;;e;5|hqpJm-r^D9`)F zxi8~K5-p?Vp1UZs?8t_a_zMHGafDRP!KsZ7(Zya|v?mFV;~*@_pdw0P94(6zh>&O) z5jb(N<4S>3KXP9}s=hD_Q(}h{YA`EFB$f!gANwR_ynAG}kO31A9Xsr{M<|$@0z4on zQVL+DlyI_%0nD5=^EldWRcopSKOmS41*GVz-B@b}KbD~RJd)!CBP0cwr!@hAAc%v% zT$l(9|FnA`(hzaZi629Q;RIE!G_ySIo;-Yt36FIZ!y96{lCXjih!3YAXM_Ec9R<*; zx>~PxhbIwVn&9Jb7CxpZxD$!vZr!mh*h|ya`vWyqs|-f( zf>8Do-ydHIB<2H9X3^MuQ>~QJ{df@ZKsXXK>v}S5qNk2+sFRyt46Dy(xWWK_Qe zmEz+Jmx_1p_J?3rF{&yw0P!3-!y^x7GV80(9#!uKPz0d@)vj9{Xz&9h)Q)CkL>m1U zl9`pt`H560!j}Z`_Rw~^SUd=aek&Bpe8-!VCNi=35{oa1nK%Xpq?6;{fen!(L@gC$ znIPy!7ARB%6|m$PtHni^;7kPMk(?qbLBS%mlpP;lygHClfQaz^(BIr`-oJW_1a9=b zI}j-{G&O09}V>@;PtgiL(@%Uy3m`(NDFO}D=8`o0<5Ak13p_U7v8>0xv($@>}aCe2Spw0r&=3>gPMP2P?n zwTGc9=A8Jz@RfEW}FSJCSK(Qkqjssh%>joeN-I`7-t@36tQ-rdS0n2`5)Si54 zX*W01G&t?OuoD1>-PjM40Kr;PndlBws;X3ToDThds=7Lc+7nHq+YMW`Qdc#gYSUe< zuWoN|uexg@g|vyFC2isk;+%_B*1jnQVR1uD7Y^JUKAgtkcpRieX`y0LdK&>PYJyH$ zL0YACxAjRU5^fq?hvXzP|09~`$T(7%o4X9Ofcila&beqUZPrHZD ze)fSU)J+qLC={NJqKhcpKjpQUrKAloJ6)o~3o^LgG5?Yey#0aaZ&8iiVaM=9&8k_4 zC;MT~5eN`LRkeY@G6PCc)3(~}{lV>D9bN#mX*UEVgin9^GXS35Jqz#Ek&8GFA&w#k zRS5{!DnoTusYbU@2n7H^ z%GAb)4lw=LA7e}pIGDM^slvJ7W$toVv6A_`l)!~FMT%Aw7psG?NL5u7>91B@b3BAZ z(n>*vgF3AbhsXc`QPnn;9eFqmo3?B8s&|KVdnMivwnyHEQ$eE>F3$2G6m*I%&*&eC zYgI&uvcPfd+~|-5aSH#QSA1A03`bxE)qsR_bm*pgk}*Oxo$hzmD0Hi4+zlZjJlUzD zc{seenB|Z(E6duTIUOOBe4Yf)!_zPj00mND9_?hE8xld5Dm3j)7~WgdRa1G_)y5ue zKOGHKUDMVzUFj8D_wN0>3>JVP46(788-zJU?VW1hi%aN4*UYkHh9v;tWqA4O)mt~W z%BbDb_UQJY>h}8CsxjlPxMnnL!3+^=5RD&@N{zl&&xECvmg1vyO9htdZ zuQU;ha46sx`BRW^Vib-dBH}%U-g)Qk7>rL`!m2n?rBn$1i%Txj6B5mGMhJje(yPpM zDET@;hvnkp>p|G8q^Jrw)Ppu?MMI8;DqMLCnH^NXiUSFRHB6 zXF}a5@#uTowk8sfGypgG$&ZSZ5GvDXqu6;OST`;rlW+>lG5`aCvcfAzA2gr>MNveD z{qg#0qm^c6568aV+_b{tt!J=Np^{r%wa#*-D$-PU+PIZAM27kuP0p{odT?V`w*dE3 zPeu9CMIUE73G&H;rKu;XlO(bumQ1ocdoO0~Ac7zxNC?DWg^D1~yG#>Fi<<;QiU`8| zWOtoy;^+htwwDskBuO_X#uE@JLlujI_?e}Wk$maAk2nh=NM%Pv@#E7gsGvC$NLn~$ z;u7!-MYOIvMcD4Q46j5F2fN*lO7Q&oX02Cye?Z84ROGyy!O?;>5nPKrmVM9E@2aUCsf(wW$=yXLzE zfJtO1I3T_t+?c9i%yA+rZ*wF86QqL7B#H>e7yw#TipaW=()J}+@ecu!OaX7ANHBF;u>%pxi5EwpGyXQ$*NErJ=Uuj*F5oVA$KZ?|wdZX)5 z2qQ{}^O=iI?o?+w?Zu+SHT)SQpo$*QeA+;i;tOSxazQ*~f^Vr(Qir$mEIAh!^DrEn z)pf1*S4X=8DZo^^ySi?)27B4>_M`73YX$kCG(!xTyW1PBF&_J;!fNplHL$e z2-|xJ^{y0>GKwNJ*TBp8M@XFYZD))!ZgdWgK%LpNb#=XJAxuWqRSmZnh|v}D`K^+; zJn?=O5LpVxl@L)wl*UUoE#!V7+9L-i$?2tk_p|S4r5XNd*gjw1b@h6*Q`g)O69j&8 zo-Ig=c%@<4PDf&PK;`|!X&ch_(|XlvA{T{-kWzKi+Gz{|nwh;5JF%UdbD>6-kfJE1 z1L4kA05asIl2_(mPw+{hZ{un?!6QrL8}H+^ktsq~6OR?qC5nWFSSejqij+25JMVFR zUU8bPBBm)Jv(zns6j9r?5P0XTcPt*jG})%DjI^X8w$2=uEUKi4#B)FP!K0u_*QVB$ zB2^E=G`T?~E;*sj)%BGkV&?r}UlyAST3Y}LAvJ>Cb{jtr8b^y`%fgB<*ui=oiAE$~ zFCL^7VRVPlQ4;+u4yIMMpZ0c-0w*RSQFP0OGG|GF3aHYx^<#*g5XqborAyvrNN#2( zIHGk$0Ky>Ni?4`ClA}_@3K!4Ez4m_CYjxdT)v{e5{N7-FebWl_VLP^M-L~Cu9F?f1 zY9KQDG3-e#k1y|^o?l;Ab*&C5V&Y6npRGP1mGDfPtbkV3_0=;7j{U*9AyvjA0(v{F zt~R8xd)#{Aiki($Ls0vNu{OH9hMT7F3QZ&ca{=)Zm*>7{P({iK=eYj7iK0^0q$XrR zs<|~vAIEj8!0ebX`2H8)9SKlmZf-kc6aky}ZN``5ei|fh!{yWaPd}^QB1MkFfyxRb zT5ABNst4aIC`6pZuSXgBu6uta!)Fq4q<~ChD;IxWNEr!dYtA)XgMCDqS}RmdT?15WHH>bN@|@nJG7v~2z1Rd1 z02c0#ePt?B8PgbV{V)yAPyT2XkIR+`$j>5oH3iL=T{=Eu1zKLK#N{XXMkhV$MMNQn3Qy#Oqpxm|Bs zH&)C%x{*PK8ma(-b*|LQIq8B()w=686$IY;Lw{sA5fJIkX1(3I;Hi~a(U6EJMN%Bj zlG!3Fd=&c|CK^R1FcAryV&!7tk+4GJ?AK=Poqs$&JX3e=x;Z}eT5A&Qw);`~(N#*< zBxc=RwXIf$m^V)k+et=Eh6T={@*)9kXRa>x1`B+ArsY!{jfk*w(|WyHZEhj(j`zF$ zaXbjvVd#fiL1K^_DR!`<-}$Evu4-Fn*=dX>j*jy)ZqMvP4Vg;(AkG$wt$d=ipG1yc znko=9c0i5cE`cbh==Sp>@a*6D^d}Tmn`*VWT3z4WOs{xydpoYLZ`Sr<>^6;nM(0B% zIT31V4ZvuF6zo8NbAFnp{^$;e$vfs;l%0zH5sFV|3^;Rf=xmDb#L2fHq>x#`ES2(g zA#r2z(j~pp2B(~8B)}4#!IjaZDiDpsR8>YR%t_pcRzb3&Fn%PSPGP!YbW74_d z9(Dj(4}uW6aH0+Jo&-b)s3CTjbY)ayOxk@LX0Npge*UiOytCHDb2E2`ecZVd1Y)#O zq^$Lsz$LWJI|?K`6}p`>sTeNEhW&BZnyzk*h8p(0LbY1g;@}-u#!R*#0ze_J9;)ps z*R!>*+th8<_U_m<8%@L%yfl_)>aT{UgliX!mj&k`U50p%Pp!{WNNeWkph!5B#8%n^%)+V?r6cNJ% zhDc3z4B>K`Dn;bQi*T;}IZG*0M5-cXeGbizS~CfULIdQ|rT{^lSn)~CNfc=5qy-|N zYimU`^v)=yYZCDShO`7#DP^>B79vt9L&Y)+YqVRf6qNT{W+bq&JZ?X7pb z+i%mkf6-DBdVYO#LqxA$y^I#irCM0{_7{pGmQBqQ5a_?%@9%D|@7`L8<>7GjG zT^XvpxZucbstSywJ$g*z=-Z9aN9Dy4RiePw`NX{vAS@&TFA^dW7L|*kAmqg}OJvQ%zpt;RM-(o=74@1 znyRbY=SJ&(zn?s_7i+Dx-jB{R3&&|yvkUL^O5Q`tJd7nWNz+56G$}>H!Vp_r1ks=W z75~xlqx>`O_R_ydrq(%5BZ;uo3lXK%deagqh^kvdqC7hiGN!6(t+lD^T0x1hEJjL| zs_I5NYx9^EOphgDvdJZ^-9Wd*3(h*`xz>hJl`tkhXl$u(u@%22J8K*ZQW#jSYWeQUQn@ILdCR~ zKCCde-cDRWKkXhTo)pNDuT|5n8}fQpue|d{Rl25Qe+0pxu3J40gBK=MuUGXn3^v5! zfZA$(cXPX5Z^&!MQ_4k_3tj4?!5>SRDv`xt^p5`>Q zEhj5HsXxgw2=ge!v6DoDYPEU)+s}mEXFvVv-C>$WKOQYRfA{>Y&3Zi!J?6lo!fi(L zzd0x-tBMO3UC6IF`)$E3h!T47u37NUQ#QX*XqgVLz{urV1q2vFN>xP0@-z+3)Zv)5 zD3aae`eSdMC#Y4`t-DoQb(*U98o$uV>77My&PcPsS83Wpp;Ai1ZE}`sTCZ1Cqllsm za+a%F6Vc>skONAoB#raPi9qa~m)Il{djvaO7?skb^c+K&!zhzsWhQv;aS%hKz~Z*Y z?dUD%+tX1MM%Al!HTeFxpPEh8RviQ&WsD+`-tD)?C+jCdRaNHp`sVib`uX!`jj2I! z(mPhvPR<+l$kX&-YXM_=< z+3g3OfAI6(_raU)HpgPdyJi_FA@WfQ!6F1ftp7*^4laWLV4Lpq-~aa5PoMeZXI{KK zPDeK$od`r!*EVg_JbQjsAok^S7Qe?$2u`;f%N16pam0?rKWTYu(Rp+7u9H6t(G)1+ zi_rM6!QqlMtEvJ}8O@@cn?!V_&E%{iVlR#@0D(7DlY$+&s+BgiomeRXXXnd|rDjLN zN&hZN$5Wvr0ywt&y)~q?(m4v<3zIV5u@@JZQW+I%G8Zorz)mi_(^S;dwH+tN!F3CP zkfE#1#!kbrw}8}5TUXUIj@C_=!DaIBP&lkQoF+wjwOX;r&>tbuuEFf8s=2AJhJKQ8 zdU=>rO>XpQR<$BU1aJ8;?2XpUK6aa>QX$Jgl5MAm#G}N?bUOP>{SzZOMthu`AO}H` zIN1B`JrO9RFv8o(UqA2Iw*dNG&tMW#CY<;QKtX8Lb`b1#`w8y(`q^r;>YsW|_1)do z)LU(co!=dIo?KF2X%8?nMEotA((-L*alk2HFTt1)`gxqThZozJt`zq&g$^Qgq-&v8 zH7sIz3a~6Re&q3rniVw%>A4_iq%MP~xxHB{f_S;UyY?^a(I01TTY(HkvNL-o_dMie z?q&gdc48myce|(Es}~Ov>hZ-T&cisiO=C<{#$1Zjd8*@Y7vn)n03m136>@H|37Wec z;?StPb=fXTd=sCZg$PBtI>)vWsSr8hnX6hG(+Z38acdldVL}ZIA|_a#v~QW&vTdoR zidxf&$T&?Lv-L{hSac;vd8Cfbsy6FWnma0h6YsrGkd4Bge6mv(;-tv?oW~g(+3)sw zrD?6|s;Nvxq(peX+jFRvL|PjISODI+s_W{?2v(1ek602mkvED)3iduC5w_N@+NQa^ zhKN|dKkgZJe>gO4+pTJLzPCM;3b@gemXwXL)|s4clO{8fy^lYs$w{hQX1mC$4JoqFm0}Dif00$ zZj7H?-PLPZZ;ww=@&I9`V&^5zaax1{t4Hf)5nmI|5=nd8ygoxEjCe=T%#?Ixz%>SF zVT@9vOhMoZt|a}$d-jN_;?BBxD@asT+BsooiO7i$Ib@E#kQWxCwev*? zEG4=Hc^;ByGhg8BDtJFU6lwz`j~j!8ogc?BuY>Tzc^4NIFKIy_fhNt&`@I#xWPR8x zDggx3m}(uw^p`m@9yslxBuGN@W<1ZU40f1o3VzD@cmZ}R67X?4uBdHSb>+L9zNc`iArV~ciYP*3+Q~a7eh@zvn!BWwMx{x+ zk?+>eh%gKe0)bxDo7?BB7ccIuI}#Z{gt^r>&+o2H0{~C=yT|@s1VZ}R-Q7E%`s~zO z;Sh`}N|91wrDv@qk&DDzJ3c(zPtKnrugq1YDxfe^X>l!?GA^$r&t6zxMO(RbbE0t0 zcxYZqOFTqLh!CI!UI9kySecjL*itZ63II57#xXC~6 zb^=#bN+2PpL0CfBg#J|ZC792bZ#8q zy?>EtCIM4Xk4sBqj>mX;`zXLELbx$ooFIYN^8;v&Qh3{e%jx< z)pc|I9aZE}H*A$s1EH z3VC{ZplwK}RLdok1w)wG2;?NjVa@)US%zjjmt1J?b;&&Lu&-Gxx&>WO*jX1aCX+Av zz@eZ})ybQaa=dX0tHN{|Ll{P1ld8JLShn61L6P?4Ri(UjD7{a4k$70^t46nV+fO}$ zf1cC1T$Ge-iJ1_Tl_2HyguUQNJRSkwds8afQxL3qSTY*r_7(w^@5@1&-kkPt*FU zet-QIu}p(y_Q!E*CbR9wclY;q*Ece$;b>Xp{^@YDX*ZkpcpMYz4&p4Yr{e8#UV@RQ z6p1rOom#b){8j+5S)<9U$MY@clBI+-q81vm_=O4%jGp=hBoQR|PhfzwR>suxD;6!5 zosbaT*wmWA-g;#S!s4Z>)v9X&c=0GAL=$m>l~IXqN*mPKsq_(D3EcU zcBNF+npFTV;X_L3tQcWTc_^e(wAKXIJF}Iv9orptyZtr?*Cq{?eG;Kj8io-<2F=ZC z<44&Idm`f}nfBaN=IythHKq%+P*6r|Kh9g}dGk*xynrA{UYsnElj)4ZqO^%iG)#&% z&Opd5u-2)H08NB?W0)O_1=Qrcsg>4veB5oPt##fzIS%7$Rn=}a9PQA@nD68E2}JAF ziXz$z&b`^wk}L5oaD<%oJ9oa|t-?}v#bLk;y>PBl~E2<)p2t<(~ z5NTr1$|&VDgp4tkClLZ=0O0rcekYIxPJ;scXV$h^=)TP%n&IwnV2H<8|Sx-*SB9;_e+xZBC^hyLz*b=7X}_hXoIGD`X>6K_`F zNw5Trlf>jq;AOy6(XYfid9PV2)pQ$e5Bs;eyD#|s&ttG1?Dn`9z@WRi=|sds9{c_1 ztoZion)eS!0jiC1y|X+5P_d#vnYsf#Wbsk%G)klLQbFUwl{M)+{Jf|Zk0yho6f-gB z^T{R3T~Oq9{pm12a%c$QB|XMPjs$GbA7=ZM3sf(kQVn5+ndfh@GD%Kk77n z1TbKEqB$ufy%`}D9c*QAL(R2m(jg#(VHh3TuzRUgTh-b~t28<9hcP6x&qDC*Y&Mx~ zB*`H>6D!GON*P5e*EB*gR-6J#0z#q#=!BR;P=>SynAnS79F1Pz9w(YbX|1k@DiacTCVlAmF6=yOiMDAbOD0Iuwx}ISGom2?q@b95FjlL`8i24cy6ajX`)LcH zGn>s-t&IXTP?(-qwP)``wxmEvIp*2~E(!rp8bm7B zxF$L2(aCQ9R6^t{TEsyoN-&L_knH3OO_e@4GtL(8AX6~uslX{fUotr%tF@$c0<_aG zI@f05875Xpsb6)3Y>ecnlMi}Ghj>nysF^&ezj`d3I?hgzn(Ce!j3h%ynR8&2?>q0aR zLn_oz@P5n?g9XpuetXq5$K%uetEUvDLAf$cp7RCJymXyMW2MIg;sNr)kHy1A-NuUro3CZr1IQNZ3kd$wvTXQ$7;`!2~6 z8JsJ=^Q&O#B3K5J)*_wUJmVdCZJR}l5Lv{JBoH-guq8nyX+cSEi!@bAnc6@Ap~}?S zC_uDVoQ$Bsofn!534f(RP5#$;jXLj5rMoKBAMv9dolF=d#JNS?s}L(eAu422Bu-+n z!mzVsvJ)#!tFG(&BOqF9=d(bGJy@+8qDFve8i#&Jsx?Z%7@?rD5h9UlKCwkaBot~7 zLX9!+_fP1qp+wk`3#LSsvK|4jkRl;KD`Jefg&cErQC)@}<*G1qya*L+kR(wQDap1a zX<~`gD9(CUkq(h92Fgl~`I#9+sp{_T8VoI3CCA>s6&_agJY_=Zv02 zkRmZ8%;-2C?;rfCU3X2jT0evE{lmSrj=&H5`*!MjcLanW*7`~-0t_jwF|re|fQ+sn z;+#u(7KB(^tL-*K+Z-w%v1&0#1>(LeO|qY=_@pF!bQRmlduBU%@5aZ6EdibxvcK9~ z)u!@(0NSf&y&aE@*2<_#YwJ7#(4=Q16<=c%0noalQ&VZ|=Mq)D@uJxzTeg&#ApwS@ ztIAA@Qxqc!#)PX!Th{1r-G8OD=}`Z4bvD5Gcj)B(YND zbm)a-nSobyF$nn3s)xNCaDT-lz?w;41*6l z_Fjm<5{*)kc=O_(iCeCSnEblv#KL=4ECmY2B!M`1frOKY(%p;f2+z~;;8vZP1~;&! z3(Wz*@p!zsUftf^zPi6h8W#ws9f*7u<8H!AbZ*%0`t6<+RMl$FK8(YQ-H-W=eCYSj z?rxsH|5_}VF!C6sq=FE+&^i-H2=em9yLWeY-uKBP6N68daJ>-zuYn~c9+`PW2t>^6 z**h!j#g2}hNZ5=e3;5`VX&a03js3K~X*)Dvac-J?Oa;)5AyR%CSh5O{S1(`Q++0K4 zjGbn4=FUyXKDGm|J0pSuxD49wl4Z2F<3p|XmwY$+e|Kw+G*GtQ5`53h`~A8f99uv*u3 zqeBpLi0k&^goQvX(zT6{4E+HiUz@#UpM`~KOs!PkPr)>mBQ6ISj{y*F->`-TlJ@AlZjCKA_)=)}!T{ZNB4@FqgnBrFD zRK6yUcFBaX=j@#0PzFr^CS5BL9EV=Pv|W|Y+%dZH%$lelM}ZJ&0XUtm8hE5ORi%to zll8IsX_Bav{!SD@riTne-w*vPPA?IZBUizJQ_@i}#K4}=qqqKm1G!CIgC z33%#v+-C(Mh-y`mRuKr4iD~jBLdoMhVX2H3)7DcE;AJ7F01(vG`s#2Pob-+zQ$=J* zTyp=;j1=Z+@P2J7trYvBACkzE%)_RwpWohj=bs)Qt+Ub8t)LK7Y;xBZOc^-@EYo2c z(g=wF>qqb0^Y=gN57Wc;frUxwx8HhpIPQfoIfMHQlPNnEB8T#aPwtv$yPUJoNkAjm5H9kbf2# z3xZKGwM!F8>}~q3^yX07TM;c9DWFWea$Us>(uVT>a@kL0;)KChO6eHeN~D~(G?A$l zkID;&Q&R}=)`LJGr7EMfb4~&a3W*2JRmAeEWPZ)5IW zNnzDh47=SPO^bC~?FL)7s%@L?V^543HBv-0-MVh7?*8FXVs+O@uGe-hAzmcvGUfR5 z;HZk{Y2Dtg$755sS|A?oa)Sf_o|*FTDw(!<_z8kOyS+0?n_9p1_FJF+%%_nv*}|aG zl%LP{yzHp}%pifkf4EZU!cQf>f}L$xLdZ)d&hQS z@7Q}zour5wBuz<46~X)o<6naJd0kX|Q==a{t!V#=OC0aa!4XPOKtn*6A^ zHC64$A+Yx_^$|vpsw+(bT~|;QTVc--u&_kfHg|j>RSI%Y3a+Q}hSJVQAi(=^nxv`> z0og|Ey$2a(Xd1^*$<&Yrg!Az`=@njF6eH=R3`mi*D3HtY(Irw9_B zPm^^jj0;H~E{^h4a=^m=xZ7aUYz$ZqyS-z#z={YWI8II-iw4BmN@)O5Jj4e?G{}qp z?596da`TDyI$tAaj)Z)t0ATUE<0Fm)kRoN>D9of(-PHXs2F49sF>e(LZF)+GKtzFv zILDs7oy1Mf`%sW8k10Ez;%b{$%ZWNn>u-LEf-#!CJlx+;)+4KGB4KA8SBARPD$0?P z<1d;p&geC3=)wt(`Lq1EEIyJvcF8borb?j(=Y5Sa6%l#ocs8)p>A+7wI6z8itzzjF zfk3KCE8T{bAb?Ww^Tazupm7=v8D*6BF>ku9ThBcCX(9RYz9o;KpxGO=N;ZZ~ZkSxK zaz&*aovfanSP(=+=|HN*oJ`iLBzu&i>&-?;oEwJT1wXCQSa%x{zuWEsRCTjjt%P~M z-!b#~n!I$q#v!kWpcIjZXr(!vtqrvud*7q#u&R0pL~wBXt41@}$`FoZX|HrswF8fp z(%w&LRUxUpIl>p|k0l>15i0=@O0FUzu-K>LJ&vT3pGLCKT$q+gvWvP@M2OrM8Iurf z$C9=KDc)mVj~R@dBDWF}1|wFM$1$Tc*u25Qiq!FNTwiTCl&zh2=cgN{_^v#Rh>XO0 z&&<}coxJz#T|BiX@4`;lP!cs!ezRm&B4k^*2zF18yQfEF1%r7zu-opRJ-cR(j^QkR z-ZSF#{H3o$VRIX^DIxBEPGq^1bDStS=jl1;s>*0%*cN4(3o_(@Et-2nN-146K-^h- zp2kV)+IZ_NPar_g7*A5g>AI=|Ev(p9H$?D`O|6w`hG{?+bu;XX{fJ1fAjJZ}%pxWl z>L^qSLWqh|M5sx&O?3{p-wkLG6sZ6h*EL%75xLfX_? z`(XPFvV$UThQCBWL`qi#iit}qNuy#3E!Xvhi;&EZr#I!yHhTN*=S|yq>-NWE_T=R; z0BJy$zn&~DDOwE$bi8Lfv2)&AmZaNqAvHSFcao@;cLn8Z3j7vkVRoQU0mI|yNIif4 zylpEH-t7-d1eQGJ=Ti0}nX+IwqZOU@st|xd*r9kR{Sn~-1Oii>MbVm^D-9oZeKc8%kYMIy;<1_o{PTn@Zc!kPnVZqT{PZ|N1B}CAy4_se+_he;b#B@@(pWbp8dx2m z&{Xv#HoLE7B};CLR$;ksV_Ko}fIgHdBcS)zzjZ)GUrUzXC2+9*J_S zsv4OkQEVb>nwd^By;10Mnk^+oMpLK&Eu%d0uI@~2D(5^5Zm-u2-`k-z4O9<6lb+lN z4`?`X*1@dMHs)#AlfqTkIorEQh(Ma)C4@I*rwoy~xw)<@b$|cL6&{ugTuRaGaU!}S z2?^b1ebsfId3OxQEhkx?m@vfbJw83X@2zL>e%B8X=R|XZFp)|$q;tkwUZ<`-H9NjR zB+U2suTD(b!ewpZnHz-J3wy`bc{j1Q%*iE9Nc$lwS#(}vGsBgHi?g^O-WhUQ{4Bhp z0QmmlUXifRSg&X*_vSs-*20W(O3%!hMSMUuy30J|G=M?_#+w&;dMZU>Wf3;-tcwk4 zwh$Acs!B-|B~@Igvmgvg9|F=^i-)NVQN`9z?1E+^0ckZ4DE=GIi!-{?noQlX<-ray z3X;+k~=T9oX%5sgOXR z6&YPh)vWGB=FLI5EX$CNphH99i^Uao-~@uhw6hZ|2vD$o3frsIv#MT=_P`##)@lGy z0q`JHH7QkHHGc0HK)0%P(_}i@tkwns8lQYOoyQhLhzaThwNHd`?O?xitfB z$OJ5vUC>yCj*c5l_TE}QP2SrW1_H#4gEIagN3uxbusDHd(pK^_#djBnP;zcs@?ilh z5#i!^g&4D!I-c8mtq{q}6&H}e@lL#WgOHYudt&~+v+*GYF zdvTnij~3&L$bu047qRbiv}$3O-|cp*Raa@_+h*)bdpH8BBM@}eABI@uD195f!cjXB z0ZOYFfHXHU6DH~93)+Z4B*KwJfnp~cbMLb!G^{j_{gVw^q91x=YRki9r|YKES7TK{ zLBP;T4}Lfvc(bm7N^2p5>(xr&9uJ4j>T11ipWG2%pw((sd*=K5SHK*qA15Q41JfCO zYEB54`6OaAV(Z?0@d6Tk85vQev>-xYg76^;Gds_-{0yfd5m0d81x&Og;SxboqF|zX zxxqhSZbC4EILB`C)`mFL@KpgoGQ^YwMlSUxGtR8$ia9RtDFI4}GZH}~+swIC`N1Lp zCHECv1N~ua2)}%2E zqmP>n2BMw}23AUz+I)l;7CaF#%HeQ`q$|Wk=zZNP0odF1W&8X!7p zkhE=ZpAoI<27sF-P87+^5>p~UIa3YZkpIx&naax zB!-8)p>o~FB=`AEWp@_rkoSBvn?o;1lic)jshLq(xLqvnQY+ zZkoYM+HO{wCrt~096tg;DXk#vyvL=x^}H&DgQ-a;TAs+*L=^&x1P=j-+4Z9%K#>kH z-Xw73{AeZm<8pfuG}OirQ9n$IRMToF!TKWXF-(23X;e*9v-eQ2-ZHy5cM=^DstB^m zN*{6QCXkxaYf50l3?j{5cK!b9sxwuC-j?xsS@aN~71Stk?qz zV#SB!4oP)&!y@D4V)mm!eWfd?skd&7gc3%5qbg&Lj}yws|g3aAuO_LDB4BV8M(vpFG*{@l%I0ibUepQ zrC2L?@A(wZgh`48st6KJ^HEw=MrDMTM_#JvGtx`a%9M(pNwn;wcp#&UA}z&xCm)KT zQ>cO##ipWZnnW0gnG8yku9Y^bZ5k3qq!k$=BQZiW%|qVV%1pLgdaTqy;j*J2hGSK) zuCA{^m32dg4=A#1^FU)Iq(t+Xi9~8Lt!g?|X(%PJ4-2JDAR=QLU6nMGIPsJj2LPl9 z`i%dDDIyYvJu(3Cc-$YfGPkSSuIWU?jY4Fqnn)lz(O7G(6WkSm$gI>=)z%f=-rPKU zYZE1fg3?lJ2nW~%qNs)>ZF)l`p1_1*IB5tGT~X|NAUiwf6{+{V^_Etl8n=K`icl^^ zbEc;g5AUcIB(koRnWDx6Uo)-cb&=o=QsT-1~xLgSU z63C5cN-)DMmAV#)#Umbu0cs#aAh4Iw9iYWX;qeIo zg`>Qaem(O;o?MjLKGorb`56L0!pxzpiJQE$%)(hZLy96-sfpa%46i7w# zi|)<#{EJ}WHF|!gSq|HgOl-7ENS`xPfBJtcKhD+R_JbUhiMOLjbWIX(;ZI9ys<{Vc-KviiX(pqn>u6Em9 zq1}@p$j;bY1G&&X;V*5B2*6B0j0TQ_U)cW)83Xd-o!FS|Q#fow8EU18k>UXJ4GMHJ z>9g|5$7>f)P|4r15plt`Df_K+>wVWWfMT8~3U$dX0FWNLW_Ppd20I-0Ry@Sx)&1_- zGXv1G>nmK*tNX2R(pzb~A&)Wrk?O7Tzkeb;g~2GLN~dDNpRW@ld5~0+ zy1Y{PYjTdq(L3jDsM{(D#=O4KKuk&uH>-y{3A3!4xmya}DA(LPs!Lb-l+2&Z{BZ%8 zl&)MUUv_yofkx$9LzN9#p9R~mt4#e}`8>35UwotakG%^Gb(Wb6-vdP4y zrvLwyeQB5DIIiUdNNwK25t&*2|Nq*YGv~eT%2>Q=;ez?VMU?Ew>QQ%P*fK?tAP8In zAP8_c?hE9^uXCy;S>rj)ph_vF z8AQxbN?B`!NJAS;6*o%LFpWWLj{Pu>BhBiFG{d>Px=ZUJrb6qd=>Y*yH+56h;l(~v zDv6scn>-DP4kylyy`)npqB@x?4`0_^x}r-%FeM% zKIg&Cp?L{{B1~0^4zXY{35l=5y+oTo&5nX{i%Ckw4_=&^+&DUCoOdaPkRFPb)fJ*E z<1I1!Ia#ao^VI~1kl$(0uWW^f|$pgdS%r3u{BT5(9#94!h+ z!$E?&t~T4PRtVu7+ij~=oPO)HKoWN%-Ea4=udmzvHVr+nP$K!S01kc-dlxhL$;h1R zB-aLjRYlO}yY+BwTLXZHs-Ua552LJ^<}hPfzHqLTBJe8bWUyO=$r@+Ly&suU{19PN zx6NL=i`-1#>HTaUp(bq3_M8860inA zc_bwus9AZBugl0YNDC3J$F8>TZB+201v0|cpr^)efp8)T@@iGj? z8gETFzAEgt;e~O$eCD|-PmM~=iE}#1jyShz{cwsXnhPaK`lKU|0Dy8Ovm-XJ+{`qo zRq~Vw3&pzrZPq;HkA*IZZ;8ziBv0y7_ZbB_0*cO>S(-dHDe$fr2!s`Dr2%n591e&= z;4boTES%0U4R47tnv8hj2_?J{TBEcAWDJ3#3uzuO$y!>*o~`dm@?{Z3yf_irY}*(* zMFJsXOw~0_rJZp;q(uXfz~$rULgXntAjYPk4f1B15T-3taKX-QQPUK110tMUM@R>;5=h7)9)Kx+4tt1GC{9A* zioo#s90*wqTaIu`Xio?bUNh}?LL~Pvk&-84tZ~!etZ@m7XJP)w>ro&fHK_QIxn&{B z^Fvu<03oV&wUy>(lwW83dJb zawW!By2i~4 z1^`wp#L29BDN3ng+>yzfRi?=2*NF+BIeOI(xDPH5grCHV`>{Kk&2YZ=c7Re!tV4)j zN{Txy!ZXD@P_;O0I_nK{J&e=sWDtu8hxU1|oZc^TPpjQK3!ZlT?=alPvs`kXx$F7!~-?_|ULF)L$bEM(rQ$r-2=52o}H!C%A45fdSa#NcGiQzS<^FjZQCLtq!hU=x8544ft=;t*ZH z!E#1$@VSx_?F9A16k|YRcoGu)%Z|5FTw^9#o~W}SY&lLIe)1ztd2mSt;=OZmv#(;7 z`N_z1(`3b2K~T9wMBQfFL5$q9j)7AF&D%7E=*ckzEG5xO6qP>&BI}oAXaieSFC#{qTXUa%gs%FSh zwnRWgUVI4i03@EylY);4DQ9__MB?%ByRX`Q)746|RlcIuppRo9q1F=gM2x5u6j#QN z&YQ03ZfxLCZCO0*_;7$}ROC;_{12CS?;yi{GRE5}g%rmX6VC>H-~n+j%;z(Cl1ES0 zQR}m;k$fvjnw4{2A`~tj|D!1RURKhYy<^Lgtdp|b^Lo=VYhhnqtF$Hl%l5ZY$d*Vb zF)@|rU}gIHd8)=g`Se&Yh_y~bl)6DcI1fc!39gu=0*eH{VFV+&=T%iTO${K(5nn7R z*R4k}01rr{9I3gtu}EkqH+36qx#KjZX%W4QE65;DrjT1hs8R}q;dX1frfIryyre_w zBqo|CG1h&ZPTTFauC!)0-j{871XZzN<)8&75fY2fj}zjic6RV^m|(Wm=8Nvq%P_

l{J<;R6Ev!%Q50mWby!_QR$KBU0Rl7NG(^wz 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 Ef{$m9t^fc4 literal 0 HcmV?d00001 From 8f9fb255bcaaa802fcd122a36c8a922c7c25a767 Mon Sep 17 00:00:00 2001 From: davegson <3080765+davegson@users.noreply.github.com> Date: Mon, 22 Mar 2021 15:55:25 +0100 Subject: [PATCH 05/10] Re-Draft Attributing DNS requests post --- ...-23-attributing-dns-requests-on-windows.md | 62 ++++++++++++++----- 1 file changed, 45 insertions(+), 17 deletions(-) diff --git a/_posts/2021-03-23-attributing-dns-requests-on-windows.md b/_posts/2021-03-23-attributing-dns-requests-on-windows.md index cbd060a..c8c76d2 100644 --- a/_posts/2021-03-23-attributing-dns-requests-on-windows.md +++ b/_posts/2021-03-23-attributing-dns-requests-on-windows.md @@ -7,18 +7,29 @@ category: "Dev Log" --- For an application firewall it is crucial to know which processes query which domains. -This sounds like an easy thing to achieve, but in practice it turned out to be a rather complicated problem. +This sounds like an easy thing to achieve, but in practice it turns out to be a rather complicated problem. Especially on Windows. + +### Applications Resolve DNS via the DNS-Client Windows Service When we first looked into how to find this vital piece of information on Windows 10, we found that for some reason, all DNS requests are sent from the "DNS-Client" Windows service. -There were no DNS requests _to_ that service on the wire, just _from_ it. -Upon further investigation we found that Windows applications use the `dnsapi.dll` for taking care of DNS requests. +There were no DNS requests _to_ that service on the wire, just _from_ it. Upon further investigation we found that Windows applications use the `dnsapi.dll` for taking care of DNS requests. + + + + These requests are not sent using common DNS packets on the wire, but use a RPC call via an internal IPC mechanism. -This means that we could not attribute DNS requests to processes out of the box. +After all this research, it became clear that we could not attribute DNS requests to processes out of the box. -### Disabling the DNS Client Turned Out to Be the Quick But Dirty Solution +### For A Long Time, Deactivating the DNS-Client Had No Real Impact - So We Did It + + + + + While researching this issue we found that disabling the DNS-Client seemed to be a rather much requested action and quite common for Windows users. + Most often, Windows users asked for this in order to work around bugs or to improve some aspect of their network performance. So we decided to take the easy route and just disable the DNS-Client upon installation, because it is only a caching stub resolver with no other functionality, right? Right? @@ -28,21 +39,39 @@ No. Apparently, the DNS-Client is much more than "just" a caching stub resolver. Maybe it should have been a stronger hint to us that Microsoft removed the ability to stop it directly - we had to change a value in the registry and reboot the system in order to get rid of it. +### Turns Out: Deactivating the DNS-Client Messes Things Up + The first reports we received that made us aware that there is much more to this service, were those of VPN clients not working correctly. Some of these clients wanted to change the configured DNS server in Windows (which is a good thing - it prevents DNS leaking), but as it turned out, the responsible Windows service for handling these changes is ... the DNS-Client! With every report of another broken application that we could attribute to the disabled DNS-Client service, we started to realize that we needed a better solution. +### Back to the Start / Searching For Alernatives + All research regarding to finding another way to see the DNS requests without disabling the DNS-Client turned up no viable options - we dismissed the crazy ones: - Hijacking the `dnsapi.dll` to force the `DNS_QUERY_WIRE_ONLY` flag - we are not malware. -- Directly replacing the DNS-Client service - replicating Windows behavior is a nightmare. +- Directly replacing the DNS-Client service - replicating Windows behavior is a nightmare. Closed source, no Docs, etc... extend why -### Biting the bullet With no options available to directly get the needed information, we were left with only one option: Working around the problem on our side. + + + + Until now, we were able to directly attribute a DNS request to a process due to our "quick and dirty" solution. No longer being able to do that means that we loose some information, and that we will have a slightly less tight grip on the system. + We will need to find a good balance between control and configurability + +-> da wir eine Connection nicht mehr einem Prozess schnell zuordnen können greifen da nur die Globals und die Attribution im Nachhinein hat eine Fehlerquote + +Setting: + +### We Will Keep Users in Power As Much as Possible + + + + The easiest way to keep control is to make previous app-specific settings global only, because then we just don't need to know the origin of a DNS request anymore to apply settings, but we're not ready to give up configurability so easily. Previously, we made decisions directly when the DNS request arrived at the Portmaster, at which point we had all the necessary information to evaluate a DNS request. @@ -51,15 +80,7 @@ Instead, we now return a valid answer to most DNS requests coming from the DNS-C Now, when an app uses the DNS-Client for resolving a domain, it receives a valid answer and the Portmaster can then attribute the domain and other information to a follow-up network connection. The decision making that previously happened directly when the DNS request was handled can now happen when the network connection is initiated instead. -### Positive Side Effects - -Not only Windows has an internal DNS server to take care of DNS requests. Linux distributions are starting to active the DBus interface of systemd-resolved, which in turn also hides DNS requests from us. The workaround presented in this post also successfully works around this. - -Similar system are known to exist and are expected in other operating systems as well, so this change will better brace us for the next systems the Portmaster will be expanded to. - -In addition to that we also now have more information available for network connections, which will make future features, such as the connection history, even more powerful. - -### Negative Side Effects +### Short-Term Side Effects Because remembered DNS requests that go through the DNS-Client are now pooled together, this can lead to a wrong attribution of a domain to a connection. @@ -72,6 +93,14 @@ But this will not solve all our problems: - Applications can fake exposed domain information with a method called "Domain Fronting". - TLS 1.3 introduces Encrypted Client Hello messages, which will (partially) hide this information again. +### This Will Also Benefit Linux Integration Long-Term + +Not only Windows has an internal DNS server to take care of DNS requests. Linux distributions are starting to active the DBus interface of systemd-resolved, which in turn also hides DNS requests from us. The workaround presented in this post also successfully works around this. + +Similar systems are known to exist and are expected in other operating systems as well, so this change will better brace us for the next systems the Portmaster will be expanded to. + +In addition to that we also now have more information available for network connections, which will make future features, such as the connection history, even more powerful. + ### Changes to the Portmaster Here is a full list of changes that this workaround brings: @@ -79,4 +108,3 @@ Here is a full list of changes that this workaround brings: - The Portmaster will activate the DNS-Client Windows Service, which it previously disabled during installation. - The DNS-Client in Windows and Linux' systemd-resolved are now categorized as a special "System DNS Client" app in the Portmaster. - If you want to disable bypass prevention for an app, you might need to also disable bypass prevention in the "System DNS Client" App in the Portmaster. -- The Portmaster still works as before with a disabled DNS-Client. Whoever prefers it the way it was, can just disable the DNS-Client manually. From ec09e96ab3394fb8559c58374aefa5cd0ccb43ee Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 22 Mar 2021 22:33:23 +0100 Subject: [PATCH 06/10] Improve Attributing DNS Requests post --- ...-23-attributing-dns-requests-on-windows.md | 91 ++++++++++--------- 1 file changed, 50 insertions(+), 41 deletions(-) diff --git a/_posts/2021-03-23-attributing-dns-requests-on-windows.md b/_posts/2021-03-23-attributing-dns-requests-on-windows.md index c8c76d2..cde114c 100644 --- a/_posts/2021-03-23-attributing-dns-requests-on-windows.md +++ b/_posts/2021-03-23-attributing-dns-requests-on-windows.md @@ -12,90 +12,97 @@ This sounds like an easy thing to achieve, but in practice it turns out to be a ### Applications Resolve DNS via the DNS-Client Windows Service When we first looked into how to find this vital piece of information on Windows 10, we found that for some reason, all DNS requests are sent from the "DNS-Client" Windows service. -There were no DNS requests _to_ that service on the wire, just _from_ it. Upon further investigation we found that Windows applications use the `dnsapi.dll` for taking care of DNS requests. +There were no DNS requests _to_ that service on the wire, just _from_ it. Upon further investigation we, found that Windows applications use the `dnsapi.dll` for taking care of DNS requests: +Whenever an application needs to resolve a dns query, for example in order to load a website, this `.dll` is loaded into the application and takes care of all the DNS details. +It then communicates directly with the DNS-Client via an internal IPC mechanism and does not even send a common DNS packet on the wire, that the Portmaster could see. - - + -These requests are not sent using common DNS packets on the wire, but use a RPC call via an internal IPC mechanism. - -After all this research, it became clear that we could not attribute DNS requests to processes out of the box. +We realized that we wouldn't be able to attribute DNS requests to processes out of the box. ### For A Long Time, Deactivating the DNS-Client Had No Real Impact - So We Did It - +Windows provides the option and official documentation on how to deactive the DNS-Client. +When this is the case, the `dnsapi.dll` falls back to sending DNS requests on the wire, where the Portmaster can pick them up and handle them. - - - -While researching this issue we found that disabling the DNS-Client seemed to be a rather much requested action and quite common for Windows users. - -Most often, Windows users asked for this in order to work around bugs or to improve some aspect of their network performance. + +While researching this issue, we found that disabling the DNS-Client actually seemed to be a rather much requested action and quite common for Windows users. So we decided to take the easy route and just disable the DNS-Client upon installation, because it is only a caching stub resolver with no other functionality, right? Right? No. Apparently, the DNS-Client is much more than "just" a caching stub resolver. Maybe it should have been a stronger hint to us that Microsoft removed the ability to stop it directly - we had to change a value in the registry and reboot the system in order to get rid of it. +The offical docs do not mention anything about that, they still "insist" that it should work directly and there is no mention of how the DNS-Client has actually become a criticial and central part of Windows. ### Turns Out: Deactivating the DNS-Client Messes Things Up The first reports we received that made us aware that there is much more to this service, were those of VPN clients not working correctly. Some of these clients wanted to change the configured DNS server in Windows (which is a good thing - it prevents DNS leaking), but as it turned out, the responsible Windows service for handling these changes is ... the DNS-Client! -With every report of another broken application that we could attribute to the disabled DNS-Client service, we started to realize that we needed a better solution. +With every report of another broken application that we could trace back to the disabled DNS-Client service, we started to realize that we needed a better solution. -### Back to the Start / Searching For Alernatives +### Back to the Drawing Board -All research regarding to finding another way to see the DNS requests without disabling the DNS-Client turned up no viable options - we dismissed the crazy ones: -- Hijacking the `dnsapi.dll` to force the `DNS_QUERY_WIRE_ONLY` flag - we are not malware. -- Directly replacing the DNS-Client service - replicating Windows behavior is a nightmare. Closed source, no Docs, etc... extend why +We went back to researching possibilities to somehow find out which processes query which domains. We found some "interesting" ways: +There actually is a way to force the `dnsapi.dll` to fall back to sending DNS requests over the wire. +Applications can specify the flag `DNS_QUERY_WIRE_ONLY` to the `.dll`, but forcing this globally would mean we'd have to hijack the `dnsapi.dll`. +While some of you might find that this is a viable solution, hijacking - as the name could "maybe" suggest - is definitely in the malware realm, and the Portmaster is no malware. -With no options available to directly get the needed information, we were left with only one option: Working around the problem on our side. +Something similar would be possible on the other end: We could just replace the full DNS-Client by disabling it and taking its place. +While this is a potential cleaner solution than hijacking something, we've had enough headaches from working with _documented_ Windows APIs, and touching undocumented Windows stuff is pretty much nightmare material for engineers. - +With no other options available to directly get the needed information, we were left with only one option: Working around the problem on our side. +The simplest way to achieve that, is accept that we won't have access to the required information and disable per-app settings completely. This would leave users without the ability to change settings for some apps and not for others. - - -Until now, we were able to directly attribute a DNS request to a process due to our "quick and dirty" solution. -No longer being able to do that means that we loose some information, and that we will have a slightly less tight grip on the system. - -We will need to find a good balance between control and configurability - --> da wir eine Connection nicht mehr einem Prozess schnell zuordnen können greifen da nur die Globals und die Attribution im Nachhinein hat eine Fehlerquote - -Setting: +This would mean that we would be able to keep our tight grip on the system, but as you have certainly guessed by now, we are all about emporing our users and this is not a solution we have ever really considered. We continued our research to find a good balance between control and configurability. ### We Will Keep Users in Power As Much as Possible - - +In order to keep the ability to empower users with per-app settings, we need to know where applications are connecting to as early as possible in order to protect your privacy as good as we can. -The easiest way to keep control is to make previous app-specific settings global only, because then we just don't need to know the origin of a DNS request anymore to apply settings, but we're not ready to give up configurability so easily. +The ideal and earliest place would have been the DNS request, which is not possible anymore. Instead, we now return a valid answer to most DNS requests coming from the DNS-Client. -Previously, we made decisions directly when the DNS request arrived at the Portmaster, at which point we had all the necessary information to evaluate a DNS request. +The most notable exception to this is the Portmaster's Bypass Protection, which will continue to also directly block DNS requests if it needs to, no matter where they come from. We think it's okay to be over-protective about protecting you. -Instead, we now return a valid answer to most DNS requests coming from the DNS-Client - bypass protection being one of the big exceptions here. Just as before, we remember that a process requested a certain domain in order to match it to a connection later. In order to correctly attribute requests that go through the DNS-Client, we now put these remembered requests into a global scope, which all processes can use to match their connections to a DNS request. In addition to that, we now attach various information about the request itself, and DNS server used for it, to that remembered request. +The next possible place to intervene is when a process initiates a network connection (think TCP). +At this point, no data has left your device and we only know the IPs, the ports and the originating process. +In most cases, we don't know yet which (Layer 5) protocol will be used over the connection, or which domain is the target. -Now, when an app uses the DNS-Client for resolving a domain, it receives a valid answer and the Portmaster can then attribute the domain and other information to a follow-up network connection. The decision making that previously happened directly when the DNS request was handled can now happen when the network connection is initiated instead. +But we would love to know already! +So, whenever the Portmaster returns a valid DNS answer to a request - even if don't know the real process behind it - we remember which IPs this domain resolved to. +We scope this information into app-specific scopes or a global scope when we don't know which app is really behind a DNS request. +In addition to the information about the DNS request, we also save information about the resolver that resolved the request for us, so we have more information to work with later on. -### Short-Term Side Effects +Now, back to our process that is initiating a new connection. +We can now look up the remote IP address and see which domain we know about that resolves to the remote IP of the connection. +We can now use this domain and all the other information that we attached there to make a decision about the connection. +And this is still before even a single bit of data leaves your device! -Because remembered DNS requests that go through the DNS-Client are now pooled together, this can lead to a wrong attribution of a domain to a connection. +We did it! +Well, almost. +I think you might have already guessed that this just a little too good to be true... + + + +### Side Effects + +Because remembered DNS requests that go through the DNS-Client are now pooled together in a global scope, this can sometimes lead to a wrong attribution of a domain to a connection. For example, if two processes use two different domains but both of them point to the same IP address, it could happen that the Portmaster thinks that the first process is connecting to the domain of the second process, _if_ requests are done in parallel, or connections are re-established without querying for the domain again. - -This also happened before, when a single process sent its DNS requests directly to the Portmaster, but the impact of wrongly attributing a domain in this case was not so high. +This also happened before, when a single process sent its DNS requests directly to the Portmaster, but this was less likely. As a remediation to this, we will start looking at HTTP headers and TLS handshakes in the future. With information gathered directly from the connection, the attribution will be more accurate. But this will not solve all our problems: - Applications can fake exposed domain information with a method called "Domain Fronting". - TLS 1.3 introduces Encrypted Client Hello messages, which will (partially) hide this information again. +These are challenges we are looking forward to solve and also blog about our journey through that process. + ### This Will Also Benefit Linux Integration Long-Term -Not only Windows has an internal DNS server to take care of DNS requests. Linux distributions are starting to active the DBus interface of systemd-resolved, which in turn also hides DNS requests from us. The workaround presented in this post also successfully works around this. +Not only Windows has an internal DNS server to take care of DNS requests. Linux distributions are starting to active the DBus interface of systemd-resolved, which in turn also hides DNS requests from the Portmaster. The workaround presented in this post also successfully works around this. Similar systems are known to exist and are expected in other operating systems as well, so this change will better brace us for the next systems the Portmaster will be expanded to. @@ -108,3 +115,5 @@ Here is a full list of changes that this workaround brings: - The Portmaster will activate the DNS-Client Windows Service, which it previously disabled during installation. - The DNS-Client in Windows and Linux' systemd-resolved are now categorized as a special "System DNS Client" app in the Portmaster. - If you want to disable bypass prevention for an app, you might need to also disable bypass prevention in the "System DNS Client" App in the Portmaster. + +These changes are live with [Portmaster v0.6.7](https://github.com/safing/portmaster/releases/tag/v0.6.7). From b40ccb157886a892101cd3224a9761473981a161 Mon Sep 17 00:00:00 2001 From: davegson <3080765+davegson@users.noreply.github.com> Date: Tue, 23 Mar 2021 09:52:26 +0100 Subject: [PATCH 07/10] Smoothen the text flow and improve some wording --- ...-23-attributing-dns-requests-on-windows.md | 68 +++++++++---------- 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/_posts/2021-03-23-attributing-dns-requests-on-windows.md b/_posts/2021-03-23-attributing-dns-requests-on-windows.md index cde114c..c324c9b 100644 --- a/_posts/2021-03-23-attributing-dns-requests-on-windows.md +++ b/_posts/2021-03-23-attributing-dns-requests-on-windows.md @@ -12,29 +12,27 @@ This sounds like an easy thing to achieve, but in practice it turns out to be a ### Applications Resolve DNS via the DNS-Client Windows Service When we first looked into how to find this vital piece of information on Windows 10, we found that for some reason, all DNS requests are sent from the "DNS-Client" Windows service. -There were no DNS requests _to_ that service on the wire, just _from_ it. Upon further investigation we, found that Windows applications use the `dnsapi.dll` for taking care of DNS requests: +There were no DNS requests _to_ that service on the wire, just _from_ it. Upon further investigation we found that Windows applications use the `dnsapi.dll` for taking care of DNS requests: Whenever an application needs to resolve a dns query, for example in order to load a website, this `.dll` is loaded into the application and takes care of all the DNS details. It then communicates directly with the DNS-Client via an internal IPC mechanism and does not even send a common DNS packet on the wire, that the Portmaster could see. -We realized that we wouldn't be able to attribute DNS requests to processes out of the box. +We realized that we would not be able to attribute DNS requests to processes out of the box. ### For A Long Time, Deactivating the DNS-Client Had No Real Impact - So We Did It -Windows provides the option and official documentation on how to deactive the DNS-Client. +Windows provides the option and official documentation on how to deactivate the DNS-Client. When this is the case, the `dnsapi.dll` falls back to sending DNS requests on the wire, where the Portmaster can pick them up and handle them. While researching this issue, we found that disabling the DNS-Client actually seemed to be a rather much requested action and quite common for Windows users. -So we decided to take the easy route and just disable the DNS-Client upon installation, because it is only a caching stub resolver with no other functionality, right? Right? - -No. +So we decided to take the easy route and just disable the DNS-Client upon installation, because it is only a caching stub resolver with no other functionality, right? Right? No. Apparently, the DNS-Client is much more than "just" a caching stub resolver. Maybe it should have been a stronger hint to us that Microsoft removed the ability to stop it directly - we had to change a value in the registry and reboot the system in order to get rid of it. -The offical docs do not mention anything about that, they still "insist" that it should work directly and there is no mention of how the DNS-Client has actually become a criticial and central part of Windows. +The official Windows docs do not mention anything about this, they still "insist" that it should work without the DNS-Client, but in reality it has become a critical and central part of Windows not to be tinkered with. ### Turns Out: Deactivating the DNS-Client Messes Things Up @@ -46,43 +44,40 @@ With every report of another broken application that we could trace back to the We went back to researching possibilities to somehow find out which processes query which domains. We found some "interesting" ways: -There actually is a way to force the `dnsapi.dll` to fall back to sending DNS requests over the wire. -Applications can specify the flag `DNS_QUERY_WIRE_ONLY` to the `.dll`, but forcing this globally would mean we'd have to hijack the `dnsapi.dll`. -While some of you might find that this is a viable solution, hijacking - as the name could "maybe" suggest - is definitely in the malware realm, and the Portmaster is no malware. +There actually is a way to force the `dnsapi.dll` to fall back to sending DNS requests over the wire. Applications can specify the flag `DNS_QUERY_WIRE_ONLY` to the `.dll`, but forcing this globally would mean we'd have to hijack the `dnsapi.dll`. +While some of you might find that this is a viable solution, hijacking - as the name suggests - is definitely edgy and likely already in the malware realm, and the Portmaster is no malware. -Something similar would be possible on the other end: We could just replace the full DNS-Client by disabling it and taking its place. -While this is a potential cleaner solution than hijacking something, we've had enough headaches from working with _documented_ Windows APIs, and touching undocumented Windows stuff is pretty much nightmare material for engineers. +Something similar would be possible on the other end: We could just replace the full DNS-Client by disabling it and taking its place with our custom built replica. +While this is a potential cleaner solution than hijacking something, we've had enough headaches from working with _documented_ Windows APIs. So touching _undocumented_ Windows stuff is pretty much nightmare material for engineers. -With no other options available to directly get the needed information, we were left with only one option: Working around the problem on our side. -The simplest way to achieve that, is accept that we won't have access to the required information and disable per-app settings completely. This would leave users without the ability to change settings for some apps and not for others. +With no other options available to directly get the needed information, we were left with only one option: embrace the DNS-Client as it is. No process attribution and no deactivation as a quick-fix. But how could we then still be an effective Application Firewall? -This would mean that we would be able to keep our tight grip on the system, but as you have certainly guessed by now, we are all about emporing our users and this is not a solution we have ever really considered. We continued our research to find a good balance between control and configurability. +The simplest way around the problem is to ditch DNS request to process attribution altogether. So instead of caring which process sent the query and acting upon the per-app setting, you just act upon global settings. The drawback is obvious, that would mean no more per-app settings. So you could not browse facebook.com on your browser while blocking their nasty trackers everywhere else. The world becomes pretty binary. + +So even though we would be able to keep our tight grip on the system, we want to empower users with all their nuanced needs. So this is not a solution we ever really considered. Instead, we continued our research to find a better balance between system control and per-app configurability. ### We Will Keep Users in Power As Much as Possible In order to keep the ability to empower users with per-app settings, we need to know where applications are connecting to as early as possible in order to protect your privacy as good as we can. -The ideal and earliest place would have been the DNS request, which is not possible anymore. Instead, we now return a valid answer to most DNS requests coming from the DNS-Client. +The ideal and earliest place would have been the DNS request, which turned out not to be feasible anymore. Instead, we now return a valid answer to most DNS requests coming from the DNS-Client. -The most notable exception to this is the Portmaster's Bypass Protection, which will continue to also directly block DNS requests if it needs to, no matter where they come from. We think it's okay to be over-protective about protecting you. + + +The most notable exception to this is the Portmaster's Bypass Protection, which will continue to also directly block DNS requests if it needs to, no matter where they come from. We think it is good to be strict in this case. The next possible place to intervene is when a process initiates a network connection (think TCP). -At this point, no data has left your device and we only know the IPs, the ports and the originating process. -In most cases, we don't know yet which (Layer 5) protocol will be used over the connection, or which domain is the target. +At this point, no data has left your device and we only know the IPs, the ports and the originating process. In most cases, we don't know yet which (Layer 5) protocol will be used over the connection, or which domain is the target. But we would love to know already! -So, whenever the Portmaster returns a valid DNS answer to a request - even if don't know the real process behind it - we remember which IPs this domain resolved to. -We scope this information into app-specific scopes or a global scope when we don't know which app is really behind a DNS request. +So, whenever the Portmaster returns a valid DNS answer to a request - even if do not know the real process behind it - we remember which IPs this domain resolved to. +We scope this information into app-specific scopes or a global scope when we do not know which app is really behind a DNS request. In addition to the information about the DNS request, we also save information about the resolver that resolved the request for us, so we have more information to work with later on. Now, back to our process that is initiating a new connection. We can now look up the remote IP address and see which domain we know about that resolves to the remote IP of the connection. -We can now use this domain and all the other information that we attached there to make a decision about the connection. -And this is still before even a single bit of data leaves your device! - -We did it! -Well, almost. -I think you might have already guessed that this just a little too good to be true... +With this domain and all the other attached information we can now make a decision about the connection. +And this is still before even a single bit of data leaves your device - we did it! Well, almost... As it turns out, there are some edge cases which might lead to side effects. Always expect and deal with side effects, especially on Windows. @@ -90,30 +85,31 @@ I think you might have already guessed that this just a little too good to be tr Because remembered DNS requests that go through the DNS-Client are now pooled together in a global scope, this can sometimes lead to a wrong attribution of a domain to a connection. -For example, if two processes use two different domains but both of them point to the same IP address, it could happen that the Portmaster thinks that the first process is connecting to the domain of the second process, _if_ requests are done in parallel, or connections are re-established without querying for the domain again. -This also happened before, when a single process sent its DNS requests directly to the Portmaster, but this was less likely. +For example, if two processes use two different domains but both of them point to the same IP address, it could happen that the Portmaster thinks that the first process is connecting to the domain of the second process and vice-versa. Especially _if_ requests are done in parallel or connections are re-established without querying for the domain again. +This could also have happened before, when a single process sent its DNS requests directly to the Portmaster, but this was less likely. As a remediation to this, we will start looking at HTTP headers and TLS handshakes in the future. With information gathered directly from the connection, the attribution will be more accurate. + But this will not solve all our problems: - Applications can fake exposed domain information with a method called "Domain Fronting". -- TLS 1.3 introduces Encrypted Client Hello messages, which will (partially) hide this information again. +- TLS 1.3 introduces Encrypted Client Hello messages, which will partially hide this information again. -These are challenges we are looking forward to solve and also blog about our journey through that process. +The rabbit hole is endless, so for now we cut it here. But no worries - we are looking forward to solving these challenges in the future. ### This Will Also Benefit Linux Integration Long-Term -Not only Windows has an internal DNS server to take care of DNS requests. Linux distributions are starting to active the DBus interface of systemd-resolved, which in turn also hides DNS requests from the Portmaster. The workaround presented in this post also successfully works around this. +Not only Windows has an internal DNS server to take care of DNS requests. Linux distributions are starting to activate the DBus interface of `systemd-resolved`, which in turn also hides DNS requests from the Portmaster. The workaround presented in this post also successfully works around this. Similar systems are known to exist and are expected in other operating systems as well, so this change will better brace us for the next systems the Portmaster will be expanded to. -In addition to that we also now have more information available for network connections, which will make future features, such as the connection history, even more powerful. +In addition to that, we now also have more information available on network connections, which will make future features, such as the connection history, even more powerful. -### Changes to the Portmaster +### Portmaster Changelog Here is a full list of changes that this workaround brings: - Domains may be wrongly attributed to connections a bit more often than before. - The Portmaster will activate the DNS-Client Windows Service, which it previously disabled during installation. - The DNS-Client in Windows and Linux' systemd-resolved are now categorized as a special "System DNS Client" app in the Portmaster. -- If you want to disable bypass prevention for an app, you might need to also disable bypass prevention in the "System DNS Client" App in the Portmaster. +- If you want to disable bypass prevention for a specific app, you might also need to disable bypass prevention in the "System DNS Client" App in the Portmaster. -These changes are live with [Portmaster v0.6.7](https://github.com/safing/portmaster/releases/tag/v0.6.7). +These changes are [live with Portmaster v0.6.7](https://github.com/safing/portmaster/releases/tag/v0.6.7). From f5f7a1b5026d71072db432fab9e71ccd60c9dcf3 Mon Sep 17 00:00:00 2001 From: davegson <3080765+davegson@users.noreply.github.com> Date: Tue, 23 Mar 2021 12:32:54 +0100 Subject: [PATCH 08/10] Master blogpost round 2 --- ...-23-attributing-dns-requests-on-windows.md | 89 ++++++++++--------- 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/_posts/2021-03-23-attributing-dns-requests-on-windows.md b/_posts/2021-03-23-attributing-dns-requests-on-windows.md index c324c9b..fce8bf6 100644 --- a/_posts/2021-03-23-attributing-dns-requests-on-windows.md +++ b/_posts/2021-03-23-attributing-dns-requests-on-windows.md @@ -11,100 +11,103 @@ This sounds like an easy thing to achieve, but in practice it turns out to be a ### Applications Resolve DNS via the DNS-Client Windows Service -When we first looked into how to find this vital piece of information on Windows 10, we found that for some reason, all DNS requests are sent from the "DNS-Client" Windows service. +When we first looked into how to find this vital piece of information on Windows 10, we found that for some reason all DNS requests are sent from the "DNS-Client" Windows service. There were no DNS requests _to_ that service on the wire, just _from_ it. Upon further investigation we found that Windows applications use the `dnsapi.dll` for taking care of DNS requests: -Whenever an application needs to resolve a dns query, for example in order to load a website, this `.dll` is loaded into the application and takes care of all the DNS details. -It then communicates directly with the DNS-Client via an internal IPC mechanism and does not even send a common DNS packet on the wire, that the Portmaster could see. +So whenever an application needs to resolve a dns query, for example in order to load a website, this `.dll` is loaded into the application and takes care of all the DNS details. +It then communicates directly with the DNS-Client via an internal IPC mechanism and does not even send a common DNS packet on the wire, which the Portmaster or any other process could see. -We realized that we would not be able to attribute DNS requests to processes out of the box. +As a result, we realized that we would not be able to attribute DNS requests to processes out of the box. -### For A Long Time, Deactivating the DNS-Client Had No Real Impact - So We Did It +### For A Long Time, Deactivating the DNS-Client Had No Real Impact - So We Did That Windows provides the option and official documentation on how to deactivate the DNS-Client. When this is the case, the `dnsapi.dll` falls back to sending DNS requests on the wire, where the Portmaster can pick them up and handle them. -While researching this issue, we found that disabling the DNS-Client actually seemed to be a rather much requested action and quite common for Windows users. -So we decided to take the easy route and just disable the DNS-Client upon installation, because it is only a caching stub resolver with no other functionality, right? Right? No. +While researching this issue we found that disabling the DNS-Client actually seemed to be a rather much requested action and quite common for Windows users. This is done by setting the registry key `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Dnscache` from "Start" to "4" and then rebooting. +We decided to follow this easy route and just disable the DNS-Client upon installation, because it is only a caching stub resolver with no other functionality, right? Right? No. -Apparently, the DNS-Client is much more than "just" a caching stub resolver. -Maybe it should have been a stronger hint to us that Microsoft removed the ability to stop it directly - we had to change a value in the registry and reboot the system in order to get rid of it. -The official Windows docs do not mention anything about this, they still "insist" that it should work without the DNS-Client, but in reality it has become a critical and central part of Windows not to be tinkered with. +As it turns out, the DNS-Client is much more than "just" a caching stub resolver. +Maybe it should have been a stronger hint to us that Microsoft removed the ability to directly stop the DNS-Client but instead requires the registry change and reboot. +However, the official Windows docs do not mention anything about there being more to the DNS-Client. They still "insist" that everything should work fine without it, but in reality the DNS-Client has become a critical and central part of Windows not to be tinkered with. -### Turns Out: Deactivating the DNS-Client Messes Things Up +### Turns Out: Deactivating the DNS-Client Causes Lots of Issues For Users -The first reports we received that made us aware that there is much more to this service, were those of VPN clients not working correctly. -Some of these clients wanted to change the configured DNS server in Windows (which is a good thing - it prevents DNS leaking), but as it turned out, the responsible Windows service for handling these changes is ... the DNS-Client! -With every report of another broken application that we could trace back to the disabled DNS-Client service, we started to realize that we needed a better solution. +The first reports we received that made us aware that there is much more to this service were those of VPN clients not working correctly. +Some of these clients wanted to change the configured DNS server in Windows, which is a good thing - it prevents DNS leaking. But as it turns out, the responsible Windows service for handling these changes is ... the DNS-Client! +With every report of another broken application that we could trace back to the disabled DNS-Client service, we started to realize that we were on the wrong path and needed a better solution. -### Back to the Drawing Board +### Hijacking dnsapi.dll Was Ditched Because it Is Malware-ish -We went back to researching possibilities to somehow find out which processes query which domains. We found some "interesting" ways: +We went back to researching possibilities to somehow find out and attribute which processes query which domains. We found some "interesting" ways: -There actually is a way to force the `dnsapi.dll` to fall back to sending DNS requests over the wire. Applications can specify the flag `DNS_QUERY_WIRE_ONLY` to the `.dll`, but forcing this globally would mean we'd have to hijack the `dnsapi.dll`. +There actually is a way to force the `dnsapi.dll` to fall back to sending DNS requests over the wire. Applications can specify the flag `DNS_QUERY_WIRE_ONLY` to the `.dll`, but forcing this globally would mean we would have to hijack the `dnsapi.dll`. While some of you might find that this is a viable solution, hijacking - as the name suggests - is definitely edgy and likely already in the malware realm, and the Portmaster is no malware. +### Replicating Windows Functionality Would Be a Nightmare + Something similar would be possible on the other end: We could just replace the full DNS-Client by disabling it and taking its place with our custom built replica. -While this is a potential cleaner solution than hijacking something, we've had enough headaches from working with _documented_ Windows APIs. So touching _undocumented_ Windows stuff is pretty much nightmare material for engineers. +While this is potentially a cleaner solution than hijacking, we already have had enough headaches from working with _documented_ Windows APIs. Touching _undocumented_ Windows stuff is pretty much nightmare material for engineers at this point. -With no other options available to directly get the needed information, we were left with only one option: embrace the DNS-Client as it is. No process attribution and no deactivation as a quick-fix. But how could we then still be an effective Application Firewall? +### No per-App Settings Is Not an Option Too -The simplest way around the problem is to ditch DNS request to process attribution altogether. So instead of caring which process sent the query and acting upon the per-app setting, you just act upon global settings. The drawback is obvious, that would mean no more per-app settings. So you could not browse facebook.com on your browser while blocking their nasty trackers everywhere else. The world becomes pretty binary. +With no other options available to directly get the needed information, we were only left with one option: embrace the DNS-Client as it is, not deactivating it and accepting we get no process attribution via that route. But how could we then still be an effective Application Firewall? -So even though we would be able to keep our tight grip on the system, we want to empower users with all their nuanced needs. So this is not a solution we ever really considered. Instead, we continued our research to find a better balance between system control and per-app configurability. +The simplest way around the problem would be to ditch DNS request to process attribution altogether. So instead of caring which process sent the query and acting upon the per-app setting, you just act upon global settings. The drawback is obvious: no more per-app settings. So you could not browse facebook.com on your browser while blocking their nasty trackers everywhere else. The world becomes pretty binary. -### We Will Keep Users in Power As Much as Possible +So even though we would be able to keep our tight grip on the system, we want to empower users with all their nuanced needs. So this was not a solution we ever really considered. Instead, we continued our research to find a better balance between system control and per-app configurability. -In order to keep the ability to empower users with per-app settings, we need to know where applications are connecting to as early as possible in order to protect your privacy as good as we can. +### The Solution: Intervene Later - When Network Connections Are Initiated -The ideal and earliest place would have been the DNS request, which turned out not to be feasible anymore. Instead, we now return a valid answer to most DNS requests coming from the DNS-Client. +In order to best protect user privacy, we need to know where applications are connecting to as early as possible. - +The ideal and earliest place would have been the DNS request, which turned out not to be feasible anymore. Here, we now return a valid answer to most DNS requests coming from the DNS-Client. -The most notable exception to this is the Portmaster's Bypass Protection, which will continue to also directly block DNS requests if it needs to, no matter where they come from. We think it is good to be strict in this case. +The most notable exception to this is the Portmaster's Bypass Protection, which will continue to directly block DNS requests if it needs to, no matter where they come from. We think it is good to be strict in this case. The next possible place to intervene is when a process initiates a network connection (think TCP). -At this point, no data has left your device and we only know the IPs, the ports and the originating process. In most cases, we don't know yet which (Layer 5) protocol will be used over the connection, or which domain is the target. +At this point, no data has left your device and we only have intel on the IPs, the ports and the originating process. In most cases, we do not yet know which (Layer 5) protocol will be used over the connection, or which domain is the target. -But we would love to know already! -So, whenever the Portmaster returns a valid DNS answer to a request - even if do not know the real process behind it - we remember which IPs this domain resolved to. -We scope this information into app-specific scopes or a global scope when we do not know which app is really behind a DNS request. -In addition to the information about the DNS request, we also save information about the resolver that resolved the request for us, so we have more information to work with later on. +But what we can do here, is collect more intel. So whenever the Portmaster returns a valid DNS answer to a request - even if we do not know the real process behind it - we remember which IPs this domain resolved to. +We scope this information into app-specific scopes or, when we do not know which app is really behind a DNS request, into a global scope. +In addition we also which resolver handled the request for us, so we have more information to work with later on. -Now, back to our process that is initiating a new connection. -We can now look up the remote IP address and see which domain we know about that resolves to the remote IP of the connection. -With this domain and all the other attached information we can now make a decision about the connection. -And this is still before even a single bit of data leaves your device - we did it! Well, almost... As it turns out, there are some edge cases which might lead to side effects. Always expect and deal with side effects, especially on Windows. +### The Application Firewall Still Acts Before Any Data Leaves Your Device + +Now, back to our process that is initiating a new connection: +We can look up the remote IP address and see which domain we know of that resolves to the remote IP of the connection. +With this domain and all the other attached information we can now attribute the connection and make a decision about it. +And this all happens before even a single bit of data leaves your device - we did it! Well, almost... As it turns out, there are some edge cases which might lead to side effects. Always expect to deal with side effects, especially on Windows. -### Side Effects +### Side Effect: Wrong Attribution Is Now More Likely -Because remembered DNS requests that go through the DNS-Client are now pooled together in a global scope, this can sometimes lead to a wrong attribution of a domain to a connection. +Since remembered DNS requests which go through the DNS-Client are now pooled together in a global scope, this can sometimes lead to a wrong attribution of a domain to a connection. For example, if two processes use two different domains but both of them point to the same IP address, it could happen that the Portmaster thinks that the first process is connecting to the domain of the second process and vice-versa. Especially _if_ requests are done in parallel or connections are re-established without querying for the domain again. This could also have happened before, when a single process sent its DNS requests directly to the Portmaster, but this was less likely. As a remediation to this, we will start looking at HTTP headers and TLS handshakes in the future. With information gathered directly from the connection, the attribution will be more accurate. -But this will not solve all our problems: +But even that will not solve all our problems: - Applications can fake exposed domain information with a method called "Domain Fronting". - TLS 1.3 introduces Encrypted Client Hello messages, which will partially hide this information again. -The rabbit hole is endless, so for now we cut it here. But no worries - we are looking forward to solving these challenges in the future. +As you see, the rabbit hole is endless, for now we are cutting it here. But no worries - we are looking forward to solving these challenges in the future. -### This Will Also Benefit Linux Integration Long-Term +### The Solution Also Benefits Linux Integration -Not only Windows has an internal DNS server to take care of DNS requests. Linux distributions are starting to activate the DBus interface of `systemd-resolved`, which in turn also hides DNS requests from the Portmaster. The workaround presented in this post also successfully works around this. +Not only Windows has an internal DNS server to take care of DNS requests. Linux distributions are starting to activate the DBus interface of `systemd-resolved`, which in turn also hides DNS requests from the Portmaster. The workaround presented in this post also successfully deals with this. -Similar systems are known to exist and are expected in other operating systems as well, so this change will better brace us for the next systems the Portmaster will be expanded to. +Similar systems are known to exist and are expected in other operating systems as well, so this change will better brace us for the next systems we plan to support as well. In addition to that, we now also have more information available on network connections, which will make future features, such as the connection history, even more powerful. -### Portmaster Changelog +### Portmaster Changelog Summary Here is a full list of changes that this workaround brings: - Domains may be wrongly attributed to connections a bit more often than before. From 76cbf78915a8750ef1e2ea91f9226d26b1353f6e Mon Sep 17 00:00:00 2001 From: davegson <3080765+davegson@users.noreply.github.com> Date: Tue, 23 Mar 2021 12:33:12 +0100 Subject: [PATCH 09/10] Add cover image source not required, but still a nice thing to do --- _posts/2021-03-23-attributing-dns-requests-on-windows.md | 1 + 1 file changed, 1 insertion(+) diff --git a/_posts/2021-03-23-attributing-dns-requests-on-windows.md b/_posts/2021-03-23-attributing-dns-requests-on-windows.md index fce8bf6..8d8f967 100644 --- a/_posts/2021-03-23-attributing-dns-requests-on-windows.md +++ b/_posts/2021-03-23-attributing-dns-requests-on-windows.md @@ -4,6 +4,7 @@ date: 2021-03-23 author: daniel custom_thumbnail_name: devlog category: "Dev Log" +cover_image_source: https://pixabay.com/photos/code-coding-web-development-944499/ --- For an application firewall it is crucial to know which processes query which domains. From 9af93c8d4c9792cf957d031b82c0e5d3088d60f3 Mon Sep 17 00:00:00 2001 From: davegson <3080765+davegson@users.noreply.github.com> Date: Tue, 23 Mar 2021 13:52:16 +0100 Subject: [PATCH 10/10] Tweak blog wording v3 implementing input from Daniel --- ...-23-attributing-dns-requests-on-windows.md | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/_posts/2021-03-23-attributing-dns-requests-on-windows.md b/_posts/2021-03-23-attributing-dns-requests-on-windows.md index 8d8f967..e0b5ca1 100644 --- a/_posts/2021-03-23-attributing-dns-requests-on-windows.md +++ b/_posts/2021-03-23-attributing-dns-requests-on-windows.md @@ -15,7 +15,7 @@ This sounds like an easy thing to achieve, but in practice it turns out to be a When we first looked into how to find this vital piece of information on Windows 10, we found that for some reason all DNS requests are sent from the "DNS-Client" Windows service. There were no DNS requests _to_ that service on the wire, just _from_ it. Upon further investigation we found that Windows applications use the `dnsapi.dll` for taking care of DNS requests: So whenever an application needs to resolve a dns query, for example in order to load a website, this `.dll` is loaded into the application and takes care of all the DNS details. -It then communicates directly with the DNS-Client via an internal IPC mechanism and does not even send a common DNS packet on the wire, which the Portmaster or any other process could see. +It then communicates directly with the DNS-Client via an internal IPC mechanism and does not even send a common DNS packet on the wire, which the Portmaster or any other firewall could see. @@ -28,12 +28,12 @@ When this is the case, the `dnsapi.dll` falls back to sending DNS requests on th -While researching this issue we found that disabling the DNS-Client actually seemed to be a rather much requested action and quite common for Windows users. This is done by setting the registry key `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Dnscache` from "Start" to "4" and then rebooting. -We decided to follow this easy route and just disable the DNS-Client upon installation, because it is only a caching stub resolver with no other functionality, right? Right? No. +While researching this issue we found that disabling the DNS-Client actually seemed to be a rather much requested action and quite common for Windows users. That is why we decided to follow this easy route and just disable the DNS-Client upon installation, because it is only a caching stub resolver with no other functionality, right? Right? No. As it turns out, the DNS-Client is much more than "just" a caching stub resolver. -Maybe it should have been a stronger hint to us that Microsoft removed the ability to directly stop the DNS-Client but instead requires the registry change and reboot. -However, the official Windows docs do not mention anything about there being more to the DNS-Client. They still "insist" that everything should work fine without it, but in reality the DNS-Client has become a critical and central part of Windows not to be tinkered with. + +In retrospect, maybe it should have been a stronger hint to us that Microsoft removed the ability to directly stop the DNS-Client from the service manager. We had to manually set the registry key `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Dnscache` -> `Start` from `2` to `4` and then reboot the system. +However, the official Windows docs do not mention anything about there being more to the DNS-Client. They imply that you can stop the DNS-Client from the service manager without side effects, when in reality the DNS-Client has to be disabled manually and has become a critical and central part of Windows not to be tinkered with. ### Turns Out: Deactivating the DNS-Client Causes Lots of Issues For Users @@ -43,54 +43,54 @@ With every report of another broken application that we could trace back to the ### Hijacking dnsapi.dll Was Ditched Because it Is Malware-ish -We went back to researching possibilities to somehow find out and attribute which processes query which domains. We found some "interesting" ways: +We went back to researching possibilities to somehow find out which processes query which domains. We found some "interesting" ways: There actually is a way to force the `dnsapi.dll` to fall back to sending DNS requests over the wire. Applications can specify the flag `DNS_QUERY_WIRE_ONLY` to the `.dll`, but forcing this globally would mean we would have to hijack the `dnsapi.dll`. -While some of you might find that this is a viable solution, hijacking - as the name suggests - is definitely edgy and likely already in the malware realm, and the Portmaster is no malware. +While some of you might find that this is a viable solution, hijacking - as the name suggests - is definitely edgy and something that malware commonly does; and the Portmaster is no malware. ### Replicating Windows Functionality Would Be a Nightmare -Something similar would be possible on the other end: We could just replace the full DNS-Client by disabling it and taking its place with our custom built replica. +Something similar would be possible on the other end: We could just replace the full DNS-Client by disabling it and taking its place with a custom built replica. While this is potentially a cleaner solution than hijacking, we already have had enough headaches from working with _documented_ Windows APIs. Touching _undocumented_ Windows stuff is pretty much nightmare material for engineers at this point. -### No per-App Settings Is Not an Option Too +### No per-App Settings Is Not an Option Either With no other options available to directly get the needed information, we were only left with one option: embrace the DNS-Client as it is, not deactivating it and accepting we get no process attribution via that route. But how could we then still be an effective Application Firewall? -The simplest way around the problem would be to ditch DNS request to process attribution altogether. So instead of caring which process sent the query and acting upon the per-app setting, you just act upon global settings. The drawback is obvious: no more per-app settings. So you could not browse facebook.com on your browser while blocking their nasty trackers everywhere else. The world becomes pretty binary. +The simplest way around the problem would be to ditch DNS request to process attribution altogether. So instead of caring which process sent the query and acting upon the per-app setting, one can solely act upon global settings. The drawback is obvious: no more per-app settings. So you could not browse facebook.com on your browser while blocking their nasty trackers everywhere else. The world becomes pretty binary. -So even though we would be able to keep our tight grip on the system, we want to empower users with all their nuanced needs. So this was not a solution we ever really considered. Instead, we continued our research to find a better balance between system control and per-app configurability. +Even though we would be able to keep our tight grip on the system, we want to empower users with all their nuanced needs. This was not a solution we ever really considered. Instead, we continued our research to find a better balance between system control and per-app configurability. ### The Solution: Intervene Later - When Network Connections Are Initiated In order to best protect user privacy, we need to know where applications are connecting to as early as possible. -The ideal and earliest place would have been the DNS request, which turned out not to be feasible anymore. Here, we now return a valid answer to most DNS requests coming from the DNS-Client. +The ideal and earliest place would have been the DNS request, which turned out not to be feasible anymore. We now return a valid answer to most DNS requests coming from the DNS-Client. The most notable exception to this is the Portmaster's Bypass Protection, which will continue to directly block DNS requests if it needs to, no matter where they come from. We think it is good to be strict in this case. The next possible place to intervene is when a process initiates a network connection (think TCP). -At this point, no data has left your device and we only have intel on the IPs, the ports and the originating process. In most cases, we do not yet know which (Layer 5) protocol will be used over the connection, or which domain is the target. +At this point, no data has left your device and we only know about the IPs, the ports and the originating process. In most cases, we do not yet know which (Layer 5) protocol will be used over the connection, or which domain is the target. -But what we can do here, is collect more intel. So whenever the Portmaster returns a valid DNS answer to a request - even if we do not know the real process behind it - we remember which IPs this domain resolved to. +But what we can do here, is collect more information. So whenever the Portmaster returns a valid DNS answer to a request - even if we do not know the real process behind it - we remember which IPs this domain resolved to. We scope this information into app-specific scopes or, when we do not know which app is really behind a DNS request, into a global scope. -In addition we also which resolver handled the request for us, so we have more information to work with later on. +In addition we also remember which resolver handled the request for us, so we have more information to work with later on. ### The Application Firewall Still Acts Before Any Data Leaves Your Device Now, back to our process that is initiating a new connection: -We can look up the remote IP address and see which domain we know of that resolves to the remote IP of the connection. -With this domain and all the other attached information we can now attribute the connection and make a decision about it. +We can now look up the remote IP address and see which domain we know of that resolves to the remote IP of the connection. +With this and all other attached information we can now attribute the connection to the domain and make an accurate decision about it. And this all happens before even a single bit of data leaves your device - we did it! Well, almost... As it turns out, there are some edge cases which might lead to side effects. Always expect to deal with side effects, especially on Windows. -### Side Effect: Wrong Attribution Is Now More Likely +### Side Effect: Wrong Attribution Is A Little More Likely Since remembered DNS requests which go through the DNS-Client are now pooled together in a global scope, this can sometimes lead to a wrong attribution of a domain to a connection. For example, if two processes use two different domains but both of them point to the same IP address, it could happen that the Portmaster thinks that the first process is connecting to the domain of the second process and vice-versa. Especially _if_ requests are done in parallel or connections are re-established without querying for the domain again. -This could also have happened before, when a single process sent its DNS requests directly to the Portmaster, but this was less likely. +This could also have happened before, when a single process sent its DNS requests directly to the Portmaster, but was less likely. As a remediation to this, we will start looking at HTTP headers and TLS handshakes in the future. With information gathered directly from the connection, the attribution will be more accurate.