杀掉本地进程其实很简单,取得进程ID后,调用OpenProcess函数打开进程句柄,然后调用TerminateProcess函数就可以杀掉进程了。有些情况下并不能直接打开进程句柄,例如WINLOGON等系统进程,因为权限不够。这个时候我们就得先提升自己的进程的权限了。提升权限过程也不复杂,先调用GetCurrentProcess函数取得当前进程的句柄,然后调用OpenProcessToken打开当前进程的访问令牌,接着调用LookupPrivilegeValue函数取得你想提升的权限的值,最后调用AdjustTokenPrivileges函数给当前进程的访问令牌增加权限就可以了。一般有了SeDebugPrivilege特权后,就可以杀掉除Idle外的所有进程了。
AK[9fxrE OK!那如何杀掉远程进程呢?说起来有点复杂,但其实也不难。
t3bDi/m <1>与远程系统建立IPC连接
YQYN.\ <2>在远程系统的系统目录admin$\system32中写入一个文件killsrv.exe
BHFWig*{ <3>调用函数OpenSCManager打开远程系统的Service Control Manager[SCM]
7i/?+| <4>调用函数CreateService在远程系统创建一个服务,服务指向的程序是在<2>中写入的程序killsrv.exe
(mz a&WF7 <5>调用函数StartService启动刚才创建的服务,把想杀掉的进程的ID作为参数传递给它
J-I7K!B <6>服务启动后,killsrv.exe运行,杀掉进程
L'['7 <7>清场
dmE-WS 嗯!这样看来,我们需要两个程序了。Killsrv.exe的源代码如下:
W:0@m^r /***********************************************************************
Txw,B2e)> Module:Killsrv.c
Rmd;ug9 Date:2001/4/27
*M KVm)Iv Author:ey4s
eUBk^C]\ Http://www.ey4s.org 6= 9 ***********************************************************************/
JQbI^ef_; #include
+F67g00T| #include
m0\(a_0V #include "function.c"
qe\j$Cjy #define ServiceName "PSKILL"
9`c :sop ^. Pn)J SERVICE_STATUS_HANDLE ssh;
m'429E]\S SERVICE_STATUS ss;
wmT3 > /////////////////////////////////////////////////////////////////////////
BJlF@F# void ServiceStopped(void)
?f &*mp {
KE(kR>OB] ss.dwServiceType=SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;
7dU X(D,? ss.dwCurrentState=SERVICE_STOPPED;
B`KpaE] ss.dwControlsAccepted=SERVICE_ACCEPT_STOP;
8qBw;A) ss.dwWin32ExitCode=NO_ERROR;
_;0:wXib= ss.dwCheckPoint=0;
AY * ss.dwWaitHint=0;
Z/ThYbk SetServiceStatus(ssh,&ss);
!)&-\!M> return;
St&XG>nWS }
][0HJG{{g /////////////////////////////////////////////////////////////////////////
[!aHP?- void ServicePaused(void)
)ns;S {
o.j;dsZ ss.dwServiceType=SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;
ZY][LU~l8 ss.dwCurrentState=SERVICE_PAUSED;
fxiq,o0 ss.dwControlsAccepted=SERVICE_ACCEPT_STOP;
1hRC
Bwx ss.dwWin32ExitCode=NO_ERROR;
Kk??} ss.dwCheckPoint=0;
b!UT<:o ss.dwWaitHint=0;
{`1zVT p[< SetServiceStatus(ssh,&ss);
r%xNfTa return;
dn`#N^Od }
s]=kD void ServiceRunning(void)
r9u*c {
o]k[l; ss.dwServiceType=SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;
n}._Nb
5 ss.dwCurrentState=SERVICE_RUNNING;
(r7~ccy4 ss.dwControlsAccepted=SERVICE_ACCEPT_STOP;
cLB"<mG ss.dwWin32ExitCode=NO_ERROR;
+/UInAM ss.dwCheckPoint=0;
,sJ{2,]~ ss.dwWaitHint=0;
5F0sfX SetServiceStatus(ssh,&ss);
(+Er return;
Rhr]ML }
$Y ]*v)}X /////////////////////////////////////////////////////////////////////////
qnT:x{o void WINAPI servier_ctrl(DWORD Opcode)//服务控制程序
cvc.-7IO {
'MC)%N, switch(Opcode)
47t^{WrT {
|pJ.73 case SERVICE_CONTROL_STOP://停止Service
[.6uw=;o ServiceStopped();
}*+ca>K break;
U8.DPRa case SERVICE_CONTROL_INTERROGATE:
6:h!gY SetServiceStatus(ssh,&ss);
KL -8Aj~ break;
gE8>5_R| }
vO"AJ`_ return;
AoTL)', }
O-: ~6A //////////////////////////////////////////////////////////////////////////////
v'Lckw@G4 //杀进程成功设置服务状态为SERVICE_STOPPED
f5`exfdHE //失败设置服务状态为SERVICE_PAUSED
_<5>
E //
^mG-O void WINAPI ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv)
g:OVAA {
xx41Qw>\W ssh=RegisterServiceCtrlHandler(ServiceName,servier_ctrl);
_YbHnb if(!ssh)
NEK;'"~ {
v|n.AGn ServicePaused();
Zb}=?fcL;@ return;
~omX(kPzK }
Yz{UP)TC
ServiceRunning();
R=PjLH&) Sleep(100);
y+X%qTB //注意,argv[0]为此程序名,argv[1]为pskill,参数需要递增1
k deJB- //argv[2]=target,argv[3]=user,argv[4]=pwd,argv[5]=pid
a:@Eg;aN*O if(KillPS(atoi(lpszArgv[5])))
0R*!o\y ServiceStopped();
1k
"*@Z< else
ukhI'alS, ServicePaused();
KqB(W,$ return;
rsiG]o=8 }
V_Y SYG9f /////////////////////////////////////////////////////////////////////////////
od-N7lp# void main(DWORD dwArgc,LPTSTR *lpszArgv)
~sk 4v:- {
aIJ[K SERVICE_TABLE_ENTRY ste[2];
a*??! ste[0].lpServiceName=ServiceName;
LoNz
1KJL ste[0].lpServiceProc=ServiceMain;
w'U;b ste[1].lpServiceName=NULL;
O^`Y>>a ste[1].lpServiceProc=NULL;
~2=B:; StartServiceCtrlDispatcher(ste);
IWKQU/l! return;
9I.="b=J) }
{OB\~$TH /////////////////////////////////////////////////////////////////////////////
[?]s((A~B function.c中有两个函数,一个是提升权限的,一个是提供进程ID,杀进程的。代码如
wn|Sdp 下:
, gz:2UY# /***********************************************************************
=Ermh7, Module:function.c
x+^iEj`gk Date:2001/4/28
][#]4_ Author:ey4s
dZ;csc@xv Http://www.ey4s.org 5a4;d+ ***********************************************************************/
et)A$'Q #include
C;STJrew ////////////////////////////////////////////////////////////////////////////
`)K1[& BOOL SetPrivilege(HANDLE hToken,LPCTSTR lpszPrivilege,BOOL bEnablePrivilege)
?$8OVq.w, {
K{"(|~=U TOKEN_PRIVILEGES tp;
.7cQKdvcC LUID luid;
Rz%+E0 'N'EC`R if(!LookupPrivilegeValue(NULL,lpszPrivilege,&luid))
\W#M]Q {
MheP@ [w|@ printf("\nLookupPrivilegeValue error:%d", GetLastError() );
8]+hfB/ return FALSE;
8+
Hho@= }
'rU5VrK tp.PrivilegeCount = 1;
h.G/HHz
tp.Privileges[0].Luid = luid;
DTgF,c if (bEnablePrivilege)
+=;F vb tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
o^5xCK:Oi2 else
iQs(Dh=* tp.Privileges[0].Attributes = 0;
dt;R // Enable the privilege or disable all privileges.
H?^Poe(=( AdjustTokenPrivileges(
)I`B+c: hToken,
M(SH3~ FALSE,
P62g7>B5^ &tp,
]6FpUF#<D sizeof(TOKEN_PRIVILEGES),
D1x~d<j (PTOKEN_PRIVILEGES) NULL,
={8ClUV# (PDWORD) NULL);
LXfDXXF // Call GetLastError to determine whether the function succeeded.
u9sffX5x[J if (GetLastError() != ERROR_SUCCESS)
xUzfBn {
m$0T" `AP` printf("AdjustTokenPrivileges failed: %u\n", GetLastError() );
mWCY%o@ return FALSE;
Q+Jzab }
|Y2u=B return TRUE;
\*a7DuVw }
@k ~Xem%< ////////////////////////////////////////////////////////////////////////////
:\gdQG BOOL KillPS(DWORD id)
;h3c+7u1 {
6YYZ S2 HANDLE hProcess=NULL,hProcessToken=NULL;
=d& BOOL IsKilled=FALSE,bRet=FALSE;
ANi}q9SC __try
mI9~\k&9 {
~#7=gI&p@ oM
Q+= if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hProcessToken))
*|ubH?71%Y {
I}$Y[Jve printf("\nOpen Current Process Token failed:%d",GetLastError());
n$B=Vt, __leave;
Ws.F=kS>h }
I@7^H48\ //printf("\nOpen Current Process Token ok!");
#.#T+B+9 if(!SetPrivilege(hProcessToken,SE_DEBUG_NAME,TRUE))
ZVk_qA% {
M)(
5S1ndq __leave;
{N/(lB8 }
O~l WFaW printf("\nSetPrivilege ok!");
f*LDrAf9 qeHb0G if((hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,id))==NULL)
`A3"*,|z {
PzNk: O printf("\nOpen Process %d failed:%d",id,GetLastError());
NKh"x&R __leave;
k G4v> }
Pr<.ld\ //printf("\nOpen Process %d ok!",id);
EL5gMs if(!TerminateProcess(hProcess,1))
$x#Y\dpS {
`a98+x?JF printf("\nTerminateProcess failed:%d",GetLastError());
Ry r2 __leave;
/vBOf;L }
=P-kb^ s IsKilled=TRUE;
)lBke*j~ }
.Hc]?R] __finally
+Ae4LeVzc {
349W0>eOT if(hProcessToken!=NULL) CloseHandle(hProcessToken);
#1&wfI$ if(hProcess!=NULL) CloseHandle(hProcess);
2LEf"FH0~ }
[N'YFb3"O return(IsKilled);
M')f,5i&$ }
7[.aAGTZ; //////////////////////////////////////////////////////////////////////////////////////////////
}&bO;o&> OK!服务端的程序已经好了。接下来还需要一个客户端。如果通过在客户端运行的时候,把killsrv.exe COPY到远程系统上,那么就需要提供两个exe文件给用户,这样显得不是很专业,呵呵。不如我们就把killsrv.exe的二进制码作为buff保存在客户端吧,这样在运行的时候,我们直接把buff中的内容写过去,这样提供给用户一个exe文件就可以了。Pskill.c的源代码如下:
Y Dq5%N` /*********************************************************************************************
I?EtU/AD ModulesKill.c
Pur~Rz\\ Create:2001/4/28
OZB(4{vnyC Modify:2001/6/23
)zf&`T Author:ey4s
3g0[(; Http://www.ey4s.org [; PsKill ==>Local and Remote process killer for windows 2k
( Y'q%$ **************************************************************************/
`XE8[XY #include "ps.h"
V80g+)| #define EXE "killsrv.exe"
*[9FPya #define ServiceName "PSKILL"
IlN9IF\9L iYEhrb #pragma comment(lib,"mpr.lib")
-}AAA*P //////////////////////////////////////////////////////////////////////////
PB(mUD2"r //定义全局变量
&k+jVymH SERVICE_STATUS ssStatus;
4w<U%57 SC_HANDLE hSCManager=NULL,hSCService=NULL;
f]jAa?d T& BOOL bKilled=FALSE;
6X$]d^)h{ char szTarget[52]=;
Oc}4`?oy<O //////////////////////////////////////////////////////////////////////////
h2QoBGL5 BOOL ConnIPC(char *,char *,char *);//建立IPC连接函数
@6~r7/WD BOOL InstallService(DWORD,LPTSTR *);//安装服务函数
WA\
P`'lg BOOL WaitServiceStop();//等待服务停止函数
`07xW*K(\Y BOOL RemoveService();//删除服务函数
h;u8{t" /////////////////////////////////////////////////////////////////////////
|$f.Qs~? int main(DWORD dwArgc,LPTSTR *lpszArgv)
&"p7X>bd {
>ZTRwy`_( BOOL bRet=FALSE,bFile=FALSE;
XJ^dX]4 char tmp[52]=,RemoteFilePath[128]=,
D
C{l.a. szUser[52]=,szPass[52]=;
^7G@CBic" HANDLE hFile=NULL;
f!|7j}3 DWORD i=0,dwIndex=0,dwWrite,dwSize=sizeof(exebuff);
wrSw> sE" ]+u`E //杀本地进程
lZCTthr\ if(dwArgc==2)
ABuK`(f. {
U%.OH?;f if(KillPS(atoi(lpszArgv[1])))
*UJ.cQ} printf("\nLoacl Process %s have beed killed!",lpszArgv[1]);
r#M0X^4A else
Y@)/iwq printf("\nLoacl Process %s can't be killed!ErrorCode:%d",
0hVw=KDO9: lpszArgv[1],GetLastError());
}1kT0*'L return 0;
VEj-%"\ }
b1>zGC^| //用户输入错误
*~YU0o else if(dwArgc!=5)
{ss^L {
C @3a/<6m printf("\nPSKILL ==>Local and Remote Process Killer"
_r@
FWUZ "\nPower by ey4s"
v0+mh] "\nhttp://www.ey4s.org 2001/6/23"
,l+lokD-# "\n\nUsage:%s <==Killed Local Process"
b*i_'k}*<g "\n %s <==Killed Remote Process\n",
f*)8bZDD lpszArgv[0],lpszArgv[0]);
J$Uj@M return 1;
mwU|Hh)N] }
!6{; z/Hy //杀远程机器进程
Gi]R8?M strncpy(szTarget,lpszArgv[1],sizeof(szTarget)-1);
W@Et strncpy(szUser,lpszArgv[2],sizeof(szUser)-1);
*DfwTbg| strncpy(szPass,lpszArgv[3],sizeof(szPass)-1);
E}LYO: 4HG;v|Cp //将在目标机器上创建的exe文件的路径
XRARgWj sprintf(RemoteFilePath,"\\%s\admin$\system32\%s",szTarget,EXE);
#X1iig+ __try
9f1,E98w_ {
.K%1{`.| //与目标建立IPC连接
Wwo'pke
if(!ConnIPC(szTarget,szUser,szPass))
>|Yr14?7 {
y:,Ro@H% printf("\nConnect to %s failed:%d",szTarget,GetLastError());
j]Y`L?!Q return 1;
82d~>i%T }
pbc<326X" printf("\nConnect to %s success!",szTarget);
T rK-XTev //在目标机器上创建exe文件
wyWe2d jiw5>RNt hFile=CreateFile(RemoteFilePath,GENERIC_ALL,FILE_SHARE_READ|FILE_SHARE_WRIT
moz*=a E,
!(2rU @. NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
sa6/$ if(hFile==INVALID_HANDLE_VALUE)
4OX|pa {
TC[(mf:8 printf("\nCreate file %s failed:%d",RemoteFilePath,GetLastError());
"Bn8WT2? __leave;
CNU,\>J@$ }
nbd-f6F6 //写文件内容
>(T)9fKF while(dwSize>dwIndex)
Dfz3\|LJ {
/<zBjvr%% +h*-9 if(!WriteFile(hFile,&exebuff[dwIndex],dwSize-dwIndex,&dwWrite,NULL))
EH1GdlhA {
iR(=<> printf("\nWrite file %s
rx[l7F
q failed:%d",RemoteFilePath,GetLastError());
<KB V __leave;
!C]2:+z-MF }
!g|)?XWc dwIndex+=dwWrite;
:]]#X
~J }
X0\O3l*j //关闭文件句柄
5 1&||. CloseHandle(hFile);
1V/?p<A bFile=TRUE;
Z@sDxYt9 //安装服务
<yNu/B.M if(InstallService(dwArgc,lpszArgv))
=emcs% {
K3g<NC //等待服务结束
Y8l
8B> if(WaitServiceStop())
Vd%%lv{v {
e 97Ll=> //printf("\nService was stoped!");
ZhvZe/ }
5ub|r0&M else
R"Ff(1m {
cl,\N\ //printf("\nService can't be stoped.Try to delete it.");
+q<G%PwbV }
;YGCsLT<xt Sleep(500);
R V@'$`Q //删除服务
,76xa%k(U| RemoveService();
)SjhOvm }
- 2DvKW$ }
9Su4nt`i __finally
FUTD/y]Lu {
u([|^~H] //删除留下的文件
[T}Lq~ if(bFile) DeleteFile(RemoteFilePath);
*h([ai"1- //如果文件句柄没有关闭,关闭之~
LZR
x>q^ if(hFile!=NULL) CloseHandle(hFile);
fGtYvl O-5 //Close Service handle
~9ZW~z' if(hSCService!=NULL) CloseServiceHandle(hSCService);
z.vERP56 //Close the Service Control Manager handle
Qvc$D{z if(hSCManager!=NULL) CloseServiceHandle(hSCManager);
rg5ZxN|g //断开ipc连接
=(aA`:Nl wsprintf(tmp,"\\%s\ipc$",szTarget);
AT{rg/oSf WNetCancelConnection2(tmp,CONNECT_UPDATE_PROFILE,TRUE);
>v?&&FhHK< if(bKilled)
"O (N=|b printf("\nProcess %s on %s have been
\5
S^~(iL killed!\n",lpszArgv[4],lpszArgv[1]);
c;6[lv else
Nv[MU@Tv printf("\nProcess %s on %s can't be
s^\
*jZ6 killed!\n",lpszArgv[4],lpszArgv[1]);
bfV&z+Rv-5 }
.m gm1zz return 0;
KA#P_e{<@ }
/BN_K8nb` //////////////////////////////////////////////////////////////////////////
`>1XL 2 BOOL ConnIPC(char *RemoteName,char *User,char *Pass)
\img
{
Ga$ J7R NETRESOURCE nr;
Vd&&GI(:?^ char RN[50]="\\";
Z~S%|{&Br =Ts5\1sc> strcat(RN,RemoteName);
:@~W$f\y strcat(RN,"\ipc$");
|$:y8H'J d}:eLC nr.dwType=RESOURCETYPE_ANY;
V9:Jz Q=?` nr.lpLocalName=NULL;
.D8|_B nr.lpRemoteName=RN;
[C-4*qOaa2 nr.lpProvider=NULL;
KHO@"+ q}xYme4 if(WNetAddConnection2(&nr,Pass,User,FALSE)==NO_ERROR)
R`HC
EX) return TRUE;
L^E#"f else
VZ3{$0
+ return FALSE;
7ciSIJ }
;}>g/lw /////////////////////////////////////////////////////////////////////////
Gv(?u BOOL InstallService(DWORD dwArgc,LPTSTR *lpszArgv)
P Y&(ObC {
>.=v*\P BOOL bRet=FALSE;
sF4+(9 = __try
U0J_
3W {
^Ay>%`hf* //Open Service Control Manager on Local or Remote machine
d8C44q+ds hSCManager=OpenSCManager(szTarget,NULL,SC_MANAGER_ALL_ACCESS);
c>b!{e@* if(hSCManager==NULL)
ZZ*+Tl\
s {
eJ
;a}{ 4% printf("\nOpen Service Control Manage failed:%d",GetLastError());
b0|;v-v __leave;
MW|*Z{6* }
BB9+d"Sq //printf("\nOpen Service Control Manage ok!");
:3N&&] //Create Service
p!Xn iY hSCService=CreateService(hSCManager,// handle to SCM database
P]^BE;7T ServiceName,// name of service to start
YZdV0-S ServiceName,// display name
1Qk]?R/DN SERVICE_ALL_ACCESS,// type of access to service
,L&d\M"f SERVICE_WIN32_OWN_PROCESS,// type of service
S.,5vI"s, SERVICE_AUTO_START,// when to start service
DQI
b57j SERVICE_ERROR_IGNORE,// severity of service
wl.a|~- failure
PP-U. EXE,// name of binary file
q).["fSV NULL,// name of load ordering group
U_KCN09 NULL,// tag identifier
p}e1!q;N NULL,// array of dependency names
S HxD(6 NULL,// account name
X/BcS[a NULL);// account password
kMx^L;:n //create service failed
, G2(l if(hSCService==NULL)
dTrz7ayH {
5Y4#aq //如果服务已经存在,那么则打开
4.e0k<]N` if(GetLastError()==ERROR_SERVICE_EXISTS)
%y|L'C,ge" {
MLT^7'y //printf("\nService %s Already exists",ServiceName);
E (.~[-K4 //open service
`k.0d`3( hSCService = OpenService(hSCManager, ServiceName,
I83 _x|$FZ SERVICE_ALL_ACCESS);
IQ\5!e if(hSCService==NULL)
$n=w {
Y/<`C printf("\nOpen Service failed:%d",GetLastError());
XVfw0-O __leave;
l.Q.G<ol }
NIh?2w"\ //printf("\nOpen Service %s ok!",ServiceName);
S
Rb-eDk' }
5q,ZH6\
{ else
s1>d)2lX {
M .oH,Kd6 printf("\nCreateService failed:%d",GetLastError());
up!54}qy __leave;
8G )O,F7z }
snicVzvA }
^61;0 //create service ok
BVzMgn; else
<~teD[1k" {
I} .9 //printf("\nCreate Service %s ok!",ServiceName);
s H(io }
JKTn ,<s/K // 起动服务
(yK@(euG if ( StartService(hSCService,dwArgc,lpszArgv))
Am@:<J {
d+WNg2#v //printf("\nStarting %s.", ServiceName);
k?;@5r) y- Sleep(20);//时间最好不要超过100ms
M(U<H;Csk while( QueryServiceStatus(hSCService, &ssStatus ) )
4DgH/Yo {
]o?r(1 if ( ssStatus.dwCurrentState == SERVICE_START_PENDING)
+5x{|!Pn {
Y(&rlL(sPK printf(".");
k+@,m\tE Sleep(20);
8J)Kn4jq }
3}2;*:p4Y else
lBzfBmEB break;
0.kC| }
*X /i< if ( ssStatus.dwCurrentState != SERVICE_RUNNING )
G{74o8 printf("\n%s failed to run:%d",ServiceName,GetLastError());
7 MS-Gs| }
|,Kk#`lW<f else if(GetLastError()==ERROR_SERVICE_ALREADY_RUNNING)
cV4]Y(9 {
3gv@JGt7` //printf("\nService %s already running.",ServiceName);
Yb\d(k$h }
:/R>0 n, else
Mx Dqp; {
]@!3os,CNF printf("\nStart Service %s failed:%d",ServiceName,GetLastError());
VA5f+c/ % __leave;
v^dQ%+}7> }
1hY%ZsjC bRet=TRUE;
&~:+2 }//enf of try
4^Og9}bm __finally
Z+Cjg#+ {
~e_ return bRet;
z?n6l7sH }
"&C>=
return bRet;
z&Xk~R*$ }
~"VM_Lz]5 /////////////////////////////////////////////////////////////////////////
ue1g(; BOOL WaitServiceStop(void)
F~sUfqiJ' {
t|m=X BOOL bRet=FALSE;
WD@v<Wx) //printf("\nWait Service stoped");
H`s[=Y,m while(1)
ws<pBC,m {
&$heW, Sleep(100);
[jR>.H' if(!QueryServiceStatus(hSCService, &ssStatus))
jqlfypU {
to;^'#B printf("\nQueryServiceStatus failed:%d",GetLastError());
<+UJgB
A- break;
~t1?oJ }
DQ@M?~1hp if(ssStatus.dwCurrentState==SERVICE_STOPPED)
EXsVZg"# {
w7c0jIf{ bKilled=TRUE;
i9Eh1A3Y bRet=TRUE;
@JPz| break;
sI6I5 }
;`h$xB( if(ssStatus.dwCurrentState==SERVICE_PAUSED)
lNz1|nS(Kd {
Y;"jsK{$ //停止服务
y&V%xE/ bRet=ControlService(hSCService,SERVICE_CONTROL_STOP,NULL);
+4+czfz break;
^CK
D[s }
hU3sEOm> else
:F_>`{ {
'~VF*i^4 //printf(".");
6_&S
?yA continue;
vdh[%T,& }
LYr9a( }
t&i