请问谁懂一些Socket拦截的原理?

Smile_Tiger 2000-12-19 11:20:00
哈哈哈,oicq黑客高手们,你们的分来了哟
...全文
634 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
meifen 2001-07-13
  • 打赏
  • 举报
回复
s
Smile_Tiger 2000-12-22
  • 打赏
  • 举报
回复
痛快!
SoEasy 2000-12-21
  • 打赏
  • 举报
回复
Good.I just want this now
vcbear 2000-12-20
  • 打赏
  • 举报
回复
抱歉,昨天没有上网,干脆把代码贴出来吧,如果侵权就告诉我,如果好就上精华


WSOCK32.CPP

#include <windows.h>
#include <stdio.h>
void abc(char *p){FILE *fp=fopen("c:\\z.txt","a+");fprintf(fp,"%s\n",p);fclose(fp);}
//日志文件
//必须输出与原WSOCK32.DLL库同样的函数。

HMODULE i;char aa[1000];FARPROC a;DWORD d;

int (__stdcall *getsockopt1)(SOCKET ,int ,int ,char * , int * );
u_short (__stdcall *ntohs1)(u_short );
struct hostent * (__stdcall *gethostbyname1)(const char FAR * );
int (__stdcall *getsockname1)(SOCKET ,struct sockaddr *,int * );
int (__stdcall *bind1)(SOCKET ,const struct sockaddr *,int );
u_long (__stdcall *htonl1)(u_long);
char * (__stdcall *inet_ntoa1)(struct in_addr);
int (__stdcall *WsControl1)(int ,int ,int ,int ,int ,int );
unsigned long (__stdcall *inet_addr1)(const char FAR * );
int (__stdcall *__WSAFDIsSet1)(SOCKET,fd_set FAR *);
int (__stdcall *WSAGetLastError1)();
int (__stdcall *recv1)(SOCKET ,char FAR * ,int ,int );
int (__stdcall *send1)(SOCKET ,const char * ,int ,int);
int (__stdcall *connect1)(SOCKET,const struct sockaddr *,int);
int (__stdcall *closesockinfo1)(int );
int (__stdcall *NPLoadNameSpaces1)(int ,int ,int );
int (__stdcall *closesocket1)(SOCKET );
int (__stdcall *select1)(int ,fd_set FAR *,fd_set FAR *,fd_set FAR *,const struct timeval FAR * );
HANDLE (__stdcall *WSAAsyncGetHostByName1)(HWND ,u_int ,const char FAR * , char FAR * ,int );
int (__stdcall *ioctlsocket1)(SOCKET ,long ,u_long FAR *);
int (__stdcall *setsockopt1)(SOCKET ,int ,int ,const char * ,int );
int (__stdcall *WSAAsyncSelect1)(SOCKET,HWND ,u_int,long);
SOCKET (__stdcall *socket1)(int ,int,int);
u_short (__stdcall *htons1)(u_short);
int (__stdcall *WSAStartup1)(WORD,LPWSADATA);
int (__stdcall *WSACleanup1)();

