杀掉本地进程其实很简单,取得进程ID后,调用OpenProcess函数打开进程句柄,然后调用TerminateProcess函数就可以杀掉进程了。有些情况下并不能直接打开进程句柄,例如WINLOGON等系统进程,因为权限不够。这个时候我们就得先提升自己的进程的权限了。提升权限过程也不复杂,先调用GetCurrentProcess函数取得当前进程的句柄,然后调用OpenProcessToken打开当前进程的访问令牌,接着调用LookupPrivilegeValue函数取得你想提升的权限的值,最后调用AdjustTokenPrivileges函数给当前进程的访问令牌增加权限就可以了。一般有了SeDebugPrivilege特权后,就可以杀掉除Idle外的所有进程了。
L%f-L.9`u OK!那如何杀掉远程进程呢?说起来有点复杂,但其实也不难。
t/ A:k <1>与远程系统建立IPC连接
VcP:}a< B\ <2>在远程系统的系统目录admin$\system32中写入一个文件killsrv.exe
VZ;@S3TS <3>调用函数OpenSCManager打开远程系统的Service Control Manager[SCM]
O)l%OOv <4>调用函数CreateService在远程系统创建一个服务,服务指向的程序是在<2>中写入的程序killsrv.exe
%j%%Rn <5>调用函数StartService启动刚才创建的服务,把想杀掉的进程的ID作为参数传递给它
6{L F-`S% <6>服务启动后,killsrv.exe运行,杀掉进程
V!mWn|lf <7>清场
"@(58nk 嗯!这样看来,我们需要两个程序了。Killsrv.exe的源代码如下:
OO$|9`a /***********************************************************************
ACgt"
M.3F Module:Killsrv.c
61G|?Aax Date:2001/4/27
-H4PRCDH Author:ey4s
JW-|<CJ Http://www.ey4s.org X!o@f$ ***********************************************************************/
.-J`d=Krp #include
S3; lKr #include
L+Eu
d #include "function.c"
9wzwY[{ #define ServiceName "PSKILL"
!`Le`c b"^\)|*4; SERVICE_STATUS_HANDLE ssh;
Xp#~N_S$ SERVICE_STATUS ss;
/GyEV Cc /////////////////////////////////////////////////////////////////////////
ZH% we void ServiceStopped(void)
Ohc^d"[7 {
K@HLIuz4t ss.dwServiceType=SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;
W.IH#`-9E ss.dwCurrentState=SERVICE_STOPPED;
cFw3Iw"JJ ss.dwControlsAccepted=SERVICE_ACCEPT_STOP;
O
/vWd" ss.dwWin32ExitCode=NO_ERROR;
%,XI]+d ss.dwCheckPoint=0;
T=.-Cl1A ss.dwWaitHint=0;
QJQJR/g SetServiceStatus(ssh,&ss);
D_Guc8* return;
n7@j}Q(&? }
@$Yb#$/ /////////////////////////////////////////////////////////////////////////
rj}(muM,R void ServicePaused(void)
Mg+4huT {
-gB{:UYi3 ss.dwServiceType=SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;
!1("(Eb ss.dwCurrentState=SERVICE_PAUSED;
!W(`<d]68: ss.dwControlsAccepted=SERVICE_ACCEPT_STOP;
lelMt= ss.dwWin32ExitCode=NO_ERROR;
SGQDro=l ss.dwCheckPoint=0;
Jlz9E|*qV ss.dwWaitHint=0;
<W?WUF SetServiceStatus(ssh,&ss);
7O"hiDQ return;
("b*? : B }
_OLI%o void ServiceRunning(void)
yk`)Cq%=; {
3\]~!;dI ss.dwServiceType=SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;
K,6OGsh ss.dwCurrentState=SERVICE_RUNNING;
C]M7GHe1q ss.dwControlsAccepted=SERVICE_ACCEPT_STOP;
\,hrk~4U;( ss.dwWin32ExitCode=NO_ERROR;
#.o0mguU ss.dwCheckPoint=0;
Q]^Yi1PbS ss.dwWaitHint=0;
h+5@I%WX SetServiceStatus(ssh,&ss);
LGAX"/LX return;
pG~'shD~Dn }
.ByU /////////////////////////////////////////////////////////////////////////
@\!ww/QT void WINAPI servier_ctrl(DWORD Opcode)//服务控制程序
(xbIUz. {
db'K!M) switch(Opcode)
2?*||c==* {
X'jr|s^s case SERVICE_CONTROL_STOP://停止Service
{-J:4*` ServiceStopped();
3h LqAj break;
72u db^ case SERVICE_CONTROL_INTERROGATE:
:1*zr SetServiceStatus(ssh,&ss);
9Eu #lV break;
sLZ>v }
6A.P6DW return;
{79qtq%W{ }
Rh[Ib m56 //////////////////////////////////////////////////////////////////////////////
vn ``0!FX //杀进程成功设置服务状态为SERVICE_STOPPED
(m/aV //失败设置服务状态为SERVICE_PAUSED
=D}4X1l //
.8:+MW/ void WINAPI ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv)
M.S
s:ttj {
wW^Zb ssh=RegisterServiceCtrlHandler(ServiceName,servier_ctrl);
-IbbPuRq if(!ssh)
9|<Be6 {
y)tYSTJK ServicePaused();
e+l\\9v return;
9N^+IZ@l }
QE3ryD ServiceRunning();
x_k S
g Sleep(100);
<$Z tik1 //注意,argv[0]为此程序名,argv[1]为pskill,参数需要递增1
fy`+Efuj //argv[2]=target,argv[3]=user,argv[4]=pwd,argv[5]=pid
gd_^ if(KillPS(atoi(lpszArgv[5])))
p0Z:Wkz] ServiceStopped();
8!;$qVt else
|UYED%dC ServicePaused();
Ox~ 9_d return;
l0. FiO@_Q }
bb}?h]a /////////////////////////////////////////////////////////////////////////////
IqNpLh|[ void main(DWORD dwArgc,LPTSTR *lpszArgv)
$e*B:}x} {
k8
u%$G SERVICE_TABLE_ENTRY ste[2];
m9woredS, ste[0].lpServiceName=ServiceName;
"Tv:*L5 ste[0].lpServiceProc=ServiceMain;
`[OXVs,7" ste[1].lpServiceName=NULL;
GyuV
% ste[1].lpServiceProc=NULL;
=&N$Vqn StartServiceCtrlDispatcher(ste);
-<PC"B return;
&kiF/F 1 }
aLYLd/ KV /////////////////////////////////////////////////////////////////////////////
(![t_r0 function.c中有两个函数,一个是提升权限的,一个是提供进程ID,杀进程的。代码如
R5gado 下:
dl_{iMhF&E /***********************************************************************
0U%Xm[: Module:function.c
|/*pT1(& Date:2001/4/28
/LF3O~Go Author:ey4s
UUH;L Http://www.ey4s.org fx]eDA|$e ***********************************************************************/
nc&Jmo7 #include
OT;cfkf7 ////////////////////////////////////////////////////////////////////////////
-zTEL(r BOOL SetPrivilege(HANDLE hToken,LPCTSTR lpszPrivilege,BOOL bEnablePrivilege)
BJgDo {
E23w *'] TOKEN_PRIVILEGES tp;
NHAH#7]M&1 LUID luid;
bNXAU\M^ @C=M
UT-! if(!LookupPrivilegeValue(NULL,lpszPrivilege,&luid))
#52NsVaT@ {
v&r=-}z2! printf("\nLookupPrivilegeValue error:%d", GetLastError() );
u1N1n;# return FALSE;
^aHh{BQ% }
GQ[pG{_+ tp.PrivilegeCount = 1;
=LK}9ViH tp.Privileges[0].Luid = luid;
ikIzhUWE if (bEnablePrivilege)
kZv*rWAm tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
9ad6uTc else
<wa(xDBw tp.Privileges[0].Attributes = 0;
`36N
n+A // Enable the privilege or disable all privileges.
k2.G%]j AdjustTokenPrivileges(
{@45?L(' hToken,
=zOeb/ FALSE,
eC;!YGZ &tp,
J.W Ho
c sizeof(TOKEN_PRIVILEGES),
ED/FlL{ (PTOKEN_PRIVILEGES) NULL,
y1#O%=g (PDWORD) NULL);
R*\~k%Z // Call GetLastError to determine whether the function succeeded.
r:NH6tAL if (GetLastError() != ERROR_SUCCESS)
&XtRLtgS {
{_(+>v"eJ printf("AdjustTokenPrivileges failed: %u\n", GetLastError() );
Zih ?Bm return FALSE;
lV)G@l[1 }
NpR6 return TRUE;
cQn)^jx= }
[@|be.g ////////////////////////////////////////////////////////////////////////////
A="fj BOOL KillPS(DWORD id)
Ye@t_,)x {
n,sY\=vB HANDLE hProcess=NULL,hProcessToken=NULL;
rVcBl4&1*g BOOL IsKilled=FALSE,bRet=FALSE;
OX^3Q:Z= __try
s/h7G}Mu {
wVE:X3Ei M~p=#V1D if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hProcessToken))
~#Aa Ldq {
r)8z#W>s printf("\nOpen Current Process Token failed:%d",GetLastError());
cix36MR_ __leave;
f?maa5S }
^j=bObaX //printf("\nOpen Current Process Token ok!");
${>DhfF if(!SetPrivilege(hProcessToken,SE_DEBUG_NAME,TRUE))
JGgxAd{L {
<m]wi7 __leave;
S=PJhAF }
W&KM/9d printf("\nSetPrivilege ok!");
S(w\Z C )x[HuIRaa if((hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,id))==NULL)
-TS?
fne) {
bE4HDq34 printf("\nOpen Process %d failed:%d",id,GetLastError());
AerFgQiS __leave;
7wi%j! }
Q;wB{vr$ //printf("\nOpen Process %d ok!",id);
c{VJ2NQ+ if(!TerminateProcess(hProcess,1))
N5!&~~ {
,E9d\+j printf("\nTerminateProcess failed:%d",GetLastError());
anC+r(jjg9 __leave;
eO[c l B }
8^vArS; IsKilled=TRUE;
P#*n3&Uu }
!.-.#<<_a __finally
)8'jxiGs {
4|f}F if(hProcessToken!=NULL) CloseHandle(hProcessToken);
`)tA
YH if(hProcess!=NULL) CloseHandle(hProcess);
PUCx]5 }
~K`1 return(IsKilled);
bjzx!OCpV }
Ow)R|/e/ //////////////////////////////////////////////////////////////////////////////////////////////
R&Ci/ OK!服务端的程序已经好了。接下来还需要一个客户端。如果通过在客户端运行的时候,把killsrv.exe COPY到远程系统上,那么就需要提供两个exe文件给用户,这样显得不是很专业,呵呵。不如我们就把killsrv.exe的二进制码作为buff保存在客户端吧,这样在运行的时候,我们直接把buff中的内容写过去,这样提供给用户一个exe文件就可以了。Pskill.c的源代码如下:
.[(P /*********************************************************************************************
TY6
rwU ModulesKill.c
+NR n0
z( Create:2001/4/28
* <q4S(l Modify:2001/6/23
K(OaW)j Author:ey4s
3I*uV!notJ Http://www.ey4s.org ]nc2/S% PsKill ==>Local and Remote process killer for windows 2k
DY.58IHg1 **************************************************************************/
l{Er+)a #include "ps.h"
u E.^w;~2= #define EXE "killsrv.exe"
pBU]=[M0 #define ServiceName "PSKILL"
k FLT!k }NwN2xTB #pragma comment(lib,"mpr.lib")
"@)lH //////////////////////////////////////////////////////////////////////////
=:/>6H1x //定义全局变量
L$hc, SERVICE_STATUS ssStatus;
R@n5AN( SC_HANDLE hSCManager=NULL,hSCService=NULL;
mPG7Zy$z BOOL bKilled=FALSE;
lD3)TAW@o char szTarget[52]=;
7Ud'd< //////////////////////////////////////////////////////////////////////////
]]/lC BOOL ConnIPC(char *,char *,char *);//建立IPC连接函数
xiCN
qk3 BOOL InstallService(DWORD,LPTSTR *);//安装服务函数
PpFsp( )x BOOL WaitServiceStop();//等待服务停止函数
^1VbH3M BOOL RemoveService();//删除服务函数
e1uMR-Q /////////////////////////////////////////////////////////////////////////
2LK]Q/WG,+ int main(DWORD dwArgc,LPTSTR *lpszArgv)
]3+`` vL {
5Eal1Qu BOOL bRet=FALSE,bFile=FALSE;
'=#5(O%pp char tmp[52]=,RemoteFilePath[128]=,
O9e.=l szUser[52]=,szPass[52]=;
Ux_<d?p HANDLE hFile=NULL;
GX5W^//} DWORD i=0,dwIndex=0,dwWrite,dwSize=sizeof(exebuff);
liD47}+ `xIh\q //杀本地进程
tW(+xu36 if(dwArgc==2)
)eq}MaW+j {
@yKZRwg if(KillPS(atoi(lpszArgv[1])))
rS,j;8D- printf("\nLoacl Process %s have beed killed!",lpszArgv[1]);
~p.%.b;~t else
\JU{xQMB printf("\nLoacl Process %s can't be killed!ErrorCode:%d",
bKUyBk,\# lpszArgv[1],GetLastError());
J7n5Ps\M return 0;
w_3xKnMT\ }
g ;LVECk //用户输入错误
BSDk9Oc else if(dwArgc!=5)
7E\gxQ(vU {
f3t.T=S printf("\nPSKILL ==>Local and Remote Process Killer"
B1+ZFQo "\nPower by ey4s"
ugxw!cj "\nhttp://www.ey4s.org 2001/6/23"
m}pL`:e! "\n\nUsage:%s <==Killed Local Process"
f~*K {7 "\n %s <==Killed Remote Process\n",
l5HWZs^ lpszArgv[0],lpszArgv[0]);
HlRAD|]\ return 1;
oLP]N$'# }
ppFYc\&= //杀远程机器进程
n ,1tD strncpy(szTarget,lpszArgv[1],sizeof(szTarget)-1);
ZqP7@fO_% strncpy(szUser,lpszArgv[2],sizeof(szUser)-1);
#TATqzA strncpy(szPass,lpszArgv[3],sizeof(szPass)-1);
+c r 1|/'"9v //将在目标机器上创建的exe文件的路径
Rf:<-C0T sprintf(RemoteFilePath,"\\%s\admin$\system32\%s",szTarget,EXE);
J#(,0h __try
o&,Y<$!:VH {
R9vY:oN% //与目标建立IPC连接
^6qjSfFW} if(!ConnIPC(szTarget,szUser,szPass))
|*E"G5WZM {
8}z3CuM printf("\nConnect to %s failed:%d",szTarget,GetLastError());
4 l1 i>_R return 1;
ns26$bU }
gQR1$n0 printf("\nConnect to %s success!",szTarget);
9FNwpL'C //在目标机器上创建exe文件
k(v"B@0
uS-3\$ hFile=CreateFile(RemoteFilePath,GENERIC_ALL,FILE_SHARE_READ|FILE_SHARE_WRIT
6F-JK1i E,
J[r^T&o NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
ls]H6z*q if(hFile==INVALID_HANDLE_VALUE)
C$K+=jT {
R'Eq:Rv~;^ printf("\nCreate file %s failed:%d",RemoteFilePath,GetLastError());
piuKVU __leave;
B52H(sm }
o\60n //写文件内容
r`[B@ while(dwSize>dwIndex)
0\wi am- {
BkV(81"C xKb"p4k9d if(!WriteFile(hFile,&exebuff[dwIndex],dwSize-dwIndex,&dwWrite,NULL))
H|K("AVP: {
[ze/@29 printf("\nWrite file %s
Y'JL (~| failed:%d",RemoteFilePath,GetLastError());
pZ\$50t&O __leave;
KGQC't }
Uz
$ @(C dwIndex+=dwWrite;
EZ{/]gCK }
#B}Qt5w //关闭文件句柄
OM{Dq| CloseHandle(hFile);
CpSK(2j bFile=TRUE;
Efvq?cG& //安装服务
~?-qZ<9/ if(InstallService(dwArgc,lpszArgv))
]hKgA~; {
]4GZ'&m} //等待服务结束
C d|W#.6 if(WaitServiceStop())
%wtXo BJ {
2/EK`S //printf("\nService was stoped!");
,{+6$h3 }
`I{ tZ$iD else
?U JSxL {
117c,yM0 //printf("\nService can't be stoped.Try to delete it.");
8H_l[/ }
$W*|~}F/Ap Sleep(500);
dr{1CP //删除服务
|i u2&p > RemoveService();
Ju4.@ }
hk.yR1Y| }
0+|>-b/% __finally
eK*W=c#@ {
kXMP=j8 //删除留下的文件
B5
&YL if(bFile) DeleteFile(RemoteFilePath);
Br&^09S //如果文件句柄没有关闭,关闭之~
T*R{L if(hFile!=NULL) CloseHandle(hFile);
}\VX^{ K j //Close Service handle
cafsMgrA if(hSCService!=NULL) CloseServiceHandle(hSCService);
*.3y2m,bZ //Close the Service Control Manager handle
7O9n!aJ if(hSCManager!=NULL) CloseServiceHandle(hSCManager);
;b| //断开ipc连接
1I
b_Kmb- wsprintf(tmp,"\\%s\ipc$",szTarget);
B#:E?a;{ WNetCancelConnection2(tmp,CONNECT_UPDATE_PROFILE,TRUE);
`1q|F9D if(bKilled)
]K*GSU printf("\nProcess %s on %s have been
}biCQ*{' killed!\n",lpszArgv[4],lpszArgv[1]);
MISE C[/ else
@sdS0pC printf("\nProcess %s on %s can't be
TwUsVM(~ killed!\n",lpszArgv[4],lpszArgv[1]);
qy6K,/&3 }
0:#7M}U return 0;
^X^,>Z| }
`yx56 //////////////////////////////////////////////////////////////////////////
{?y<%@ BOOL ConnIPC(char *RemoteName,char *User,char *Pass)
_{mJ.1)V; {
!")WZq^` NETRESOURCE nr;
'xk1o,; char RN[50]="\\";
q^%5HeV 2 =oPng=: strcat(RN,RemoteName);
q#|r strcat(RN,"\ipc$");
T(gg>_'jh %:%MUdl6 nr.dwType=RESOURCETYPE_ANY;
A-;^~I nr.lpLocalName=NULL;
T1bFxim#b nr.lpRemoteName=RN;
);!dg\U nr.lpProvider=NULL;
`^zQ$au'u 0H<4+
*`K if(WNetAddConnection2(&nr,Pass,User,FALSE)==NO_ERROR)
Z7oaQ\fR return TRUE;
@f%wd2 else
6$DG.p return FALSE;
xh`Du|jvm }
_\!0t /////////////////////////////////////////////////////////////////////////
NU(^6 BOOL InstallService(DWORD dwArgc,LPTSTR *lpszArgv)
!YIb {
Q<C@KBiVE BOOL bRet=FALSE;
VT
Vm7l __try
g/!Otgfu {
ff[C' //Open Service Control Manager on Local or Remote machine
j37: hSCManager=OpenSCManager(szTarget,NULL,SC_MANAGER_ALL_ACCESS);
~n8F7 if(hSCManager==NULL)
VD9J}bgJ {
#]igB9Cf)w printf("\nOpen Service Control Manage failed:%d",GetLastError());
&jFKc0\i@ __leave;
p[b7E`7 }
h>.9RX & //printf("\nOpen Service Control Manage ok!");
o:4CI //Create Service
Z+Xc1W^ hSCService=CreateService(hSCManager,// handle to SCM database
OK.-]()! ServiceName,// name of service to start
}d@LSaM ServiceName,// display name
Y6+k9$h SERVICE_ALL_ACCESS,// type of access to service
N:d
D*[QZ SERVICE_WIN32_OWN_PROCESS,// type of service
PJ}[D.elO SERVICE_AUTO_START,// when to start service
Ae.]F)w_\ SERVICE_ERROR_IGNORE,// severity of service
`P#8(GU failure
dbg|VoNf EXE,// name of binary file
sC9-+} NULL,// name of load ordering group
We|-5 NULL,// tag identifier
[1mIdwS NULL,// array of dependency names
BJ"Ay@D* NULL,// account name
Na-q%ru NULL);// account password
Up'."w_zE //create service failed
XQ4dohGCP if(hSCService==NULL)
c_t7RWV} {
Y5Ft96o))x //如果服务已经存在,那么则打开
roL}lM$ if(GetLastError()==ERROR_SERVICE_EXISTS)
z(#=tC| {
[rc'/@L //printf("\nService %s Already exists",ServiceName);
UJ
O]sD`i //open service
0:s8o@} hSCService = OpenService(hSCManager, ServiceName,
g:;Ya?5N SERVICE_ALL_ACCESS);
!\3}R25 if(hSCService==NULL)
o%$<LaQG5 {
= >P_mPP= printf("\nOpen Service failed:%d",GetLastError());
5 =*@l __leave;
)\(lg*?: }
6NU8HJp //printf("\nOpen Service %s ok!",ServiceName);
)ynA:LXx }
2YaTT& J else
GCZu<, {
t&8<k+m printf("\nCreateService failed:%d",GetLastError());
G[vUOEU~O __leave;
a
pKa4nI
}
g<0w/n!jmC }
Ja^7$WY //create service ok
!'Gb$l! else
ZWov_ {
^Kb9@lz/ //printf("\nCreate Service %s ok!",ServiceName);
q#.rYzl0 }
fp,1qzU[k [f/vLLK // 起动服务
.QNjeMu. if ( StartService(hSCService,dwArgc,lpszArgv))
}k4` {
Z3Bo@`&? //printf("\nStarting %s.", ServiceName);
(/To?` Sleep(20);//时间最好不要超过100ms
wVlSjk while( QueryServiceStatus(hSCService, &ssStatus ) )
fMgcK$ {
=%:JjgKc*t if ( ssStatus.dwCurrentState == SERVICE_START_PENDING)
t%0r"bTi {
k\Yu5) printf(".");
Qfwwh`; Sleep(20);
yLV2>kq }
AECxd[k$9 else
|2WxcW]U.% break;
Q9Q!9B@ }
Z3LQl( if ( ssStatus.dwCurrentState != SERVICE_RUNNING )
c1 gz#, printf("\n%s failed to run:%d",ServiceName,GetLastError());
bCH*8,Bmh }
vcaBL<io else if(GetLastError()==ERROR_SERVICE_ALREADY_RUNNING)
-lnTYxo+]^ {
A/ox#(!v //printf("\nService %s already running.",ServiceName);
0G+L1a- }
v+|@}9| Z else
|`N$>9qN {
?v0A/68s# printf("\nStart Service %s failed:%d",ServiceName,GetLastError());
1v> __leave;
WHZe)|n }
Q=)"om bRet=TRUE;
e);bF>.~ }//enf of try
1\M"`L/ __finally
=d:R/Z%, {
O6M}W_ return bRet;
~e,f )? }
>DSNKU+j return bRet;
Ah(\%35& }
Ak<IHp^Q /////////////////////////////////////////////////////////////////////////
dj8F6\ BOOL WaitServiceStop(void)
48R]\B<R{ {
b'1/cY/! BOOL bRet=FALSE;
yffU%
) //printf("\nWait Service stoped");
vE^h}~5U while(1)
+&&MUT{
3 {
~YR <SV\{ Sleep(100);
>w%d'e$ if(!QueryServiceStatus(hSCService, &ssStatus))
ph}wnIW] {
SSSDl$}'t printf("\nQueryServiceStatus failed:%d",GetLastError());
l}U~I
3}). break;
[)C)p*!Y) }
c,b`N0dOKL if(ssStatus.dwCurrentState==SERVICE_STOPPED)
c,g]0S?gu {
9Bbm7Gd bKilled=TRUE;
?NL&x bRet=TRUE;
I;bg?RsF break;
X_^_r{ }
Wwa41z if(ssStatus.dwCurrentState==SERVICE_PAUSED)
t?3{s\z 8+ {
muqfSF //停止服务
i'eYmm96Q bRet=ControlService(hSCService,SERVICE_CONTROL_STOP,NULL);
\N'hbT= break;
R{2GQB }
s>9z+;~! else
%l9WZ*yZ`2 {
F3H:I"4 //printf(".");
_oMs
`"4K continue;
5JXzfc9rL }
7(nz<z p }
<