杀掉本地进程其实很简单,取得进程ID后,调用OpenProcess函数打开进程句柄,然后调用TerminateProcess函数就可以杀掉进程了。有些情况下并不能直接打开进程句柄,例如WINLOGON等系统进程,因为权限不够。这个时候我们就得先提升自己的进程的权限了。提升权限过程也不复杂,先调用GetCurrentProcess函数取得当前进程的句柄,然后调用OpenProcessToken打开当前进程的访问令牌,接着调用LookupPrivilegeValue函数取得你想提升的权限的值,最后调用AdjustTokenPrivileges函数给当前进程的访问令牌增加权限就可以了。一般有了SeDebugPrivilege特权后,就可以杀掉除Idle外的所有进程了。
s=K?-O OK!那如何杀掉远程进程呢?说起来有点复杂,但其实也不难。
M D&7k,! <1>与远程系统建立IPC连接
oykb8~u}} <2>在远程系统的系统目录admin$\system32中写入一个文件killsrv.exe
5CfD/}{:#I <3>调用函数OpenSCManager打开远程系统的Service Control Manager[SCM]
U{@2kg- <4>调用函数CreateService在远程系统创建一个服务,服务指向的程序是在<2>中写入的程序killsrv.exe
(*T$:/zIS <5>调用函数StartService启动刚才创建的服务,把想杀掉的进程的ID作为参数传递给它
2P=~6( <6>服务启动后,killsrv.exe运行,杀掉进程
L{XW2c$h <7>清场
[{>1wJ Pdj 嗯!这样看来,我们需要两个程序了。Killsrv.exe的源代码如下:
g^jTdrW/s /***********************************************************************
vr6YE;Rs Module:Killsrv.c
/z}b1m+ Date:2001/4/27
=?\%E[j Author:ey4s
`Hu2a]e9 Http://www.ey4s.org :/"5x ***********************************************************************/
iMV=R2t 2 #include
:N_DJ51 #include
7e#|Iq:o #include "function.c"
AW!A+?F6 #define ServiceName "PSKILL"
iG=Di)O #D ]CuSi SERVICE_STATUS_HANDLE ssh;
,.|/B^jV SERVICE_STATUS ss;
{lppv(U /////////////////////////////////////////////////////////////////////////
U+["b-c void ServiceStopped(void)
m !i`|]m {
h$6~3^g:P ss.dwServiceType=SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;
0x^lHBYc ss.dwCurrentState=SERVICE_STOPPED;
5x,/p ss.dwControlsAccepted=SERVICE_ACCEPT_STOP;
e:rbyzf# ss.dwWin32ExitCode=NO_ERROR;
]8'PLsS9<w ss.dwCheckPoint=0;
P%!=Rj^ 2m ss.dwWaitHint=0;
Cm"S=gV SetServiceStatus(ssh,&ss);
vbG&F.P return;
43O5|8o }
2,|;qFJY-@ /////////////////////////////////////////////////////////////////////////
ID{XZ void ServicePaused(void)
Tgbq4xR( {
-]n%+,3L
ss.dwServiceType=SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;
3kwkU ss.dwCurrentState=SERVICE_PAUSED;
W|s";EAM ss.dwControlsAccepted=SERVICE_ACCEPT_STOP;
}EJ/H3< ss.dwWin32ExitCode=NO_ERROR;
i;29*" ss.dwCheckPoint=0;
hR.vJ2oa ss.dwWaitHint=0;
zW)Wt.svP SetServiceStatus(ssh,&ss);
RU>qj
*e return;
_w'_l>I }
@:>gRD void ServiceRunning(void)
~zWLqnS} {
hp2$[p6O ss.dwServiceType=SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;
h b8L[ 4 ss.dwCurrentState=SERVICE_RUNNING;
y3PrLBTz ss.dwControlsAccepted=SERVICE_ACCEPT_STOP;
{9^p3Q+:P ss.dwWin32ExitCode=NO_ERROR;
,^DP ss.dwCheckPoint=0;
B^ddi ss.dwWaitHint=0;
A<( DYd1H SetServiceStatus(ssh,&ss);
Ea-U+7JC return;
Qam48XZ > }
_8\B~;0 /////////////////////////////////////////////////////////////////////////
+!$`0v void WINAPI servier_ctrl(DWORD Opcode)//服务控制程序
}WBHuVcZG {
q1ZZ T"' switch(Opcode)
ojA !!Ru {
Ap4.c8f?Q- case SERVICE_CONTROL_STOP://停止Service
$~%h4 ServiceStopped();
4x#tUzb; break;
lXzm) case SERVICE_CONTROL_INTERROGATE:
!aL=R)G&e SetServiceStatus(ssh,&ss);
_c5*9')-) break;
4:/^ .: }
- leYR`P return;
|f.,fVVV; }
Q7tvpU //////////////////////////////////////////////////////////////////////////////
6GqC]rd*: //杀进程成功设置服务状态为SERVICE_STOPPED
$ \o)-3 //失败设置服务状态为SERVICE_PAUSED
tvq((2 //
#l7v|)9v void WINAPI ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv)
B<a` o&? {
eg1F[~YL/ ssh=RegisterServiceCtrlHandler(ServiceName,servier_ctrl);
,(f W0d# if(!ssh)
@~UQU)-( {
;P/ 4.|< ServicePaused();
GS}JyU return;
9jM7z/Ff }
DVJn;X^T: ServiceRunning();
{];-b0MS~ Sleep(100);
n+i=Ff
//注意,argv[0]为此程序名,argv[1]为pskill,参数需要递增1
KD H<T4#x //argv[2]=target,argv[3]=user,argv[4]=pwd,argv[5]=pid
:F@goiuC if(KillPS(atoi(lpszArgv[5])))
A
r>BL2@ ServiceStopped();
=q`T|9v else
"^;h' ServicePaused();
.0~uM!3y return;
i$<")q }
ou<,c?nNM /////////////////////////////////////////////////////////////////////////////
4??LK/s* void main(DWORD dwArgc,LPTSTR *lpszArgv)
Fop +xR,Z {
YhqMTOw SERVICE_TABLE_ENTRY ste[2];
gx?r8 ste[0].lpServiceName=ServiceName;
NK(_ &.F
ste[0].lpServiceProc=ServiceMain;
M CP GDr ste[1].lpServiceName=NULL;
2% OAQ( ste[1].lpServiceProc=NULL;
()F{kM8 StartServiceCtrlDispatcher(ste);
1xkrhqq return;
ZmNNR 1%/ }
p(8 @ /////////////////////////////////////////////////////////////////////////////
*c&|2EsZ function.c中有两个函数,一个是提升权限的,一个是提供进程ID,杀进程的。代码如
x}V&v?1{5 下:
^H{YLO /***********************************************************************
=Vazxt@[ Module:function.c
'
2O@ Date:2001/4/28
nAAv42j[ Author:ey4s
e?*Teb?R Http://www.ey4s.org
*
1xs/$` ***********************************************************************/
#.$y #include
R^P>yk8 ////////////////////////////////////////////////////////////////////////////
RVLVY:h|F BOOL SetPrivilege(HANDLE hToken,LPCTSTR lpszPrivilege,BOOL bEnablePrivilege)
4RYH^9;>K {
@qj]`}Gx' TOKEN_PRIVILEGES tp;
|r36iUHZS LUID luid;
Id>4fF:o t8rFn if(!LookupPrivilegeValue(NULL,lpszPrivilege,&luid))
D|Wlq~IpQ {
D}j`T printf("\nLookupPrivilegeValue error:%d", GetLastError() );
kxJ[Bi# return FALSE;
j0V/\Ep)T< }
Pd(_ tp.PrivilegeCount = 1;
tMp!MQ
tp.Privileges[0].Luid = luid;
{*[(j^OE if (bEnablePrivilege)
{ I\og tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
SY%y *6[6 else
0y?;o*&U\ tp.Privileges[0].Attributes = 0;
pRL:,q\ // Enable the privilege or disable all privileges.
( }Bb=~ AdjustTokenPrivileges(
UxzF5V5 hToken,
2Q5 @2jT FALSE,
Hbd>sS &tp,
w`V6vYd@ sizeof(TOKEN_PRIVILEGES),
.R'M'a#*!A (PTOKEN_PRIVILEGES) NULL,
Y0A(-" (PDWORD) NULL);
;FRUB@: // Call GetLastError to determine whether the function succeeded.
_vDmiIn6K if (GetLastError() != ERROR_SUCCESS)
1EEcNtpub] {
NRx I?v printf("AdjustTokenPrivileges failed: %u\n", GetLastError() );
#jW=K&; return FALSE;
TjYHoL5 }
y_=y% return TRUE;
#kq!{5, }
x\8|A ////////////////////////////////////////////////////////////////////////////
3}F>t{FDk BOOL KillPS(DWORD id)
El;"7Qn {
Jou*e% HANDLE hProcess=NULL,hProcessToken=NULL;
tqCkqmyC BOOL IsKilled=FALSE,bRet=FALSE;
' BS.:^ __try
(;%T]?<9# {
@z{SDM Qz#By V: if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hProcessToken))
wK#*| {
b \ln XN printf("\nOpen Current Process Token failed:%d",GetLastError());
?4Rd4sIM$u __leave;
V|$PO
Qa3 }
p?,<{mAe //printf("\nOpen Current Process Token ok!");
"wTCO1 if(!SetPrivilege(hProcessToken,SE_DEBUG_NAME,TRUE))
o5NmNOXm {
^jwzCo- __leave;
t'@mUX:-A }
J ~3m7 printf("\nSetPrivilege ok!");
t^FE]$, fx[&"$X if((hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,id))==NULL)
Ez5t)l- {
;p`to"6IFD printf("\nOpen Process %d failed:%d",id,GetLastError());
~uty<fP __leave;
/pPH D] }
PQ[?zNrSV //printf("\nOpen Process %d ok!",id);
X )tH23 if(!TerminateProcess(hProcess,1))
h72/03! {
V3q`V/\ printf("\nTerminateProcess failed:%d",GetLastError());
hRu}P" __leave;
$5)#L$!,] }
NimgU Fa IsKilled=TRUE;
(EY@{'.& }
MyllL@kP __finally
0#!}s&j/ {
Y6VJr+Ap( if(hProcessToken!=NULL) CloseHandle(hProcessToken);
A#T"4'#?< if(hProcess!=NULL) CloseHandle(hProcess);
PENB5+1OK }
!V3+(o1 return(IsKilled);
:VZS7$5 }
~io. TS|r //////////////////////////////////////////////////////////////////////////////////////////////
[Tp?u8$p` OK!服务端的程序已经好了。接下来还需要一个客户端。如果通过在客户端运行的时候,把killsrv.exe COPY到远程系统上,那么就需要提供两个exe文件给用户,这样显得不是很专业,呵呵。不如我们就把killsrv.exe的二进制码作为buff保存在客户端吧,这样在运行的时候,我们直接把buff中的内容写过去,这样提供给用户一个exe文件就可以了。Pskill.c的源代码如下:
Zja3HGL /*********************************************************************************************
AG=PbY9 ModulesKill.c
0P9\; !Y Create:2001/4/28
dR1IndZl Modify:2001/6/23
*YvtT(Gt Author:ey4s
;'8P/a$ Http://www.ey4s.org d\]KG(T PsKill ==>Local and Remote process killer for windows 2k
%bN{FKNN **************************************************************************/
LkS tU) #include "ps.h"
eTvjo(Lvx #define EXE "killsrv.exe"
ZZI}
Ot{ #define ServiceName "PSKILL"
+u0of^}=
r+E!V'{C #pragma comment(lib,"mpr.lib")
|xFA} //////////////////////////////////////////////////////////////////////////
~rdS#f&R2 //定义全局变量
ZF[W<Q SERVICE_STATUS ssStatus;
1LRP
R@b^ SC_HANDLE hSCManager=NULL,hSCService=NULL;
[,AFtg[ BOOL bKilled=FALSE;
&kmaKc char szTarget[52]=;
if|5v^/ //////////////////////////////////////////////////////////////////////////
9=MNuV9/s BOOL ConnIPC(char *,char *,char *);//建立IPC连接函数
}_zN%Tf~ BOOL InstallService(DWORD,LPTSTR *);//安装服务函数
i~]60M> BOOL WaitServiceStop();//等待服务停止函数
h$!YKfhq} BOOL RemoveService();//删除服务函数
@i>)x*I#AI /////////////////////////////////////////////////////////////////////////
BNCM{}e int main(DWORD dwArgc,LPTSTR *lpszArgv)
'`k7l7I[@ {
|f fHOef BOOL bRet=FALSE,bFile=FALSE;
K?'m#}] char tmp[52]=,RemoteFilePath[128]=,
)2?]c szUser[52]=,szPass[52]=;
zMbFh_dcq HANDLE hFile=NULL;
w!6{{m DWORD i=0,dwIndex=0,dwWrite,dwSize=sizeof(exebuff);
Y:TfD{Xgc QjY}$ //杀本地进程
7CH&n4v if(dwArgc==2)
KJec/qca {
}'eef"DJ9 if(KillPS(atoi(lpszArgv[1])))
a~0 ~Y y printf("\nLoacl Process %s have beed killed!",lpszArgv[1]);
FXJ0
G>F else
%u66H2 printf("\nLoacl Process %s can't be killed!ErrorCode:%d",
>:6iFPP lpszArgv[1],GetLastError());
M> WWP3 return 0;
z.-yL,Rc`- }
Eb4NPWo //用户输入错误
";rXCH. else if(dwArgc!=5)
)Su>8f[?e {
`D[O\ VE printf("\nPSKILL ==>Local and Remote Process Killer"
~F'6k&A^q "\nPower by ey4s"
m_/Ut "\nhttp://www.ey4s.org 2001/6/23"
,FzkGB# "\n\nUsage:%s <==Killed Local Process"
JT0j2_*Rr "\n %s <==Killed Remote Process\n",
XYWyxx5` lpszArgv[0],lpszArgv[0]);
%eDSo9Y return 1;
~O\A 0e }
VtLRl0/ //杀远程机器进程
@rbd`7$% strncpy(szTarget,lpszArgv[1],sizeof(szTarget)-1);
azv173XZ strncpy(szUser,lpszArgv[2],sizeof(szUser)-1);
)v_Wn[Y.H strncpy(szPass,lpszArgv[3],sizeof(szPass)-1);
T"vf Q/]~`S //将在目标机器上创建的exe文件的路径
cmXbkM sprintf(RemoteFilePath,"\\%s\admin$\system32\%s",szTarget,EXE);
VU,G.eLW __try
#wIWh^^ Zy {
u>lt}0 //与目标建立IPC连接
g,JfT^ if(!ConnIPC(szTarget,szUser,szPass))
.4%z$(+6 {
3(V0,L'1 printf("\nConnect to %s failed:%d",szTarget,GetLastError());
qo3+=*"V return 1;
Lf5zHUH }
}lp37, printf("\nConnect to %s success!",szTarget);
l3Zi]`@r //在目标机器上创建exe文件
I;'{X_9$a Nt$4; hFile=CreateFile(RemoteFilePath,GENERIC_ALL,FILE_SHARE_READ|FILE_SHARE_WRIT
]YI9 E,
eX#.Zt] NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
&qg6^& if(hFile==INVALID_HANDLE_VALUE)
yx|iZhK0:} {
y-E'Y=j printf("\nCreate file %s failed:%d",RemoteFilePath,GetLastError());
Q O =5Q __leave;
^ l#6Es }
GV0@We~ //写文件内容
:L@;.s while(dwSize>dwIndex)
~o_JZ: {
L-`V^{R] lW|=rq-| if(!WriteFile(hFile,&exebuff[dwIndex],dwSize-dwIndex,&dwWrite,NULL))
x,mt}> {
-6DRX printf("\nWrite file %s
`$> Y failed:%d",RemoteFilePath,GetLastError());
cS%dTrfo __leave;
<?B3^z$ }
hdw.S`~}% dwIndex+=dwWrite;
#l}Fk)dj }
ljK?2z> //关闭文件句柄
`]W9Fj<1j CloseHandle(hFile);
:-jbIpj' bFile=TRUE;
H14Q-2U1xa //安装服务
OS#aYER~/ if(InstallService(dwArgc,lpszArgv))
>G|RVB {
B$rhsK% //等待服务结束
x"q]~u<rB if(WaitServiceStop())
FcM)v"bF&] {
1?&|V1vc //printf("\nService was stoped!");
eXKEx4rU }
;&=jSgr8 else
SN@>m pcJS {
Dc0=gq0 //printf("\nService can't be stoped.Try to delete it.");
!+3&%vQ) }
U3&GRY|## Sleep(500);
3;L$&X2 //删除服务
Q*<KX2O RemoveService();
X:s~w#>R }
LujLC&S }
i
FZGfar? __finally
gf>H-718F {
;7s^slVzF //删除留下的文件
_{'[Uf/l if(bFile) DeleteFile(RemoteFilePath);
+m./RlQ{ //如果文件句柄没有关闭,关闭之~
jz"
>Kh.} if(hFile!=NULL) CloseHandle(hFile);
8zHx$g //Close Service handle
v K{2 if(hSCService!=NULL) CloseServiceHandle(hSCService);
DRm`y>. //Close the Service Control Manager handle
CjPdN#*l if(hSCManager!=NULL) CloseServiceHandle(hSCManager);
^|Z'}p|& //断开ipc连接
a&JY x wsprintf(tmp,"\\%s\ipc$",szTarget);
VLm\P S
WNetCancelConnection2(tmp,CONNECT_UPDATE_PROFILE,TRUE);
yJ!26 if(bKilled)
~4+Y BN printf("\nProcess %s on %s have been
'sIne> killed!\n",lpszArgv[4],lpszArgv[1]);
O W.CU=XU else
w98M#GqV printf("\nProcess %s on %s can't be
VX8rM!3 killed!\n",lpszArgv[4],lpszArgv[1]);
1_{ e*=/y }
H4`>B>\ return 0;
.pPuBJL]< }
b|AjB: G //////////////////////////////////////////////////////////////////////////
wzy[sB274 BOOL ConnIPC(char *RemoteName,char *User,char *Pass)
J#C4A]A {
@}6<,;|DQ NETRESOURCE nr;
H,TApF89A char RN[50]="\\";
"=DQ { (L #EUT"^:d strcat(RN,RemoteName);
3\RD%[} strcat(RN,"\ipc$");
qZ!kVrmg& @>(JC]HtR nr.dwType=RESOURCETYPE_ANY;
T&[6 nr.lpLocalName=NULL;
KH#z =_ nr.lpRemoteName=RN;
5nib<B%<V nr.lpProvider=NULL;
;!f~ _5S0A0 if(WNetAddConnection2(&nr,Pass,User,FALSE)==NO_ERROR)
KC}G_"f.$ return TRUE;
gnZ#86sO else
*
;sz/. return FALSE;
6rbR0dSgx }
+i}H $.
/////////////////////////////////////////////////////////////////////////
e~
OrZhJ=_ BOOL InstallService(DWORD dwArgc,LPTSTR *lpszArgv)
%' WC7s {
qery|0W BOOL bRet=FALSE;
sT1k]duT __try
;R0LJApey {
B ZU@W%E //Open Service Control Manager on Local or Remote machine
3M?O(oO hSCManager=OpenSCManager(szTarget,NULL,SC_MANAGER_ALL_ACCESS);
%1p-DX6 if(hSCManager==NULL)
%|x9C,0p# {
neu<zSS printf("\nOpen Service Control Manage failed:%d",GetLastError());
(L4llZ;q __leave;
!+$QN4{9 }
;5;>f)diS //printf("\nOpen Service Control Manage ok!");
1 .@{5f3T //Create Service
`EgX# hSCService=CreateService(hSCManager,// handle to SCM database
??e|ec2% ServiceName,// name of service to start
(&79}IEd ServiceName,// display name
.*6NqX$ SERVICE_ALL_ACCESS,// type of access to service
'eBD/w5U SERVICE_WIN32_OWN_PROCESS,// type of service
~roNe|P SERVICE_AUTO_START,// when to start service
)0E_Y@ SERVICE_ERROR_IGNORE,// severity of service
'%/=\Q` failure
-cU bIbW EXE,// name of binary file
*2/qm:gB NULL,// name of load ordering group
tt-ci,X+ NULL,// tag identifier
MzB.Vvsy%9 NULL,// array of dependency names
<LH6my NULL,// account name
\YJQN3^46> NULL);// account password
vbJdhaf //create service failed
6I(Y<LZ5 if(hSCService==NULL)
KW'nW {
>!Y#2]@}o //如果服务已经存在,那么则打开
^7>~y( if(GetLastError()==ERROR_SERVICE_EXISTS)
5q@s6_"{ {
eb}XooX //printf("\nService %s Already exists",ServiceName);
5-0&`, //open service
8fi'" hSCService = OpenService(hSCManager, ServiceName,
OU` !c[O SERVICE_ALL_ACCESS);
E8PwA. if(hSCService==NULL)
*MfH\X379 {
mEYfsO printf("\nOpen Service failed:%d",GetLastError());
fX:q] __leave;
2?LPr }
<WWZb\"{ //printf("\nOpen Service %s ok!",ServiceName);
WYRC_U7 }
eK(k;$4\^Y else
c]1AM)xo {
tc.|mIvw printf("\nCreateService failed:%d",GetLastError());
o_=4Ex
" __leave;
@Oz3A<M }
~pH!.|k-& }
sa<\nH$_X //create service ok
;~r- P$kCY else
19[o XyFI {
,
0X J|#% //printf("\nCreate Service %s ok!",ServiceName);
+MHIZI }
*ze/$vz- 8(-
29 // 起动服务
4 5wqX h if ( StartService(hSCService,dwArgc,lpszArgv))
_~tF2`,Y_p {
id+EBVHAd //printf("\nStarting %s.", ServiceName);
:I/9j=@1 Sleep(20);//时间最好不要超过100ms
HZ!<dy3 while( QueryServiceStatus(hSCService, &ssStatus ) )
z|],s]F>G {
-]}#Z:& if ( ssStatus.dwCurrentState == SERVICE_START_PENDING)
lmUCrs37 {
5`&@3
m9/ printf(".");
4`o0?_.' Sleep(20);
vq9O|E3 }
IDpLf*vSG else
@g`|ob]9 break;
#a@ jt }
W,,3@: if ( ssStatus.dwCurrentState != SERVICE_RUNNING )
m4uh<;C~ printf("\n%s failed to run:%d",ServiceName,GetLastError());
dm_Pz\* }
qp*~| else if(GetLastError()==ERROR_SERVICE_ALREADY_RUNNING)
.PT7 {
F@ |( //printf("\nService %s already running.",ServiceName);
@6|0H`kv }
[oBRH]9cq
else
Ivcy=W=Jk {
hN0h'JJ[7 printf("\nStart Service %s failed:%d",ServiceName,GetLastError());
T
;84Sv __leave;
"+ {2! }
?HOnDw.v1 bRet=TRUE;
U7/
=|Z }//enf of try
SR.xI:}4 __finally
G3!O@j!7w$ {
K5bR7f: return bRet;
[giw(4m#y }
"WmsBdO return bRet;
'-~J.8-</ }
w AdaP9h /////////////////////////////////////////////////////////////////////////
N`,,sw BOOL WaitServiceStop(void)
w(S&X"~ {
`'r~3kP*NT BOOL bRet=FALSE;
1x/ R //printf("\nWait Service stoped");
8kd):gZKZ while(1)
HnFH|H<Uf {
Q A~F
Sleep(100);
L{;Q6_m if(!QueryServiceStatus(hSCService, &ssStatus))
BuAzO>= {
!jEV75 printf("\nQueryServiceStatus failed:%d",GetLastError());
"p+oi@ break;
iM9k!u FE }
xrY >Or if(ssStatus.dwCurrentState==SERVICE_STOPPED)
c>c4IQ&d {
"5$p=| bKilled=TRUE;
bs%
RWwn bRet=TRUE;
FB,rQ9D break;
s/>0gu]A8 }
./DlHS; if(ssStatus.dwCurrentState==SERVICE_PAUSED)
>D##94PZ {
h<'tQGC //停止服务
1W0[|Hf2v* bRet=ControlService(hSCService,SERVICE_CONTROL_STOP,NULL);
)B-[Q#*A- break;
#@V<{/;49 }
.2rpQa/h else
Z3Ww@&bU