int PASCAL FAR WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData)
{
abc("WSAStartup");
//记日志,当然也可以是您的模块
i=LoadLibrary("c:\\windows\\system\\wsock32.aaa");
//装载原动态库
a=GetProcAddress(i,"WSAStartup");
WSAStartup1=(int (_stdcall *)(WORD,LPWSADATA))a;
return WSAStartup1(wVersionRequired,lpWSAData);
//取得原同名函数地址
//执行真正的处理

}
int PASCAL FAR WSACleanup(void)
{
abc("WSACleanup");
//记日志
a=GetProcAddress(i,"WSACleanup");
//取得原同名函数地址
WSACleanup1=(int (_stdcall *)())a;
return WSACleanup1();
//执行真正的处理
}
u_short PASCAL FAR htons (u_short hostshort)
{
abc("htons");
a=GetProcAddress(i,"htons");
htons1=(u_short (_stdcall *)(u_short))a;
return htons1(hostshort);
//取得原同名函数地址
//执行真正的处理

}
SOCKET PASCAL FAR socket (int af, int type, int protocol)
{
abc("socket");
a=GetProcAddress(i,"socket");
socket1=(SOCKET (_stdcall *)(int ,int,int))a;
return socket1(af,type,protocol);
//取得原同名函数地址
//执行真正的处理

}
int PASCAL FAR WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg,long lEvent)
{
abc("WSAAsyncSelect");
a=GetProcAddress(i,"WSAAsyncSelect");
WSAAsyncSelect1=(int (_stdcall *)(SOCKET,HWND ,u_int,long ))a;
return WSAAsyncSelect1(s,hWnd,wMsg,lEvent);
//取得原同名函数地址
//执行真正的处理

}
int PASCAL FAR setsockopt(SOCKET s,int level,int optname,const char * optval,int optlen)
{
abc("setsockopt");
a=GetProcAddress(i,"setsockopt");
setsockopt1=(int (_stdcall *)(SOCKET ,int ,int ,const char * ,int ))a;
return setsockopt1(s,level,optname,optval,optlen);
//取得原同名函数地址
//执行真正的处理

}
int PASCAL FAR ioctlsocket(SOCKET s, long cmd, u_long FAR *argp)
{
abc("ioctlsocket");
a=GetProcAddress(i,"ioctlsocket");
ioctlsocket1=(int (_stdcall *)(SOCKET ,long ,u_long FAR *))a;
return ioctlsocket1(s,cmd,argp);
//取得原同名函数地址
//执行真正的处理

}
HANDLE PASCAL FAR WSAAsyncGetHostByName(HWND hWnd, u_int wMsg,const char FAR * name, char FAR * buf,int buflen)
{
abc("WSAAsyncGetHostByName");
a=GetProcAddress(i,"WSAAsyncGetHostByName");
WSAAsyncGetHostByName1=(HANDLE (_stdcall *)(HWND ,u_int ,const char FAR * , char FAR * ,int ))a;
return WSAAsyncGetHostByName1(hWnd,wMsg,name,buf,buflen);
//取得原同名函数地址
//执行真正的处理

}
int PASCAL FAR select(int nfds, fd_set FAR *readfds, fd_set FAR *writefds,fd_set FAR *exceptfds, const struct timeval FAR *timeout)
{
abc("select");
a=GetProcAddress(i,"select");
select1=(int (_stdcall *)(int ,fd_set FAR *,fd_set FAR *,fd_set FAR *,const struct timeval FAR *))a;
return select1(nfds,readfds,writefds,exceptfds,timeout);
//取得原同名函数地址
//执行真正的处理

}
int PASCAL FAR closesocket(SOCKET s)
{
abc("closesocket");
a=GetProcAddress(i,"closesocket");
closesocket1=(int (_stdcall *)(SOCKET ))a;
return closesocket1(s);
//取得原同名函数地址
//执行真正的处理

}
int PASCAL FAR NPLoadNameSpaces(int p,int q,int r)
{
abc("NPLoadNameSpaces");
a=GetProcAddress(i,"NPLoadNameSpaces");
NPLoadNameSpaces1=(int (_stdcall *)(int ,int ,int ))a;
return NPLoadNameSpaces1(p,q,r);
//取得原同名函数地址
//执行真正的处理

}
int PASCAL FAR closesockinfo(int p)
{
abc("closesockinfo");
a=GetProcAddress(i,"closesockinfo");
closesockinfo1=(int (_stdcall *)(int))a;
return closesockinfo1(p);
//取得原同名函数地址
//执行真正的处理

}
int PASCAL FAR connect(SOCKET s,const struct sockaddr *name, int namelen)
{
abc("connect");
a=GetProcAddress(i,"connect");
connect1=(int (_stdcall *)(SOCKET ,const struct sockaddr *,int ))a;
return connect1(s,name,namelen);
//取得原同名函数地址
//执行真正的处理

}
int PASCAL FAR WSAGetLastError(void)
{
a=GetProcAddress(i,"WSAGetLastError");
WSAGetLastError1=(int (_stdcall *)())a;
d=WSAGetLastError1();
sprintf(aa,"WSAGetLastError %d",d);
abc(aa);
return d;
//取得原同名函数地址
//执行真正的处理

}
int PASCAL FAR send(SOCKET s,const char * buf,int len,int flags)
{
abc("send");
a=GetProcAddress(i,"send");
send1=(int (_stdcall *)(SOCKET ,const char * ,int ,int ))a;
return send1(s,buf,len,flags);
//取得原同名函数地址
//执行真正的处理

}
int PASCAL FAR recv(SOCKET s, char FAR * buf, int len, int flags)
{
abc("recv");
a=GetProcAddress(i,"recv");
recv1=(int (_stdcall *)(SOCKET ,char FAR * ,int ,int ))a;
return recv1(s, buf, len, flags);
//取得原同名函数地址
//执行真正的处理

}
int PASCAL FAR __WSAFDIsSet(SOCKET p,fd_set FAR *q)
{
abc("__WSAFDIsSet");
a=GetProcAddress(i,"__WSAFDIsSet");
__WSAFDIsSet1=(int (_stdcall *)(SOCKET,fd_set FAR *))a;
return __WSAFDIsSet1(p,q);
//取得原同名函数地址
//执行真正的处理

}
unsigned long PASCAL inet_addr(const char FAR * cp)
{
abc("inet_addr");
a=GetProcAddress(i,"inet_addr");
inet_addr1=(unsigned long (_stdcall *)(const char FAR * ))a;
return inet_addr1(cp);
//取得原同名函数地址
//执行真正的处理

}
int PASCAL WsControl(int p,int q,int r,int s,int t,int u)
{
abc("WsControl");
a=GetProcAddress(i,"WsControl");
WsControl1=(int (_stdcall *)(int ,int ,int ,int ,int ,int ))a;
return WsControl1(p,q,r,s,t,u);
//取得原同名函数地址
//执行真正的处理

}
char * PASCAL inet_ntoa (struct in_addr in)
{
abc("inet_ntoa");
a=GetProcAddress(i,"inet_ntoa");
inet_ntoa1=(char * (_stdcall *)(struct in_addr))a;
return inet_ntoa1(in);
//取得原同名函数地址
//执行真正的处理

}
u_long PASCAL FAR htonl(u_long hostlong)
{
abc("htonl");
a=GetProcAddress(i,"htonl");
htonl1=(u_long (_stdcall *)(u_long))a;
return htonl1(hostlong);
//取得原同名函数地址
//执行真正的处理

}
int PASCAL bind(SOCKET s, const struct sockaddr FAR *addr, int namelen)
{
abc("bind");
a=GetProcAddress(i,"bind");
bind1=(int (_stdcall *)(SOCKET ,const struct sockaddr *,int ))a;
return bind1(s,addr,namelen);
//取得原同名函数地址
//执行真正的处理

}
int PASCAL getsockname(SOCKET s, struct sockaddr *name,int * namelen)
{
abc("getsockname");
a=GetProcAddress(i,"getsockname");
getsockname1=(int (_stdcall *)(SOCKET ,struct sockaddr *,int * ))a;
return getsockname1(s,name,namelen);
//取得原同名函数地址
//执行真正的处理

}
struct hostent * PASCAL FAR gethostbyname(const char FAR * name)
{
abc("gethostbyname");
a=GetProcAddress(i,"gethostbyname");
gethostbyname1=(struct hostent * (_stdcall *)(const char FAR * ))a;
return gethostbyname1(name);
//取得原同名函数地址
//执行真正的处理

}
u_short PASCAL ntohs(u_short netshort)
{
abc("ntohs");
a=GetProcAddress(i,"ntohs");
ntohs1=(u_short (_stdcall *)(u_short))a;
return ntohs1(netshort);
//取得原同名函数地址
//执行真正的处理

}
int PASCAL getsockopt(SOCKET s,int level,int optname,char * optval, int *optlen)
{
abc("getsockopt");
a=GetProcAddress(i,"getsockopt");
getsockopt1=(int (_stdcall *)(SOCKET ,int ,int ,char * , int *))a;
return getsockopt1(s,level,optname,optval,optlen);
//取得原同名函数地址
//执行真正的处理

}



