杀掉本地进程其实很简单,取得进程ID后,调用OpenProcess函数打开进程句柄,然后调用TerminateProcess函数就可以杀掉进程了。有些情况下并不能直接打开进程句柄,例如WINLOGON等系统进程,因为权限不够。这个时候我们就得先提升自己的进程的权限了。提升权限过程也不复杂,先调用GetCurrentProcess函数取得当前进程的句柄,然后调用OpenProcessToken打开当前进程的访问令牌,接着调用LookupPrivilegeValue函数取得你想提升的权限的值,最后调用AdjustTokenPrivileges函数给当前进程的访问令牌增加权限就可以了。一般有了SeDebugPrivilege特权后,就可以杀掉除Idle外的所有进程了。
b]]8Vs)' OK!那如何杀掉远程进程呢?说起来有点复杂,但其实也不难。
P~trxp=k <1>与远程系统建立IPC连接
0SL{J*S4[# <2>在远程系统的系统目录admin$\system32中写入一个文件killsrv.exe
v8ap"9b <3>调用函数OpenSCManager打开远程系统的Service Control Manager[SCM]
lD,2])> <4>调用函数CreateService在远程系统创建一个服务,服务指向的程序是在<2>中写入的程序killsrv.exe
J 6KHc^,7 <5>调用函数StartService启动刚才创建的服务,把想杀掉的进程的ID作为参数传递给它
*DPX4P <6>服务启动后,killsrv.exe运行,杀掉进程
<IZt]P <7>清场
7.h{"xOx{ 嗯!这样看来,我们需要两个程序了。Killsrv.exe的源代码如下:
2%pED
xui /***********************************************************************
'0D$C},^|8 Module:Killsrv.c
xG/Q%A Date:2001/4/27
J{ju3jo Author:ey4s
4f\NtQ) Http://www.ey4s.org W'@|ob ***********************************************************************/
M-^I! C #include
N_c44[z1 #include
M1kA- Xr #include "function.c"
{]Zan'{PCO #define ServiceName "PSKILL"
a!$kKOK V.*TOU{{xh SERVICE_STATUS_HANDLE ssh;
0VNLhM(LM SERVICE_STATUS ss;
dTg`z,^F /////////////////////////////////////////////////////////////////////////
jo:Z void ServiceStopped(void)
efQ8jO {
bCw{9El!K4 ss.dwServiceType=SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;
L0g+RohW ss.dwCurrentState=SERVICE_STOPPED;
GY]P(NU ss.dwControlsAccepted=SERVICE_ACCEPT_STOP;
(GmBv ss.dwWin32ExitCode=NO_ERROR;
~qghw@Q~ ss.dwCheckPoint=0;
*9j'@2!M ss.dwWaitHint=0;
=p@`bx SetServiceStatus(ssh,&ss);
0zr27ko return;
hObL=^F }
EsGu#lD2 /////////////////////////////////////////////////////////////////////////
.==D?#bn void ServicePaused(void)
aS [[
AL {
[{7#IZL ss.dwServiceType=SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;
,clbD4 ss.dwCurrentState=SERVICE_PAUSED;
!zE{`Ha~ ss.dwControlsAccepted=SERVICE_ACCEPT_STOP;
,sL'T[tuiU ss.dwWin32ExitCode=NO_ERROR;
_N`.1Dl%Q ss.dwCheckPoint=0;
^@^8iZ ss.dwWaitHint=0;
T)mQ+&| SetServiceStatus(ssh,&ss);
i6if\B return;
vywB{%p }
I0}.! void ServiceRunning(void)
H a!,9{T {
lCU clD ss.dwServiceType=SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;
\jC) ;mk ss.dwCurrentState=SERVICE_RUNNING;
h[remR#3\ ss.dwControlsAccepted=SERVICE_ACCEPT_STOP;
uFWA] ":is ss.dwWin32ExitCode=NO_ERROR;
Clum
m@z;# ss.dwCheckPoint=0;
Cf[tNq ss.dwWaitHint=0;
(kxS0 ]= SetServiceStatus(ssh,&ss);
Zy(i_B-b return;
(K[{X0T }
gnp.!- /////////////////////////////////////////////////////////////////////////
pQa51 nc void WINAPI servier_ctrl(DWORD Opcode)//服务控制程序
+fVv H {
);0 switch(Opcode)
#kW=|8X {
^)dsi case SERVICE_CONTROL_STOP://停止Service
ew1L+ ServiceStopped();
5eTA] break;
hV7EjQp case SERVICE_CONTROL_INTERROGATE:
Bq8#'K2i, SetServiceStatus(ssh,&ss);
N'2?Z b break;
*u$aItx }
bbC@ return;
puOtF YZ\ }
@8W@I| //////////////////////////////////////////////////////////////////////////////
3WwS+6R //杀进程成功设置服务状态为SERVICE_STOPPED
84(Jo_9 //失败设置服务状态为SERVICE_PAUSED
5=TgOS]R //
*Dg@fxCQ void WINAPI ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv)
J*zzjtY( 1 {
-m`|S q ssh=RegisterServiceCtrlHandler(ServiceName,servier_ctrl);
85E$m'0O if(!ssh)
ko}& X= {
}_lG2#Ll5 ServicePaused();
+-!3ruwSn return;
(pELd(*Ga }
}U7IMONU ServiceRunning();
MD[hqshoh Sleep(100);
,kJ'_mq //注意,argv[0]为此程序名,argv[1]为pskill,参数需要递增1
Q`bXsH //argv[2]=target,argv[3]=user,argv[4]=pwd,argv[5]=pid
s,_+5ukv if(KillPS(atoi(lpszArgv[5])))
eCI'<^ ServiceStopped();
P`Zon else
C@qWour ServicePaused();
;2kQ)Bq" return;
u(Mbp$R'? }
+C`!4v\n /////////////////////////////////////////////////////////////////////////////
NCk-[I?R void main(DWORD dwArgc,LPTSTR *lpszArgv)
&eV5#Ph {
]>~.U~ SERVICE_TABLE_ENTRY ste[2];
U4d7-&U ste[0].lpServiceName=ServiceName;
:cA P{rSe ste[0].lpServiceProc=ServiceMain;
O<vBuD2 ste[1].lpServiceName=NULL;
KF7w{A){ ste[1].lpServiceProc=NULL;
0Jv6?7]LKa StartServiceCtrlDispatcher(ste);
~|KqG return;
'pA%lc) }
!8p>4 |VM /////////////////////////////////////////////////////////////////////////////
?,VpZ%Df2 function.c中有两个函数,一个是提升权限的,一个是提供进程ID,杀进程的。代码如
^$oa`B^2JM 下:
G4i%/_JU /***********************************************************************
bm;iX*~ Module:function.c
4<s;xSCL Date:2001/4/28
\gP?uJ Author:ey4s
+vZYuEq_ Http://www.ey4s.org 4b}p[9k ***********************************************************************/
xiW}P% bf #include
wQ(DX! ////////////////////////////////////////////////////////////////////////////
Cx;it/8+ BOOL SetPrivilege(HANDLE hToken,LPCTSTR lpszPrivilege,BOOL bEnablePrivilege)
A6szTX#0 {
TY]0aw2]|7 TOKEN_PRIVILEGES tp;
jO"/5x26 LUID luid;
+/&rO,Ql @C-dCC? if(!LookupPrivilegeValue(NULL,lpszPrivilege,&luid))
}<G
ae5 {
(lwV(M printf("\nLookupPrivilegeValue error:%d", GetLastError() );
`
,T. return FALSE;
b#7nt ?`7p }
O[Z$~ tp.PrivilegeCount = 1;
1<9d[N* tp.Privileges[0].Luid = luid;
ky !ZJR if (bEnablePrivilege)
I6WHC* tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
;FlDRDZ% else
@IL@|Srs8 tp.Privileges[0].Attributes = 0;
y6am(ugE // Enable the privilege or disable all privileges.
Q8HNST($? AdjustTokenPrivileges(
0^{Tq0Ri[ hToken,
YEV;GFI1 FALSE,
f.ua,,P. &tp,
-~.+3rcZ] sizeof(TOKEN_PRIVILEGES),
tic3a1 (PTOKEN_PRIVILEGES) NULL,
j &[lDlI_ (PDWORD) NULL);
kX V // Call GetLastError to determine whether the function succeeded.
jYU0zGpj if (GetLastError() != ERROR_SUCCESS)
FBNi (D {
]oix))'n printf("AdjustTokenPrivileges failed: %u\n", GetLastError() );
i8<5|du&? return FALSE;
oi Q3E }
8k{XUn return TRUE;
bIT[\Q }
SMvlEj^ ////////////////////////////////////////////////////////////////////////////
T>|+cg BOOL KillPS(DWORD id)
nILUo2e~ {
6+sz4 HANDLE hProcess=NULL,hProcessToken=NULL;
|vi=h2* BOOL IsKilled=FALSE,bRet=FALSE;
?z`yNx6 __try
v*excl~ {
4-O.i\1q 2s2KI=6 if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hProcessToken))
lxTqGwx {
je\]j-0$u printf("\nOpen Current Process Token failed:%d",GetLastError());
!@gjIYq_Y __leave;
}0R"ZPU1Rw }
PJb/tKC //printf("\nOpen Current Process Token ok!");
f:q2JgX if(!SetPrivilege(hProcessToken,SE_DEBUG_NAME,TRUE))
937<:zo: {
QdZHIgh`i __leave;
AJ
0Bb7 }
/L,iF?7 printf("\nSetPrivilege ok!");
\(Dm\7Q. 7OZ0;fK if((hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,id))==NULL)
'(ETXQ@ {
@bkSA printf("\nOpen Process %d failed:%d",id,GetLastError());
:^7_E& __leave;
K0*er }
s/?(G L+Ae //printf("\nOpen Process %d ok!",id);
x =JZ"|TE if(!TerminateProcess(hProcess,1))
aS3-A4 {
*[nS*D\: printf("\nTerminateProcess failed:%d",GetLastError());
<c`,fd8 __leave;
9Lt3^MKa" }
YbVZK4 IsKilled=TRUE;
a6T!)g }
;XY#Jl>tg __finally
Rv*x'w
== {
#!z'R20PH if(hProcessToken!=NULL) CloseHandle(hProcessToken);
!H^R_GC if(hProcess!=NULL) CloseHandle(hProcess);
sN[q.M? }
PClwGO8'& return(IsKilled);
f$nZogaQ }
Z_<Wr7D //////////////////////////////////////////////////////////////////////////////////////////////
n-9X<t|*?a OK!服务端的程序已经好了。接下来还需要一个客户端。如果通过在客户端运行的时候,把killsrv.exe COPY到远程系统上,那么就需要提供两个exe文件给用户,这样显得不是很专业,呵呵。不如我们就把killsrv.exe的二进制码作为buff保存在客户端吧,这样在运行的时候,我们直接把buff中的内容写过去,这样提供给用户一个exe文件就可以了。Pskill.c的源代码如下:
DKQQZ`PF /*********************************************************************************************
c1%ki%J# ModulesKill.c
a;7gy419<p Create:2001/4/28
blV'-Al Modify:2001/6/23
d#, Author:ey4s
tG,xG& Http://www.ey4s.org YcaLc_pUx PsKill ==>Local and Remote process killer for windows 2k
Ky7-6$ **************************************************************************/
^oHK.x#{ #include "ps.h"
]N'4q}<5o #define EXE "killsrv.exe"
"^pF2JI #define ServiceName "PSKILL"
5tbi}; bir tA{q #pragma comment(lib,"mpr.lib")
)Z?\9'6e4 //////////////////////////////////////////////////////////////////////////
Re\V<\$J //定义全局变量
"'8o8g SERVICE_STATUS ssStatus;
o AS 'Z| SC_HANDLE hSCManager=NULL,hSCService=NULL;
53^1; BOOL bKilled=FALSE;
AQBr{^inH| char szTarget[52]=;
#5kg3OO //////////////////////////////////////////////////////////////////////////
5o~AUo{ BOOL ConnIPC(char *,char *,char *);//建立IPC连接函数
h1_KZ[X BOOL InstallService(DWORD,LPTSTR *);//安装服务函数
jK=-L#hz BOOL WaitServiceStop();//等待服务停止函数
eR1]<Z$W\ BOOL RemoveService();//删除服务函数
=uR[Jewa /////////////////////////////////////////////////////////////////////////
a67NWH int main(DWORD dwArgc,LPTSTR *lpszArgv)
doe u` {
( (mNB]sy BOOL bRet=FALSE,bFile=FALSE;
[VB\T|$ char tmp[52]=,RemoteFilePath[128]=,
WAw} ?&k szUser[52]=,szPass[52]=;
.=b)Ae c HANDLE hFile=NULL;
EJrQ9"x&n DWORD i=0,dwIndex=0,dwWrite,dwSize=sizeof(exebuff);
9%Ftln6 rFv=j:8 //杀本地进程
bO{wQ1)Z_ if(dwArgc==2)
o@\q 6xl. {
!
+Hc(i if(KillPS(atoi(lpszArgv[1])))
!Ys.KDL printf("\nLoacl Process %s have beed killed!",lpszArgv[1]);
9%uJ:c? else
u-Ip *1/wp printf("\nLoacl Process %s can't be killed!ErrorCode:%d",
DCtrTX lpszArgv[1],GetLastError());
8J7<7Sx return 0;
T;I>5aQ:q4 }
/?8rj3 //用户输入错误
eYjr/`>O else if(dwArgc!=5)
UD r@ {
,e>N9\* printf("\nPSKILL ==>Local and Remote Process Killer"
(OK;*ZH+T@ "\nPower by ey4s"
0jwex "\nhttp://www.ey4s.org 2001/6/23"
i%_nH"h "\n\nUsage:%s <==Killed Local Process"
n47v5.Wn "\n %s <==Killed Remote Process\n",
#`2*V lpszArgv[0],lpszArgv[0]);
+l$BUX return 1;
\.dvRI' }
^RS`q+g //杀远程机器进程
|N>TPK&Xt strncpy(szTarget,lpszArgv[1],sizeof(szTarget)-1);
Qjh @oWT strncpy(szUser,lpszArgv[2],sizeof(szUser)-1);
Z4Qq#iHZR strncpy(szPass,lpszArgv[3],sizeof(szPass)-1);
5AT[1@H(_ '.DFyHsq //将在目标机器上创建的exe文件的路径
~lLIq!!\ sprintf(RemoteFilePath,"\\%s\admin$\system32\%s",szTarget,EXE);
1~q|%"J __try
}"'l8t0? {
tm}0kWx //与目标建立IPC连接
|q\:3R_0 if(!ConnIPC(szTarget,szUser,szPass))
:u53zX[v {
Q<pL5[00fD printf("\nConnect to %s failed:%d",szTarget,GetLastError());
6jtnH'E/ return 1;
Ol]+l] }
5Y97?n+6 printf("\nConnect to %s success!",szTarget);
jz;"]k //在目标机器上创建exe文件
Dos`lh
F\;G'dm hFile=CreateFile(RemoteFilePath,GENERIC_ALL,FILE_SHARE_READ|FILE_SHARE_WRIT
HI30-$9 E,
Nu'T0LPNq( NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
;HeUD5Nt6F if(hFile==INVALID_HANDLE_VALUE)
3"hPplE {
*7o( printf("\nCreate file %s failed:%d",RemoteFilePath,GetLastError());
t/aT __leave;
Bq]eNq }
+K%4jIm //写文件内容
e[7n`ka
' while(dwSize>dwIndex)
Xj<B!Wn*Xb {
5)GO v 5GV"qY if(!WriteFile(hFile,&exebuff[dwIndex],dwSize-dwIndex,&dwWrite,NULL))
9IC|2w66 {
v9OK
< printf("\nWrite file %s
5}4r'P$m: failed:%d",RemoteFilePath,GetLastError());
F|XRh 6j __leave;
/_P5UE( }
!7lS=D(? dwIndex+=dwWrite;
_0<EbJ8Z }
/K9Tn //关闭文件句柄
LMrb
1lg$ CloseHandle(hFile);
X)|b_ 3Z bFile=TRUE;
eZm,K'/! //安装服务
+mN]VO*y if(InstallService(dwArgc,lpszArgv))
-P<e-V%< {
PSQ5/l?\> //等待服务结束
k/yoRv% if(WaitServiceStop())
/t083 {
y-93 >Y //printf("\nService was stoped!");
n
LZ
}
{?
jr else
M38QA {
{(#>%f+|C //printf("\nService can't be stoped.Try to delete it.");
gI
qYIt }
afcI5w;>} Sleep(500);
^{GnEqml& //删除服务
c?{&=,u2 RemoveService();
{`vF4@ }
7N/v }
Nj_h+=UE! __finally
Z`23z(+ {
54w..8' //删除留下的文件
wYJ. F if(bFile) DeleteFile(RemoteFilePath);
dhW)< //如果文件句柄没有关闭,关闭之~
G:QaWqUb if(hFile!=NULL) CloseHandle(hFile);
@""aNKA^r> //Close Service handle
;k<g#She if(hSCService!=NULL) CloseServiceHandle(hSCService);
"3A.x1uQ //Close the Service Control Manager handle
DDT)l+: XP if(hSCManager!=NULL) CloseServiceHandle(hSCManager);
$e7dE$eH //断开ipc连接
!PI& y wsprintf(tmp,"\\%s\ipc$",szTarget);
eEkFZx WNetCancelConnection2(tmp,CONNECT_UPDATE_PROFILE,TRUE);
CCOd4 if(bKilled)
7Xi)[M?)# printf("\nProcess %s on %s have been
{mK=Vi g killed!\n",lpszArgv[4],lpszArgv[1]);
~1Q$FgLk else
((TiBCF4 printf("\nProcess %s on %s can't be
`Li3=!V[ killed!\n",lpszArgv[4],lpszArgv[1]);
G-[fz }
z )2h\S return 0;
{(i>$RG_ }
+v3@WdLcD //////////////////////////////////////////////////////////////////////////
:e5)Q=lX BOOL ConnIPC(char *RemoteName,char *User,char *Pass)
#=@(
m.k:s {
@JS O=8 NETRESOURCE nr;
W~J@v@..4 char RN[50]="\\";
ON|Bpt2Qp A=/|f$s+ strcat(RN,RemoteName);
Rdd[b? strcat(RN,"\ipc$");
y-gSal Q"KD O-t nr.dwType=RESOURCETYPE_ANY;
F7wpGtt nr.lpLocalName=NULL;
oO-kO!59y nr.lpRemoteName=RN;
"k(Ee nr.lpProvider=NULL;
_6"!y
]Q 0!YB.=\{_q if(WNetAddConnection2(&nr,Pass,User,FALSE)==NO_ERROR)
_Kg:jal return TRUE;
mr]IxTv else
({g7{tUy^H return FALSE;
Gk0f#; }
445}Yw5;9 /////////////////////////////////////////////////////////////////////////
Cvr?%+)$M BOOL InstallService(DWORD dwArgc,LPTSTR *lpszArgv)
q$Z.5EN {
u;m[, BOOL bRet=FALSE;
IPK. __try
^~k2(DLk {
s_A<bW566F //Open Service Control Manager on Local or Remote machine
/(Se:jH$> hSCManager=OpenSCManager(szTarget,NULL,SC_MANAGER_ALL_ACCESS);
%]Gm if(hSCManager==NULL)
7RQ.oee {
*P,dR]-m printf("\nOpen Service Control Manage failed:%d",GetLastError());
e$M \HPc __leave;
ORhe?E] }
Mj2o>N2, //printf("\nOpen Service Control Manage ok!");
a,3}
o:f //Create Service
!%<bLD8 hSCService=CreateService(hSCManager,// handle to SCM database
8jW"8~Y#0 ServiceName,// name of service to start
TQyi-Dc ServiceName,// display name
gz-X4A" SERVICE_ALL_ACCESS,// type of access to service
A`x_M!m SERVICE_WIN32_OWN_PROCESS,// type of service
SR@yG:~ SERVICE_AUTO_START,// when to start service
6\ g-KO SERVICE_ERROR_IGNORE,// severity of service
2`qO'V3Q failure
:|3n`, EXE,// name of binary file
SnsOuC5Ah NULL,// name of load ordering group
G:NI+E"] NULL,// tag identifier
bLyU; NULL,// array of dependency names
e)kN%JqW NULL,// account name
i#o:V/Z. NULL);// account password
zrWkz3FN //create service failed
T >XnVK if(hSCService==NULL)
Zi5d"V[}T {
IKx]?0sS //如果服务已经存在,那么则打开
AvF:$kG if(GetLastError()==ERROR_SERVICE_EXISTS)
M}|<#
i7u {
v|:2U8YREf //printf("\nService %s Already exists",ServiceName);
eHUr!zH: //open service
\^O#)&5 V hSCService = OpenService(hSCManager, ServiceName,
WVUa:_5{ SERVICE_ALL_ACCESS);
c+:LDc3!Gb if(hSCService==NULL)
m%Ah]x; {
AsyJDt'i printf("\nOpen Service failed:%d",GetLastError());
B -XM(Cj __leave;
Ffxf!zS }
X_yAx)Do //printf("\nOpen Service %s ok!",ServiceName);
TxL;qZRY
^ }
;fLYO6 else
x_&=IyU0j {
+cS%b}O`$ printf("\nCreateService failed:%d",GetLastError());
-F.A1{l[. __leave;
'|mVY; i[ }
UX3
]cr }
{[~cQgCI //create service ok
0F$;]zg else
dc[w` {
(\^| @ //printf("\nCreate Service %s ok!",ServiceName);
Ve,h]/G }
acd8?>%[ <T?H
H$es) // 起动服务
P%`|Tu!B if ( StartService(hSCService,dwArgc,lpszArgv))
w E^6DNh {
C{mL]ds< //printf("\nStarting %s.", ServiceName);
tHlKo0S$0 Sleep(20);//时间最好不要超过100ms
4 [2^#t[ while( QueryServiceStatus(hSCService, &ssStatus ) )
R%)ZhG*
{
*7.EL`8 if ( ssStatus.dwCurrentState == SERVICE_START_PENDING)
6% +s` {
`NIc*B4q. printf(".");
gd~# uR\ Sleep(20);
v0EF?$Wo }
>05_#{up else
^B[%|{cO break;
$F V!HD }
qI-q%]l if ( ssStatus.dwCurrentState != SERVICE_RUNNING )
m/W0vPM1 printf("\n%s failed to run:%d",ServiceName,GetLastError());
|3\$\qa }
6*3J3Lc_< else if(GetLastError()==ERROR_SERVICE_ALREADY_RUNNING)
^+Ho#] {
W\xM$#)m //printf("\nService %s already running.",ServiceName);
9Yih%d,
}
@* a'B=7 else
e!cZW.B=`f {
'_)NI printf("\nStart Service %s failed:%d",ServiceName,GetLastError());
V_Owi5h __leave;
]^9B%t
s9 }
fNz*E|]8& bRet=TRUE;
{oIv%U9 }//enf of try
)U4h?J __finally
Q}#5mf&cD {
-oGJPl {r return bRet;
2w>lnJ- }
*Jd,8B/hC return bRet;
UO%VuC5B }
dxm_AUM /////////////////////////////////////////////////////////////////////////
1QHCX*_ BOOL WaitServiceStop(void)
{4u8~whLp {
d0(GE4+/ BOOL bRet=FALSE;
BPAz.K Q //printf("\nWait Service stoped");
GtZkzVqLd while(1)
.eQIU$Kw!O {
V&)lS Qw Sleep(100);
0fc]RkHs" if(!QueryServiceStatus(hSCService, &ssStatus))
A)I4 `3E {
&mebpEHUG7 printf("\nQueryServiceStatus failed:%d",GetLastError());
.;6G?8` break;
Op] L#<&T }
wm@/>X if(ssStatus.dwCurrentState==SERVICE_STOPPED)
{ bjK(| {
W`zY\] bKilled=TRUE;
T*"15ppfk bRet=TRUE;
4{2)ZI# break;
" bHeNWZ }
Wj N0KA if(ssStatus.dwCurrentState==SERVICE_PAUSED)
o* qF"xG {
SZ+<0Y| //停止服务
W?W vT`
T{ bRet=ControlService(hSCService,SERVICE_CONTROL_STOP,NULL);
BaSNr6
YW break;
I W_:nm6 }
b"Ep?=*5 else
~r~~0|= {
qK
,mG{ //printf(".");
~i)O^CKq continue;
&&