杀掉本地进程其实很简单,取得进程ID后,调用OpenProcess函数打开进程句柄,然后调用TerminateProcess函数就可以杀掉进程了。有些情况下并不能直接打开进程句柄,例如WINLOGON等系统进程,因为权限不够。这个时候我们就得先提升自己的进程的权限了。提升权限过程也不复杂,先调用GetCurrentProcess函数取得当前进程的句柄,然后调用OpenProcessToken打开当前进程的访问令牌,接着调用LookupPrivilegeValue函数取得你想提升的权限的值,最后调用AdjustTokenPrivileges函数给当前进程的访问令牌增加权限就可以了。一般有了SeDebugPrivilege特权后,就可以杀掉除Idle外的所有进程了。
g?,\bmH E OK!那如何杀掉远程进程呢?说起来有点复杂,但其实也不难。
<SeK3@Gi <1>与远程系统建立IPC连接
v'`VyXetl <2>在远程系统的系统目录admin$\system32中写入一个文件killsrv.exe
1}1.5[4d <3>调用函数OpenSCManager打开远程系统的Service Control Manager[SCM]
$'D|}=h<Y <4>调用函数CreateService在远程系统创建一个服务,服务指向的程序是在<2>中写入的程序killsrv.exe
jOL $kiW0 <5>调用函数StartService启动刚才创建的服务,把想杀掉的进程的ID作为参数传递给它
E.V#Bk=
<6>服务启动后,killsrv.exe运行,杀掉进程
eZes) &4 <7>清场
K|Sh
嗯!这样看来,我们需要两个程序了。Killsrv.exe的源代码如下:
yVQ0;h /***********************************************************************
r;}%} /IX Module:Killsrv.c
\.c Date:2001/4/27
$ M?VJ\8 Author:ey4s
sPMCN's Http://www.ey4s.org d{^9` J' ***********************************************************************/
i("ok #include
\;&WF1d`ac #include
O$d z=) #include "function.c"
VF8pH< #define ServiceName "PSKILL"
{%g]Ym= l/?Jp+] SERVICE_STATUS_HANDLE ssh;
%JUD54bBt SERVICE_STATUS ss;
5>z`==N) /////////////////////////////////////////////////////////////////////////
8nzDLFxp_ void ServiceStopped(void)
m-V_J`9" {
HCOv<k ss.dwServiceType=SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;
Nn/me ss.dwCurrentState=SERVICE_STOPPED;
Ql`N)! ss.dwControlsAccepted=SERVICE_ACCEPT_STOP;
Ph@hk0dgr/ ss.dwWin32ExitCode=NO_ERROR;
quXL'g ss.dwCheckPoint=0;
VX+:k.} ss.dwWaitHint=0;
f(}?Sp_ SetServiceStatus(ssh,&ss);
NDsF<2A4 return;
X2CpA;#;7l }
~mAv)JK /////////////////////////////////////////////////////////////////////////
vjNP void ServicePaused(void)
jz
CA2N% {
'3B"@^] ss.dwServiceType=SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;
tzH~[n, ss.dwCurrentState=SERVICE_PAUSED;
pC=kv ve ss.dwControlsAccepted=SERVICE_ACCEPT_STOP;
WC2sRv4]3 ss.dwWin32ExitCode=NO_ERROR;
D^]g`V*N ss.dwCheckPoint=0;
.|ZO2MCd ss.dwWaitHint=0;
IRWVoCc9/\ SetServiceStatus(ssh,&ss);
p7H0|> return;
Sv&_LZ-"P }
=$kSvCjP void ServiceRunning(void)
D==C"}J {
6ZvGD}/ ss.dwServiceType=SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;
v#/k`x\ ss.dwCurrentState=SERVICE_RUNNING;
l1_hD,4 ss.dwControlsAccepted=SERVICE_ACCEPT_STOP;
{lv@V*_Y0 ss.dwWin32ExitCode=NO_ERROR;
jU~q~e7Te ss.dwCheckPoint=0;
,O`a_b] ss.dwWaitHint=0;
K+HP2|#6 SetServiceStatus(ssh,&ss);
)DR/Xu;b return;
10?+6*d }
Whd.AaD\ /////////////////////////////////////////////////////////////////////////
{,:yZ&( void WINAPI servier_ctrl(DWORD Opcode)//服务控制程序
B!J~ t8 {
3^!Y9$y1 switch(Opcode)
l~",<bTc {
6*W7I-A case SERVICE_CONTROL_STOP://停止Service
_k'?eZB ServiceStopped();
aK|],L break;
@Z}TF/Rx4 case SERVICE_CONTROL_INTERROGATE:
'ozu4y SetServiceStatus(ssh,&ss);
^T>P break;
%s&"gWi }
0j\} @ return;
nF"NXYa }
qcVmt1" //////////////////////////////////////////////////////////////////////////////
msf%i ! //杀进程成功设置服务状态为SERVICE_STOPPED
t%S2D //失败设置服务状态为SERVICE_PAUSED
G;jX@XqZ //
Ja4j7d1: void WINAPI ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv)
B>]4NF\)H9 {
M9C
v00& ssh=RegisterServiceCtrlHandler(ServiceName,servier_ctrl);
4,g[g#g<q if(!ssh)
bd'io O {
ZovF]jf k ServicePaused();
g"}j return;
9-ei#|Vnt[ }
V*d@@%u** ServiceRunning();
rS|nO_9 f Sleep(100);
IuV7~w //注意,argv[0]为此程序名,argv[1]为pskill,参数需要递增1
NCX`-SLv //argv[2]=target,argv[3]=user,argv[4]=pwd,argv[5]=pid
Zb&5)&'X if(KillPS(atoi(lpszArgv[5])))
3*8m!gq7s ServiceStopped();
\&XtPQ else
]H {g/C{j
ServicePaused();
QgF2f/;! return;
O3/w@q Q }
'&LH9r /////////////////////////////////////////////////////////////////////////////
'QOV! D void main(DWORD dwArgc,LPTSTR *lpszArgv)
y8.3tp {
k-jlYHsA SERVICE_TABLE_ENTRY ste[2];
9z'(4U ste[0].lpServiceName=ServiceName;
*8% nbR ste[0].lpServiceProc=ServiceMain;
qk}Mb_*C) ste[1].lpServiceName=NULL;
']C" 'b ste[1].lpServiceProc=NULL;
D~Rv"Hh StartServiceCtrlDispatcher(ste);
Tebu?bj return;
'/U% -/@ }
VX6M4<8 /////////////////////////////////////////////////////////////////////////////
!n^7&Y[N; function.c中有两个函数,一个是提升权限的,一个是提供进程ID,杀进程的。代码如
j=kz^o~mH 下:
Nu,t,&B
/***********************************************************************
APUpqY Module:function.c
tBjMm8lgb Date:2001/4/28
Ewq7oq5: Author:ey4s
$?*XPzZ Http://www.ey4s.org Q $^)z_jai ***********************************************************************/
-n"7G%$M #include
i|!D ////////////////////////////////////////////////////////////////////////////
Wr6y w# BOOL SetPrivilege(HANDLE hToken,LPCTSTR lpszPrivilege,BOOL bEnablePrivilege)
yc7"tptfF {
eW\C@>Ke TOKEN_PRIVILEGES tp;
bbG!Fg=qQ? LUID luid;
bMGU9~CeJ SdXAL if(!LookupPrivilegeValue(NULL,lpszPrivilege,&luid))
EUmbNV0u {
gR76g4|=; printf("\nLookupPrivilegeValue error:%d", GetLastError() );
2{A/Fbk return FALSE;
/4>|6l= }
gg?O0W{ tp.PrivilegeCount = 1;
[A'9sxG tp.Privileges[0].Luid = luid;
OI)U c . if (bEnablePrivilege)
'>Uip+' tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
0?w4 else
rd ]dDG tp.Privileges[0].Attributes = 0;
c:u2a/Q? // Enable the privilege or disable all privileges.
-(VX+XHW AdjustTokenPrivileges(
jmr1e).]; hToken,
f)#nXTXeC FALSE,
-~TgA*_5] &tp,
|>v8yS5 sizeof(TOKEN_PRIVILEGES),
seS) `@n (PTOKEN_PRIVILEGES) NULL,
i:sb_U+M (PDWORD) NULL);
eMOnzW|h // Call GetLastError to determine whether the function succeeded.
}&Ul(HR if (GetLastError() != ERROR_SUCCESS)
mNQ*YCq. {
5;[h&jH printf("AdjustTokenPrivileges failed: %u\n", GetLastError() );
"ZR^w5 return FALSE;
P"s7}cl }
4mci@1K#^ return TRUE;
A)HV#T`N }
&d 6 ////////////////////////////////////////////////////////////////////////////
I,7n-G_' BOOL KillPS(DWORD id)
D {N,7kT {
KY9&Ky+2 B HANDLE hProcess=NULL,hProcessToken=NULL;
x}7` Q:k= BOOL IsKilled=FALSE,bRet=FALSE;
:rnj>U6<> __try
wh#x`Nc {
\heQVWRl 6B&ERdoX if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hProcessToken))
Nrfj[I {
v0W/7?D printf("\nOpen Current Process Token failed:%d",GetLastError());
KB a
__leave;
GcHZ&m4 }
8+8P{_ //printf("\nOpen Current Process Token ok!");
(I ~r~5^ if(!SetPrivilege(hProcessToken,SE_DEBUG_NAME,TRUE))
X@^"@ {
N6uKFQL:{ __leave;
4L/8Hj#g }
(E<QA printf("\nSetPrivilege ok!");
/u pDbP.O h%!N!\ if((hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,id))==NULL)
YnwP\Arfq {
r1AG1Y printf("\nOpen Process %d failed:%d",id,GetLastError());
`t Zw(Z=h __leave;
}Oe9Zq }
!~a1xI~s //printf("\nOpen Process %d ok!",id);
^<v]x;
3 if(!TerminateProcess(hProcess,1))
S1E=EVG {
V"W)u#4, printf("\nTerminateProcess failed:%d",GetLastError());
*S\/l-D __leave;
:'K%&e?7s }
t_{rKb,
IsKilled=TRUE;
B$&&'i% }
Z)dE#A_X __finally
hgI;^ia
{
0|OmQ\SQ if(hProcessToken!=NULL) CloseHandle(hProcessToken);
_?~)B\@~0 if(hProcess!=NULL) CloseHandle(hProcess);
>o8N@`@VK- }
8\9s,W:5 return(IsKilled);
t.6gyrV7>< }
N-<m/RS //////////////////////////////////////////////////////////////////////////////////////////////
3PRK.vf OK!服务端的程序已经好了。接下来还需要一个客户端。如果通过在客户端运行的时候,把killsrv.exe COPY到远程系统上,那么就需要提供两个exe文件给用户,这样显得不是很专业,呵呵。不如我们就把killsrv.exe的二进制码作为buff保存在客户端吧,这样在运行的时候,我们直接把buff中的内容写过去,这样提供给用户一个exe文件就可以了。Pskill.c的源代码如下:
x
L]Z3"p% /*********************************************************************************************
I;3Uzv ModulesKill.c
[LrA_N Create:2001/4/28
L7 g4' Modify:2001/6/23
U=>4=gsG Author:ey4s
)+v'@]r Http://www.ey4s.org .h@HAnmE PsKill ==>Local and Remote process killer for windows 2k
1`l10f qU **************************************************************************/
QP1bm]QYA #include "ps.h"
~JSa]6:_+ #define EXE "killsrv.exe"
1xt N3{c #define ServiceName "PSKILL"
<|c[
#f
r^$WX@ t& #pragma comment(lib,"mpr.lib")
$ZfoJR]% //////////////////////////////////////////////////////////////////////////
:Tn1]a)f6 //定义全局变量
c(!8L\69V} SERVICE_STATUS ssStatus;
7 J+cs^2 SC_HANDLE hSCManager=NULL,hSCService=NULL;
2` j#eB1 BOOL bKilled=FALSE;
,]8$QFf char szTarget[52]=;
h0n,WU/Kw //////////////////////////////////////////////////////////////////////////
)Qixde>]p BOOL ConnIPC(char *,char *,char *);//建立IPC连接函数
X)k+BJ BOOL InstallService(DWORD,LPTSTR *);//安装服务函数
zx=AT BOOL WaitServiceStop();//等待服务停止函数
M`gr*p BOOL RemoveService();//删除服务函数
Yn1CU /////////////////////////////////////////////////////////////////////////
rhvTV(Bz int main(DWORD dwArgc,LPTSTR *lpszArgv)
_)F0oC { {
4&/m>%r BOOL bRet=FALSE,bFile=FALSE;
EE[JXoke char tmp[52]=,RemoteFilePath[128]=,
/{+77{#Qn szUser[52]=,szPass[52]=;
nN[gAM ( HANDLE hFile=NULL;
.m
\y6 DWORD i=0,dwIndex=0,dwWrite,dwSize=sizeof(exebuff);
3FpS o+ (#%R'9Rv //杀本地进程
/8tF7Mmr if(dwArgc==2)
A3c&VT6Q {
6<+ 8[o if(KillPS(atoi(lpszArgv[1])))
(N` x printf("\nLoacl Process %s have beed killed!",lpszArgv[1]);
d@0& else
*m9,_~t printf("\nLoacl Process %s can't be killed!ErrorCode:%d",
6d#
V lpszArgv[1],GetLastError());
n;,>Fv return 0;
s2M|ni= }
{rWFgn4Li //用户输入错误
&0QtHcXpR else if(dwArgc!=5)
^VAvQ(b!:i {
Q^z&;%q1 printf("\nPSKILL ==>Local and Remote Process Killer"
"8YXFg "\nPower by ey4s"
]eD5It\ "\nhttp://www.ey4s.org 2001/6/23"
L#X!. "\n\nUsage:%s <==Killed Local Process"
Ij}k>qO/2 "\n %s <==Killed Remote Process\n",
+/Q?<*[ lpszArgv[0],lpszArgv[0]);
zMW[Xx! return 1;
+7|Q d}\X }
K3($,aB} //杀远程机器进程
)Y:9sd8g7 strncpy(szTarget,lpszArgv[1],sizeof(szTarget)-1);
*>f-UNV strncpy(szUser,lpszArgv[2],sizeof(szUser)-1);
KWB;*P
C^ strncpy(szPass,lpszArgv[3],sizeof(szPass)-1);
#I|jFn9 b+3QqbJ[F //将在目标机器上创建的exe文件的路径
I]OVzM sprintf(RemoteFilePath,"\\%s\admin$\system32\%s",szTarget,EXE);
E]26a,^L __try
oiY&O]} {
E^<.; //与目标建立IPC连接
\4r?=5v* if(!ConnIPC(szTarget,szUser,szPass))
X`E3lgfqT {
8!q$8]M printf("\nConnect to %s failed:%d",szTarget,GetLastError());
.<|.nK` 6 return 1;
9Di@r!Db }
Lavm printf("\nConnect to %s success!",szTarget);
Q'n]+%YN //在目标机器上创建exe文件
!mtq?LV XexslzI hFile=CreateFile(RemoteFilePath,GENERIC_ALL,FILE_SHARE_READ|FILE_SHARE_WRIT
PK7
kpC E,
%.3]F2_Q NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
IoI
,IX]i) if(hFile==INVALID_HANDLE_VALUE)
98^o9i {
(hv>vfY@ printf("\nCreate file %s failed:%d",RemoteFilePath,GetLastError());
5gnmRd __leave;
Jf|6 FQo& }
eX9Hwq4X44 //写文件内容
eaGd:( while(dwSize>dwIndex)
5$C]$o} {
M7 Z9(3Va 07:N)y, if(!WriteFile(hFile,&exebuff[dwIndex],dwSize-dwIndex,&dwWrite,NULL))
aur4Ky> : {
aE'nW@YL. printf("\nWrite file %s
GDMg.w4Yk failed:%d",RemoteFilePath,GetLastError());
U`h> [9 __leave;
b08s610fk }
x!@P|c1nKC dwIndex+=dwWrite;
"/MA.zEl0, }
KqH_?r` //关闭文件句柄
WMw]W& CloseHandle(hFile);
/K2=GLl; bFile=TRUE;
!<P|:Oo*Dl //安装服务
E6FT*}Q if(InstallService(dwArgc,lpszArgv))
mtQlm5l {
%oY=.Ok ] //等待服务结束
k_}aiHdG if(WaitServiceStop())
Im* ~6[ {
Zg#VZg1
2 //printf("\nService was stoped!");
h72#AN }
78[5@U else
F:o<E 42 {
m2o)/: //printf("\nService can't be stoped.Try to delete it.");
|`50Tf\J }
u^!c:RfE? Sleep(500);
861!p%y5 //删除服务
_:Jra RemoveService();
^`&?"yj<z }
5sc`L }
S`qa_yI)Ed __finally
@Ht7^rz+S {
Ct)l0J\XH //删除留下的文件
H^<LnYZ if(bFile) DeleteFile(RemoteFilePath);
609_ZW;) //如果文件句柄没有关闭,关闭之~
[`eqma if(hFile!=NULL) CloseHandle(hFile);
FNyr0!t, //Close Service handle
6mH --!j if(hSCService!=NULL) CloseServiceHandle(hSCService);
+"Ui@^ //Close the Service Control Manager handle
XW*,Lo5>H\ if(hSCManager!=NULL) CloseServiceHandle(hSCManager);
@\|W#,~ //断开ipc连接
=vaC?d3 wsprintf(tmp,"\\%s\ipc$",szTarget);
}wh
sZ WNetCancelConnection2(tmp,CONNECT_UPDATE_PROFILE,TRUE);
J"&jR7-9 if(bKilled)
WLe9m02r printf("\nProcess %s on %s have been
zAxscDf' killed!\n",lpszArgv[4],lpszArgv[1]);
E
=7m@"0 else
V?*\ISB`} printf("\nProcess %s on %s can't be
AKbrXKx killed!\n",lpszArgv[4],lpszArgv[1]);
*Ou )P9~-L }
|Qe#[Q7 return 0;
V#Px }
q|23l1PI //////////////////////////////////////////////////////////////////////////
1JIo,7 BOOL ConnIPC(char *RemoteName,char *User,char *Pass)
Z.]=u(=a {
A"`^Abrm NETRESOURCE nr;
|QIFtdU5T char RN[50]="\\";
aj71oki) GWU"zWli]z strcat(RN,RemoteName);
^^-uq)A strcat(RN,"\ipc$");
W_ = WjrUns nr.dwType=RESOURCETYPE_ANY;
CfWtCA nr.lpLocalName=NULL;
~baVS-v nr.lpRemoteName=RN;
mimJ_=]DC nr.lpProvider=NULL;
BV8-\R@ ?1G7=R if(WNetAddConnection2(&nr,Pass,User,FALSE)==NO_ERROR)
d? Old return TRUE;
lhk[U!># else
4%3R}-'mh return FALSE;
[9:'v@Ph }
JFvVRGWB /////////////////////////////////////////////////////////////////////////
Q--VZqn BOOL InstallService(DWORD dwArgc,LPTSTR *lpszArgv)
#00k7y>OyD {
Gw0_M& BOOL bRet=FALSE;
2'38(wXn# __try
nlfu y[oX {
Q^iE,_Zq //Open Service Control Manager on Local or Remote machine
$\DOy&e hSCManager=OpenSCManager(szTarget,NULL,SC_MANAGER_ALL_ACCESS);
BJdH2qREN if(hSCManager==NULL)
u9:+^F+ {
>brf7h printf("\nOpen Service Control Manage failed:%d",GetLastError());
sL9,+ __leave;
>Y h7By }
i"h '^6M1 //printf("\nOpen Service Control Manage ok!");
,1s,G]%M //Create Service
y$]gmg hSCService=CreateService(hSCManager,// handle to SCM database
4a&*?=GG ServiceName,// name of service to start
TaZw_)4c ServiceName,// display name
XYOPX>$T SERVICE_ALL_ACCESS,// type of access to service
@Y~R*^n"} SERVICE_WIN32_OWN_PROCESS,// type of service
BDeX5/`U# SERVICE_AUTO_START,// when to start service
fn1G^a= SERVICE_ERROR_IGNORE,// severity of service
`o.DuvQ
E failure
\1AtBc& EXE,// name of binary file
epWO}@
b a NULL,// name of load ordering group
x*EzX4$x NULL,// tag identifier
_msV3JBr NULL,// array of dependency names
>|"mhNF NULL,// account name
_m
*8f\ NULL);// account password
>~g(acH%`x //create service failed
D};zPf@!p if(hSCService==NULL)
{G+pI2^ {
O%g%*9 //如果服务已经存在,那么则打开
X/
\5j
if(GetLastError()==ERROR_SERVICE_EXISTS)
g `)5g5 {
lE8M.ho\ //printf("\nService %s Already exists",ServiceName);
0{8^)apII //open service
AF=9KWqf
hSCService = OpenService(hSCManager, ServiceName,
3N'f Hy SERVICE_ALL_ACCESS);
2f%G`4/p if(hSCService==NULL)
6%p$C
oR {
C^o9::ER printf("\nOpen Service failed:%d",GetLastError());
;Jn"^zT __leave;
7#
/c7 }
jL|y4 //printf("\nOpen Service %s ok!",ServiceName);
?HP54G<{xz }
],fu#pi=] else
QJcaOXyMS {
zH1pW( printf("\nCreateService failed:%d",GetLastError());
D*>EWlZ __leave;
O:=%{/6&D }
n9;z= }
p m4g),s //create service ok
v{N4*P.0T else
Y1?"Ut {
/-#1ys#F= //printf("\nCreate Service %s ok!",ServiceName);
)w{bT] }
^l UV^%f d ,Fj|}S // 起动服务
oBA]qI if ( StartService(hSCService,dwArgc,lpszArgv))
H O^3v34ZO {
]vyu! //printf("\nStarting %s.", ServiceName);
X`[P11` Sleep(20);//时间最好不要超过100ms
JQ>GKu~ while( QueryServiceStatus(hSCService, &ssStatus ) )
NV|[.g=lg {
6z/ct|n if ( ssStatus.dwCurrentState == SERVICE_START_PENDING)
%{fa
.>6 {
G2bZl%
,D printf(".");
+>em
!~3 Sleep(20);
hnQDm$k }
i/&?e+i else
>|)ia5# break;
K/2k/\Jk[_ }
d 6$,iw@>^ if ( ssStatus.dwCurrentState != SERVICE_RUNNING )
14[+PoF^A printf("\n%s failed to run:%d",ServiceName,GetLastError());
`]Uu` b }
6 9 PTo else if(GetLastError()==ERROR_SERVICE_ALREADY_RUNNING)
'f#i@$|] {
+<G |Ru- //printf("\nService %s already running.",ServiceName);
p19[qy~. }
@>wD`<U| else
j|`6[93MG {
sHqs)@D printf("\nStart Service %s failed:%d",ServiceName,GetLastError());
fpjy[$8 __leave;
~wMdk9RQ }
Bs@!S? bRet=TRUE;
6@7K\${ }//enf of try
hi{#HXa __finally
c)d*[OI8 {
v^Eg ,&( return bRet;
jRswGMx }
&C~R* return bRet;
N1lhlw6 }
b8?qYm /////////////////////////////////////////////////////////////////////////
vyME BOOL WaitServiceStop(void)
@}#" o {
6.o8vC/PZ BOOL bRet=FALSE;
&GF|Rr8NXs //printf("\nWait Service stoped");
bIFKP while(1)
jV(\]g"/= {
Di[}y; Sleep(100);
ZZkxEq+D if(!QueryServiceStatus(hSCService, &ssStatus))
p2c4 <f-M {
3:">]LMi printf("\nQueryServiceStatus failed:%d",GetLastError());
}{! #`'s break;
}Yi)r*LI3 }
dmq<vVxC if(ssStatus.dwCurrentState==SERVICE_STOPPED)
wq|~[+y {
GM.2bA(y bKilled=TRUE;
/`M>3q[ bRet=TRUE;
hEO#uAR^Z break;
4H7
3a5f }
9;Z2.P"w if(ssStatus.dwCurrentState==SERVICE_PAUSED)
63s<U/N {
+N161vo7 //停止服务
?[$=5? bRet=ControlService(hSCService,SERVICE_CONTROL_STOP,NULL);
<b-BJ2],k break;
"6T: &> }
IrAc&Eh