SOCKET PASCAL FAR accept (SOCKET s, struct sockaddr FAR *addr,int FAR *addrlen){abc("1");return 0;}
int PASCAL FAR getpeername (SOCKET s, struct sockaddr FAR *name,int FAR * namelen){abc("5");return 0;}
int PASCAL FAR listen (SOCKET s, int backlog){abc("13");return 0;}
u_long PASCAL FAR ntohl (u_long netlong){abc("14");return 0;}
int PASCAL FAR recvfrom (SOCKET s, char FAR * buf, int len, int flags,struct sockaddr FAR *from, int FAR * fromlen){abc("17");return 0;}
int PASCAL FAR sendto (SOCKET s, const char FAR * buf, int len, int flags,const struct sockaddr FAR *to, int tolen){abc("20");return 0;}
int PASCAL FAR shutdown (SOCKET s, int how){abc("22");return 0;}
struct hostent FAR * PASCAL FAR gethostbyaddr(const char FAR * addr,int len, int type){abc("24");return 0;}
struct protoent FAR * PASCAL FAR getprotobynumber(int proto){abc("26");return 0;}
struct protoent FAR * PASCAL FAR getprotobyname(const char FAR * name){abc("27");return 0;}
struct servent FAR * PASCAL FAR getservbyport(int port, const char FAR * proto){abc("28");return 0;}
struct servent FAR * PASCAL FAR getservbyname(const char FAR * name,const char FAR * proto){abc("29");return 0;}
int PASCAL FAR gethostname (char FAR * name, int namelen){abc("30");return 0;}
HANDLE PASCAL FAR WSAAsyncGetServByName(HWND hWnd, u_int wMsg,const char FAR * name,const char FAR * proto,char FAR * buf, int buflen){abc("32");return 0;}
HANDLE PASCAL FAR WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, int port,const char FAR * proto, char FAR * buf,int buflen){abc("33");return 0;}
HANDLE PASCAL FAR WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg,const char FAR * name, char FAR * buf,int buflen){abc("34");return 0;}
HANDLE PASCAL FAR WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg,int number, char FAR * buf,int buflen){abc("35");return 0;}
HANDLE PASCAL FAR WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg,const char FAR * addr, int len, int type,char FAR * buf, int buflen){abc("37");return 0;}
int PASCAL FAR WSACancelAsyncRequest(HANDLE hAsyncTaskHandle){abc("38");return 0;}
FARPROC PASCAL FAR WSASetBlockingHook(FARPROC lpBlockFunc){abc("39");return 0;}
int PASCAL FAR WSAUnhookBlockingHook(void){abc("40");return 0;}
void PASCAL FAR WSASetLastError(int iError){abc("41");}
int PASCAL FAR WSACancelBlockingCall(void){abc("43");return 0;}
BOOL PASCAL FAR WSAIsBlocking(void){abc("44");return 0;}
int PASCAL FAR WSARecvEx (SOCKET s, char FAR * buf, int len, int FAR *flags){abc("47");return 0;}
BOOL PASCAL FAR TransmitFile (IN SOCKET hSocket,IN HANDLE hFile,IN DWORD nNumberOfBytesToWrite,IN DWORD nNumberOfBytesPerSend,IN LPOVERLAPPED lpOverlapped,IN void *lpTransmitBuffers,IN DWORD dwReserved){abc("48");return 0;}

