注释了holy_father写的这个端口转发的程序,虽然注释了大部分代码,本人还是不敢说把代码完全
搞懂了,比如转发的过程偶就不是很明白,如果那个大牛了解这个程序端口转发的过程,请指导偶一
下下,如果那个朋友有不懂得地方或者发现偶注释错误的地方.
//
;====================[ The Smallest TCP Port Redirector ]=======================
;
;
;
;Copyright (c) 2000,forever ExEwORx
;birthday: 8.9.2002
;version: 1.0
;
;compiled with MASM 6.14 with ALIGN:4
;total size: 2512b
;write no output, silently terminates when error
;it is multithreaded and stable on Windows NT 4.0, Windows 2000 and Windows XP
;
;usage: sredir.exe listen_on_port redir_to_ip redir_to_port
; redir_to_ip must be IP address in A.B.C.D format
; no DNS implemented
;
;example: sredir.exe 100 212.80.76.18 80
;
;no other comments, cuz code is comment :)
;
.386p
.model flat, stdcall
include kernel32.inc
include winsock2.inc
LocalAlloc PROTO :DWORD,:DWORD
LocalFree PROTO :DWORD
ExitThread PROTO :DWORD
ExitProcess PROTO :DWORD
GetCommandLineA PROTO
Sleep PROTO :DWORD
CloseHandle PROTO :DWORD
CreateThread PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
TerminateThread PROTO :DWORD,:DWORD
WaitForMultipleObjects PROTO :DWORD,:DWORD,:DWORD,:DWORD
bind PROTO :DWORD,:DWORD,:DWORD
listen PROTO :DWORD,:DWORD
recv PROTO :DWORD,:DWORD,:DWORD,:DWORD
send PROTO :DWORD,:DWORD,:DWORD,:DWORD
closesocket PROTO :DWORD
inet_addr PROTO :DWORD
WSAIoctl PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,
:DWORD,:DWORD
WSAStartup PROTO :DWORD,:DWORD
WSACleanup PROTO
WSACreateEvent PROTO
WSASocketA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
WSAConnect PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
WSAEnumNetworkEvents PROTO :DWORD,:DWORD,:DWORD
WSAAccept PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
WSAEventSelect PROTO :DWORD,:DWORD,:DWORD
WSAWaitForMultipleEvents PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
SOMAXCONN equ 07FFFFFFFh
IPPROTO_TCP equ 006h
SOCK_STREAM equ 001h
AF_INET equ 002h
FIONREAD equ 04004667Fh
WAITFOREVENTSTIMEOUT equ 0FAh
WSA_WAIT_TIMEOUT equ 00102h
SOCK_ADDR_SIZE equ 010h
FD_READ equ 001h
FD_ACCEPT equ 008h
FD_CLOSE equ 020h
FD_ALL_EVENTS equ 003FFh
LMEM_FIXED equ 000h
.data
.code
start:
mov ebp,esp
sub esp,001ECh; 保存一段堆栈空间
lea eax,[ebp-01ECh];指向WSADATA的指针
push eax
push 0202h
call WSAStartup; 启动socket
test eax, eax ;测试
jnz @end
xor eax,eax ;得到命令行参数
call GetCommandLineA
mov esi,eax ;保存指针到esi
xor eax,eax
lodsb ;将命令行参数的第一个字节装入eax
cmp al,022h ;是否含有该死的"
setz al
mov [ebp-004h],eax ;将第一个字符保存到堆栈中
@Next_char:
lodsb ;装入下个字节
test eax,eax ;是否已经到达末尾
jz @end ;是。跳
sub al,020h ;是否为空格?
jz @Space_found ;是,跳 处理空格
dec eax ;是否是一个.
dec eax
setnz al ;是就屏蔽掉
and [ebp-004h],eax ;
jmp @Next_char
@Space_found:
cmp byte ptr [ebp-004h],000h ; 测试是否是尾部
jnz @Next_char ;不是,找到一个参数
call @Find_arg
mov edi,esi ;将edi设置为字符串指针
push 020h ;为eax赋值
pop eax
call @arg_len ;调用函数,得到参数长度
mov ecx,eax ;保存字符串长度
lea edi,[ebp-0100h]
push edi
rep movsb ;将参数移动到堆栈
mov [edi],cl ;为字符串加个null
call @IntToStr
mov [ebp-004h],eax ;把eax存入堆栈
inc eax
jz @end ;如果是0则字符串转化时出现错误,跳
inc edi ;修改edi指针,查找下一个参数
push edi
call @Find_arg
xchg esi,edi
push 020h
pop eax
call @arg_len ;---------------+
mov ecx,eax ; +
xchg esi,edi ; +
rep movsb ; +
mov [edi],cl ; +
call inet_addr; ; +
mov [ebp-008h],eax ; +
inc eax ; +
jz @end ; +
call @Find_arg ; +
inc edi ; +
push edi ; +
xchg esi,edi ; +
xor eax,eax ; +
call @arg_len ; +
mov ecx,eax ; +-------下面的查找过程,和上面基本一直,不在废话鸟~
xchg esi,edi ; +
rep movsb ; +
mov [edi],cl ; +
call @IntToStr ; +
mov [ebp-00Ch],eax ; +
inc eax ; +
jz @end ; +
mov eax,[ebp-00Ch] ; +
shl eax,010h ; +
mov ax,[ebp-004h] ; +
push eax ; +
push dword ptr [ebp-008h]
call @Server ; +
@end:
call WSACleanup; ; +
push 000h ; +
call ExitProcess; ;---------------+
@IntToStr:
push esi ;保存参数指针
xor eax,eax ;清空eax,edx
xor edx,edx
mov esi,[esp+008h] ;将edi的值存入esi。如果问为什么,自己去算下
@IntToStr_next_char:
lodsb ;像eax中装入一个字节
test eax,eax ;是否到达null
jz @IntToStr_end ;日,到了,跑路
imul edx,edx,00Ah ;edx=edx*10
cmp al,030h ;al是否为0
jb @IntToStr_error ;汗比0还小,跳
cmp al,039h ;是否为9
ja @IntToStr_error ;汗,比九大跳
sub eax,030h
add edx,eax ;转换完成
jmp @IntToStr_next_char ;处理下一个字符
@IntToStr_error:
xor edx,edx ;清空edx
dec edx
@IntToStr_end:
mov eax,edx
pop esi
ret
@arg_len: ;@arg -> edi, char -> eax
push edi ;指向参数的字符串
xor ecx,ecx
dec ecx ;比较是否已经到达空格,没有则重复
repnz scasb ;
not ecx ;这里说明一下,ecx为什么要设为-1,因为偶们的指针现在指向的是参数的尾部
dec ecx ;偶们要采取逆序的方法查找前一个空格,故设为负值在求反减1就能得到长度
mov eax,ecx ;如果不这样做,而采用调整指针,会浪费很多代码,不利于优化,这段代码值得大家学习的说
pop edi
ret
@Find_arg: ;str -> esi -> esi
lodsb
cmp al,020h
jz @Find_arg
dec esi
ret
@Server:
push ebp
mov ebp,esp
sub esp,034h
; -030 - NewClient.Host.sin_family:Word
; -02E - NewClient.Host.sin_port:Word
; -02C - NewClient.Host.sin_addr:TInAddr
; -028..-024 - NewClient.Host.sin_zero:array[0..7] of Char
; -020 - NewClient.Socket:TSocket
; -01C - TID:Cardinal;
; -018 - ServerEventHandle:THandle
; -014 - ServerHost.sin_family:Word
; -012 - ServerHost.sin_port:Word
; -010 - ServerHost.sin_addr:TInAddr
; -00C..-008 - ServerHost.sin_zero:array[0..7] of Char
; -004 - ServerSocket:TSocket
; +008 - FinalAddr:TInAddr
; +00C - ListenPort:Word
; +010 - FinalPort:Word
push esi
push edi
push ebx
xor eax,eax
mov [ebp-010h],eax ;WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,0,0,0)
push eax ;建立一个套接字
push eax
push eax
push IPPROTO_TCP
push SOCK_STREAM
push AF_INET
call WSASocketA
mov [ebp-004h],eax ;讲套接字保存到堆栈
inc eax ;是否建立失败,是,跳
jz @Server_end
mov eax,[ebp+00Ch] ;将监听端口转换为网络顺序
xchg ah,al
mov [ebp-012h],ax
mov word ptr [ebp-014h],AF_INET ;使用IP地址家族
push 010h
lea eax,[ebp-014h]
push eax
push dword ptr [ebp-004h]
call bind; 绑定端口 bind(s,&serverhost.sin_family,10)实际上第二个参数中必须包含sin_family即可,故写为这种样子
inc eax ;是否失败,是,跳
jz @Server_end
push SOMAXCONN
push dword ptr [ebp-004h]
call listen; 监听端口listen(s,SOMAXCONN) 队列长度设为最大
jnz @Server_end
@Server_loop:
lea eax,[ebp-018h] ;进入事件循环
push eax ;压入事件句柄
push [ebp-004h] ;套接字
call @EventSelect ;选择要处理的事件
test eax,eax ;失败?跳
jz @Server_end
push [ebp-018h] ;再次压入句柄和套接字
push [ebp-004h]
call @WaitForEvents ;等待事件
test eax,eax ;测试下 WSANETWORKEVENTS是否已经接收到数据
jnz @Server_proc_events
push 019h ;没有则休息下。避免占用资源,偶则跳,处理事件去鸟~~~~~
call Sleep
jmp @Server_loop ;循环等待
@Server_proc_events:
and eax,FD_ACCEPT ;是否是FD_ACCEPT事件
jz @Server_loop ;不是,继续进入事件循环,等待下个事件
xor eax,eax ;oh ,yeah!!!!!!!终于等到了
push eax
push eax
push eax
lea eax,[ebp-030h] ;客户端IP地址
push eax
push dword ptr [ebp-004h] ;偶们创建的套接字
call WSAAccept; ;接收事件
mov [ebp-020h],eax ;把为客户端创建的套接字保存到缓冲区
inc eax ;创建失败?继续进入事件循环
jz @Server_loop
push 01Ch
push LMEM_FIXED
call LocalAlloc; 分配一个固定的内存
test eax,eax ;分配失败?关闭套节字
jz @Server_close_newsock
mov ecx,[ebp-020h] ;客户端套接字存入内存中
mov [eax],ecx
lea esi,[ebp-030h] ;取客户端地址
lea edi,[eax+004h] ;貌似要修改新套接字中的地址了,其实偶这里比较糊涂,只是从代码上推断
movsd ;
movsd ;---------开始修改
movsd ;
movsd ;
lea esi,[ebp+008h] ;修改FinalAddr,晕这是什么?????????????????、
movsd
movsd
lea ecx,[ebp-01Ch] ;取线程ID指针,看来要对线程动手了:)
push ecx ;压
xor ecx,ecx
push ecx
push eax ;压入分配的内存
push offset @NewClientThread ;压入线程参数地址
push ecx
push ecx
call CreateThread; bingo,创建线程
jmp @Server_loop ;该事件处理完毕,继续进入事件循环,等待下一个事件
@Server_close_newsock:
push dword ptr [ebp-020h]
call CloseSocket
jmp @Server_loop
@Server_end:
push dword ptr [ebp-018h]
call CloseHandle
push dword ptr [ebp-004h]
call CloseSocket
jmp @end
@EventSelect:
call WSACreateEvent;建立一个时间 WSACreateEvent(VOID)
test eax,eax ;测试是否建立成功
jz @EventSelect_fail ;失败则退出
mov ecx,[esp+008h] ;
mov [ecx],eax ;保存事件指针
push FD_ALL_EVENTS
push eax
push [esp+00Ch]
call WSAEventSelect;筛选事件 WSAEventSelect(S,Thanlde,FD_ALL_EVENT)
inc eax
jnz @EventSelect_end ;测试是否失败,失败就跳
@EventSelect_fail:
xor eax,eax
@EventSelect_end:
ret 008h ;平衡堆栈
@WaitForEvents:
push ebp
mov ebp,esp
sub esp,02Ch
push 000h ;函数返回后,完成的例程不被执行
push WAITFOREVENTSTIMEOUT
push 000h ;一接到信号就返回
lea eax,[ebp+00Ch]
push eax ;设置事件句柄数组
push 1 ;指定一个数组
call WSAWaitForMultipleEvents; ;;;;;;;;;;;;;;;;这个函数没用过,所以不能说清楚,看MSDN把自己
inc eax
jz @WaitForEvents_end ;失败就跳
sub eax,WSA_WAIT_TIMEOUT+1 ;测试下是否是超时返回(不清楚)
jz @WaitForEvents_end
lea eax,[ebp-02Ch] ;为WSANETWORKEVENTS分配个缓冲区,不知道能不能溢出,挖嘎嘎~~~~
push eax ;一个缓冲区
push dword ptr [ebp+00Ch] ;世界安句柄
push dword ptr [ebp+008h] ;套接字
call WSAEnumNetworkEvents
inc eax
jz @WaitForEvents_end ;出错?跳
mov eax,[ebp-02Ch] ;WSANETWORKEVENTS的指针装入eax
@WaitForEvents_end:
leave ;平衡堆栈
jmp @EventSelect_end ;******************************终于注释完了最乱的一段了************************
搞懂了,比如转发的过程偶就不是很明白,如果那个大牛了解这个程序端口转发的过程,请指导偶一
下下,如果那个朋友有不懂得地方或者发现偶注释错误的地方.
//
;====================[ The Smallest TCP Port Redirector ]=======================
;
;
;
;Copyright (c) 2000,forever ExEwORx
;birthday: 8.9.2002
;version: 1.0
;
;compiled with MASM 6.14 with ALIGN:4
;total size: 2512b
;write no output, silently terminates when error
;it is multithreaded and stable on Windows NT 4.0, Windows 2000 and Windows XP
;
;usage: sredir.exe listen_on_port redir_to_ip redir_to_port
; redir_to_ip must be IP address in A.B.C.D format
; no DNS implemented
;
;example: sredir.exe 100 212.80.76.18 80
;
;no other comments, cuz code is comment :)
;
.386p
.model flat, stdcall
include kernel32.inc
include winsock2.inc
LocalAlloc PROTO :DWORD,:DWORD
LocalFree PROTO :DWORD
ExitThread PROTO :DWORD
ExitProcess PROTO :DWORD
GetCommandLineA PROTO
Sleep PROTO :DWORD
CloseHandle PROTO :DWORD
CreateThread PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
TerminateThread PROTO :DWORD,:DWORD
WaitForMultipleObjects PROTO :DWORD,:DWORD,:DWORD,:DWORD
bind PROTO :DWORD,:DWORD,:DWORD
listen PROTO :DWORD,:DWORD
recv PROTO :DWORD,:DWORD,:DWORD,:DWORD
send PROTO :DWORD,:DWORD,:DWORD,:DWORD
closesocket PROTO :DWORD
inet_addr PROTO :DWORD
WSAIoctl PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,
:DWORD,:DWORD
WSAStartup PROTO :DWORD,:DWORD
WSACleanup PROTO
WSACreateEvent PROTO
WSASocketA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
WSAConnect PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
WSAEnumNetworkEvents PROTO :DWORD,:DWORD,:DWORD
WSAAccept PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
WSAEventSelect PROTO :DWORD,:DWORD,:DWORD
WSAWaitForMultipleEvents PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
SOMAXCONN equ 07FFFFFFFh
IPPROTO_TCP equ 006h
SOCK_STREAM equ 001h
AF_INET equ 002h
FIONREAD equ 04004667Fh
WAITFOREVENTSTIMEOUT equ 0FAh
WSA_WAIT_TIMEOUT equ 00102h
SOCK_ADDR_SIZE equ 010h
FD_READ equ 001h
FD_ACCEPT equ 008h
FD_CLOSE equ 020h
FD_ALL_EVENTS equ 003FFh
LMEM_FIXED equ 000h
.data
.code
start:
mov ebp,esp
sub esp,001ECh; 保存一段堆栈空间
lea eax,[ebp-01ECh];指向WSADATA的指针
push eax
push 0202h
call WSAStartup; 启动socket
test eax, eax ;测试
jnz @end
xor eax,eax ;得到命令行参数
call GetCommandLineA
mov esi,eax ;保存指针到esi
xor eax,eax
lodsb ;将命令行参数的第一个字节装入eax
cmp al,022h ;是否含有该死的"
setz al
mov [ebp-004h],eax ;将第一个字符保存到堆栈中
@Next_char:
lodsb ;装入下个字节
test eax,eax ;是否已经到达末尾
jz @end ;是。跳
sub al,020h ;是否为空格?
jz @Space_found ;是,跳 处理空格
dec eax ;是否是一个.
dec eax
setnz al ;是就屏蔽掉
and [ebp-004h],eax ;
jmp @Next_char
@Space_found:
cmp byte ptr [ebp-004h],000h ; 测试是否是尾部
jnz @Next_char ;不是,找到一个参数
call @Find_arg
mov edi,esi ;将edi设置为字符串指针
push 020h ;为eax赋值
pop eax
call @arg_len ;调用函数,得到参数长度
mov ecx,eax ;保存字符串长度
lea edi,[ebp-0100h]
push edi
rep movsb ;将参数移动到堆栈
mov [edi],cl ;为字符串加个null
call @IntToStr
mov [ebp-004h],eax ;把eax存入堆栈
inc eax
jz @end ;如果是0则字符串转化时出现错误,跳
inc edi ;修改edi指针,查找下一个参数
push edi
call @Find_arg
xchg esi,edi
push 020h
pop eax
call @arg_len ;---------------+
mov ecx,eax ; +
xchg esi,edi ; +
rep movsb ; +
mov [edi],cl ; +
call inet_addr; ; +
mov [ebp-008h],eax ; +
inc eax ; +
jz @end ; +
call @Find_arg ; +
inc edi ; +
push edi ; +
xchg esi,edi ; +
xor eax,eax ; +
call @arg_len ; +
mov ecx,eax ; +-------下面的查找过程,和上面基本一直,不在废话鸟~
xchg esi,edi ; +
rep movsb ; +
mov [edi],cl ; +
call @IntToStr ; +
mov [ebp-00Ch],eax ; +
inc eax ; +
jz @end ; +
mov eax,[ebp-00Ch] ; +
shl eax,010h ; +
mov ax,[ebp-004h] ; +
push eax ; +
push dword ptr [ebp-008h]
call @Server ; +
@end:
call WSACleanup; ; +
push 000h ; +
call ExitProcess; ;---------------+
@IntToStr:
push esi ;保存参数指针
xor eax,eax ;清空eax,edx
xor edx,edx
mov esi,[esp+008h] ;将edi的值存入esi。如果问为什么,自己去算下
@IntToStr_next_char:
lodsb ;像eax中装入一个字节
test eax,eax ;是否到达null
jz @IntToStr_end ;日,到了,跑路
imul edx,edx,00Ah ;edx=edx*10
cmp al,030h ;al是否为0
jb @IntToStr_error ;汗比0还小,跳
cmp al,039h ;是否为9
ja @IntToStr_error ;汗,比九大跳
sub eax,030h
add edx,eax ;转换完成
jmp @IntToStr_next_char ;处理下一个字符
@IntToStr_error:
xor edx,edx ;清空edx
dec edx
@IntToStr_end:
mov eax,edx
pop esi
ret
@arg_len: ;@arg -> edi, char -> eax
push edi ;指向参数的字符串
xor ecx,ecx
dec ecx ;比较是否已经到达空格,没有则重复
repnz scasb ;
not ecx ;这里说明一下,ecx为什么要设为-1,因为偶们的指针现在指向的是参数的尾部
dec ecx ;偶们要采取逆序的方法查找前一个空格,故设为负值在求反减1就能得到长度
mov eax,ecx ;如果不这样做,而采用调整指针,会浪费很多代码,不利于优化,这段代码值得大家学习的说
pop edi
ret
@Find_arg: ;str -> esi -> esi
lodsb
cmp al,020h
jz @Find_arg
dec esi
ret
@Server:
push ebp
mov ebp,esp
sub esp,034h
; -030 - NewClient.Host.sin_family:Word
; -02E - NewClient.Host.sin_port:Word
; -02C - NewClient.Host.sin_addr:TInAddr
; -028..-024 - NewClient.Host.sin_zero:array[0..7] of Char
; -020 - NewClient.Socket:TSocket
; -01C - TID:Cardinal;
; -018 - ServerEventHandle:THandle
; -014 - ServerHost.sin_family:Word
; -012 - ServerHost.sin_port:Word
; -010 - ServerHost.sin_addr:TInAddr
; -00C..-008 - ServerHost.sin_zero:array[0..7] of Char
; -004 - ServerSocket:TSocket
; +008 - FinalAddr:TInAddr
; +00C - ListenPort:Word
; +010 - FinalPort:Word
push esi
push edi
push ebx
xor eax,eax
mov [ebp-010h],eax ;WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,0,0,0)
push eax ;建立一个套接字
push eax
push eax
push IPPROTO_TCP
push SOCK_STREAM
push AF_INET
call WSASocketA
mov [ebp-004h],eax ;讲套接字保存到堆栈
inc eax ;是否建立失败,是,跳
jz @Server_end
mov eax,[ebp+00Ch] ;将监听端口转换为网络顺序
xchg ah,al
mov [ebp-012h],ax
mov word ptr [ebp-014h],AF_INET ;使用IP地址家族
push 010h
lea eax,[ebp-014h]
push eax
push dword ptr [ebp-004h]
call bind; 绑定端口 bind(s,&serverhost.sin_family,10)实际上第二个参数中必须包含sin_family即可,故写为这种样子
inc eax ;是否失败,是,跳
jz @Server_end
push SOMAXCONN
push dword ptr [ebp-004h]
call listen; 监听端口listen(s,SOMAXCONN) 队列长度设为最大
jnz @Server_end
@Server_loop:
lea eax,[ebp-018h] ;进入事件循环
push eax ;压入事件句柄
push [ebp-004h] ;套接字
call @EventSelect ;选择要处理的事件
test eax,eax ;失败?跳
jz @Server_end
push [ebp-018h] ;再次压入句柄和套接字
push [ebp-004h]
call @WaitForEvents ;等待事件
test eax,eax ;测试下 WSANETWORKEVENTS是否已经接收到数据
jnz @Server_proc_events
push 019h ;没有则休息下。避免占用资源,偶则跳,处理事件去鸟~~~~~
call Sleep
jmp @Server_loop ;循环等待
@Server_proc_events:
and eax,FD_ACCEPT ;是否是FD_ACCEPT事件
jz @Server_loop ;不是,继续进入事件循环,等待下个事件
xor eax,eax ;oh ,yeah!!!!!!!终于等到了
push eax
push eax
push eax
lea eax,[ebp-030h] ;客户端IP地址
push eax
push dword ptr [ebp-004h] ;偶们创建的套接字
call WSAAccept; ;接收事件
mov [ebp-020h],eax ;把为客户端创建的套接字保存到缓冲区
inc eax ;创建失败?继续进入事件循环
jz @Server_loop
push 01Ch
push LMEM_FIXED
call LocalAlloc; 分配一个固定的内存
test eax,eax ;分配失败?关闭套节字
jz @Server_close_newsock
mov ecx,[ebp-020h] ;客户端套接字存入内存中
mov [eax],ecx
lea esi,[ebp-030h] ;取客户端地址
lea edi,[eax+004h] ;貌似要修改新套接字中的地址了,其实偶这里比较糊涂,只是从代码上推断
movsd ;
movsd ;---------开始修改
movsd ;
movsd ;
lea esi,[ebp+008h] ;修改FinalAddr,晕这是什么?????????????????、
movsd
movsd
lea ecx,[ebp-01Ch] ;取线程ID指针,看来要对线程动手了:)
push ecx ;压
xor ecx,ecx
push ecx
push eax ;压入分配的内存
push offset @NewClientThread ;压入线程参数地址
push ecx
push ecx
call CreateThread; bingo,创建线程
jmp @Server_loop ;该事件处理完毕,继续进入事件循环,等待下一个事件
@Server_close_newsock:
push dword ptr [ebp-020h]
call CloseSocket
jmp @Server_loop
@Server_end:
push dword ptr [ebp-018h]
call CloseHandle
push dword ptr [ebp-004h]
call CloseSocket
jmp @end
@EventSelect:
call WSACreateEvent;建立一个时间 WSACreateEvent(VOID)
test eax,eax ;测试是否建立成功
jz @EventSelect_fail ;失败则退出
mov ecx,[esp+008h] ;
mov [ecx],eax ;保存事件指针
push FD_ALL_EVENTS
push eax
push [esp+00Ch]
call WSAEventSelect;筛选事件 WSAEventSelect(S,Thanlde,FD_ALL_EVENT)
inc eax
jnz @EventSelect_end ;测试是否失败,失败就跳
@EventSelect_fail:
xor eax,eax
@EventSelect_end:
ret 008h ;平衡堆栈
@WaitForEvents:
push ebp
mov ebp,esp
sub esp,02Ch
push 000h ;函数返回后,完成的例程不被执行
push WAITFOREVENTSTIMEOUT
push 000h ;一接到信号就返回
lea eax,[ebp+00Ch]
push eax ;设置事件句柄数组
push 1 ;指定一个数组
call WSAWaitForMultipleEvents; ;;;;;;;;;;;;;;;;这个函数没用过,所以不能说清楚,看MSDN把自己
inc eax
jz @WaitForEvents_end ;失败就跳
sub eax,WSA_WAIT_TIMEOUT+1 ;测试下是否是超时返回(不清楚)
jz @WaitForEvents_end
lea eax,[ebp-02Ch] ;为WSANETWORKEVENTS分配个缓冲区,不知道能不能溢出,挖嘎嘎~~~~
push eax ;一个缓冲区
push dword ptr [ebp+00Ch] ;世界安句柄
push dword ptr [ebp+008h] ;套接字
call WSAEnumNetworkEvents
inc eax
jz @WaitForEvents_end ;出错?跳
mov eax,[ebp-02Ch] ;WSANETWORKEVENTS的指针装入eax
@WaitForEvents_end:
leave ;平衡堆栈
jmp @EventSelect_end ;******************************终于注释完了最乱的一段了************************