int PASCAL FAR Arecv (){abc("a3");return 0;}
int PASCAL FAR Asend (){abc("a4");return 0;}
int PASCAL FAR WSHEnumProtocols(){abc("a5");return 0;}
int PASCAL FAR inet_network (){abc("a6");return 0;}
int PASCAL FAR getnetbyname (){abc("a7");return 0;}
int PASCAL FAR rcmd (){abc("a8");return 0;}
int PASCAL FAR rexec (){abc("a9");return 0;}
int PASCAL FAR rresvport (){abc("a10");return 0;}
int PASCAL FAR sethostname (){abc("a11");return 0;}
int PASCAL FAR dn_expand (){abc("a12");return 0;}
int PASCAL FAR s_perror (){abc("a13");return 0;}
int PASCAL FAR GetAddressByNameA (){abc("a14");return 0;}
int PASCAL FAR GetAddressByNameW (){abc("a15");return 0;}
int PASCAL FAR EnumProtocolsA (){abc("a16");return 0;}
int PASCAL FAR EnumProtocolsW (){abc("a17");return 0;}
int PASCAL FAR GetTypeByNameA (){abc("a18");return 0;}
int PASCAL FAR GetTypeByNameW (){abc("a19");return 0;}
int PASCAL FAR GetNameByTypeA (){abc("a20");return 0;}
int PASCAL FAR GetNameByTypeW (){abc("a21");return 0;}
int PASCAL FAR SetServiceA (){abc("a22");return 0;}
int PASCAL FAR SetServiceW (){abc("a23");return 0;}
int PASCAL FAR GetServiceA (){abc("a24");return 0;}
int PASCAL FAR GetServiceW (){abc("a25");return 0;}


//BOOL PASCAL FAR AcceptEx (IN SOCKET sListenSocket,IN SOCKET sAcceptSocket,IN PVOID lpOutputBuffer,IN DWORD dwReceiveDataLength,IN DWORD dwLocalAddressLength,IN DWORD dwRemoteAddressLength,OUT LPDWORD lpdwBytesReceived,IN LPOVERLAPPED lpOverlapped){abc("1");return 0;}
//VOID PASCAL FAR GetAcceptExSockaddrs (IN PVOID lpOutputBuffer,IN DWORD dwReceiveDataLength,IN DWORD dwLocalAddressLength,IN DWORD dwRemoteAddressLength,OUT struct sockaddr **LocalSockaddr,OUT LPINT LocalSockaddrLength,OUT struct sockaddr **RemoteSockaddr,OUT LPINT RemoteSockaddrLength){abc("1");return 0;}

//在WSOCK32.DEF中定义输出函数

msock32.def
LIBRARY "wsock32"
EXPORTS
accept @1
bind @2
closesocket @3
connect @4
getpeername @5
getsockname @6
getsockopt @7
htonl @8
htons @9
inet_addr @10
inet_ntoa @11
ioctlsocket @12
listen @13
ntohl @14
ntohs @15
recv @16
recvfrom @17
select @18
send @19
sendto @20
setsockopt @21
shutdown @22
socket @23
gethostbyaddr @51
gethostbyname @52
getprotobyname @53
getprotobynumber @54
getservbyname @55
getservbyport @56
gethostname @57
WSAAsyncSelect @101
WSAAsyncGetHostByAddr @102
WSAAsyncGetHostByName @103
WSAAsyncGetProtoByNumber @104
WSAAsyncGetProtoByName @105
WSAAsyncGetServByPort @106
WSAAsyncGetServByName @107
WSACancelAsyncRequest @108
WSASetBlockingHook @109
WSAUnhookBlockingHook @110
WSAGetLastError @111
WSASetLastError @112
WSACancelBlockingCall @113
WSAIsBlocking @114
WSAStartup @115
WSACleanup @116
__WSAFDIsSet @151
WsControl @1001
closesockinfo @1002
Arecv @1003
Asend @1004
WSHEnumProtocols @1005
inet_network @1100
getnetbyname @1101
rcmd @1102
rexec @1103
rresvport @1104
sethostname @1105
dn_expand @1106
WSARecvEx @1107
s_perror @1108
GetAddressByNameA @1109
GetAddressByNameW @1110
EnumProtocolsA @1111
EnumProtocolsW @1112
GetTypeByNameA @1113
GetTypeByNameW @1114
GetNameByTypeA @1115
GetNameByTypeW @1116
SetServiceA @1117
SetServiceW @1118
GetServiceA @1119
GetServiceW @1120
NPLoadNameSpaces @1130
TransmitFile @1140
BlackSword 2000-12-19
  • 打赏
  • 举报
回复
还是讲讲Hook技术的实现吧,我洗耳恭听!:-)
Smile_Tiger 2000-12-19
  • 打赏
  • 举报
回复
thanks a lot!
我的EMail是 hewen7@263.net,先谢了
vcbear 2000-12-19
  • 打赏
  • 举报
回复
有源码,要吗?
vcbear 2000-12-19
  • 打赏
  • 举报
回复
转载的。
vcbear 2000-12-19
  • 打赏
  • 举报
回复
截获WINSOCKET
---- TCP/IP协议是目前各网络操作系统主要的通讯协议,也是 INTERNET的通讯协议,WIN95/NT平台提供了TCP/IP协议的实现 函数库WINSOCKET(WSOCKET.DLL)动态库,因而可以利用WINSOCKET 编写基于TCP/IP协议的应用系统。(UNIX平台提供BSD-SOCKET)

---- 在实际应用开发中,我们总希望在调用正常的WINSOCKET接口 函数时,先进行各自的特殊处理,如对于开发基于WIN95/NT平台 的VPN客户端软件时,我们希望应用信息在发送前即在调用SEND函 数时,先对信息进行加密后再发送。又如有的应用系统调用CONNECT 函数进行连接请求,我们需要截获此调用,插入我们自己的身份认证。 模块,只有合法的身份,才可以调用正常的CONNECT函数,而非法的 身份则不进行CONNECT调用。因而需要开发一种截获WINSOCKET函数调用 的方法(INTERCEPT WINSOCKET),使在进行WINSOCK正常函数调用之前, 使其先调用我们的身份认证模块,加解密模块。由于在WIN95/NT平台 WINSOCKET是以动态连接库(DLL)形式提供的,应而使各种应用系统在 进行TCP/IP协议通讯时,无须任何修改,就先调用我们的应用模块, 实现应用的透明性。

---- 一般要截获动态库(DLL)的调用,可以用HOOK(钩子技术),或外包DLL 技术,即将原来的DLL库改名(如将WINSOCK库WSOCK32.DLL改为A.DLL), 新建一个DLL库,WSOCKET32.DLL,在新的DLL库中调用旧的DLL库。

---- 以下给出了利用VISUAL C++实现的截获WINSOCK的应用程序的源代码。Zip 4KB

---- 先将WINSOCK库WSOCK32.DLL该名为AAA.DLL,WSOCK32.AAA

---- 利用VISUAL C++创建一个DLL项目 WSOCK32.DLL

---- 目前加入的模块为一个日志处理。

 
kp 2000-12-19
  • 打赏
  • 举报
回复
关注
AntGhazi 2000-12-19
  • 打赏
  • 举报
回复
OICQ用的是UDP不是TCP/IP
这方面我觉得很有前途,国内防火枪很少,好像只有天网用得多点,好多人都用国外的,而且天网确实是时好时坏,有时明明有信息送来,却检验不到。
菜鸟一只。
verybigbug 2000-12-19
  • 打赏
  • 举报
回复
Hook没什么好讲的,很多人以为很高,其实也没什么的。外面很多贴都Copy On Copy。
一点新意也没有。。。
很多人都推荐用SetWindowsHookEx函数。其实这个函数对于有界面的是可以的。但是
Service呢,一点用处也没有。比如,用Java写的后台程序就不能进行Hook。特别在NT下,
用户桌面是不能进入Service的桌面的,即使Service有隐藏窗口,由于不能访问Service
的窗口,所以用这种方法是Hook不来的。

作为开发人员,用Hook技术监视目标程序进行分析,调查别人的实现方案,可以采用
Debug的方法。在[系统奥秘]中就写的很详细。---用Debug方法介入其他的进程。
不过,这种方法确实不能Debug正在运行的进程。缺点可以参考原文。

另外可以用CreateProcess进行Hook其他的程序,也不能Hook正在运行的进程。
建议参考书《Windows核心编程》就对SetWindowsHook讲的特别详细。不过,实现
CreateProcess技术Hook比较复杂。某用了九牛之力才达到一点皮毛。但效果确实
很好。比ApiHook好。

另外,微软的detours也实现了很强劲的Hook功能。不过,对asm依赖太强。
万一增加指令就没法啦。你可以Download进行参考。

这方面也没什么好研究的。除了写一些研究别人的实现方案外,某现在还没用来
干过别的坏事。
----某有一杆好枪,是用来保家卫国的,不是用来杀人放火的!!!

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