;
;
;programmed by Holy_Father <holy_father@phreaker.net>
;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 ;******************************终于注释完了最乱的一段了************************
@NewClientThread:
mov ebp,esp
sub esp,070h
; -070 - RedirThreadHandle:THandle
; -06C - ClientThreadHandle:THandle
; -068 - Redir.ThreadArgs.MainItem:PTcpItem
; -064 - Redir.ThreadArgs.OtherItem:PTcpItem
; -060 - Redir.ThreadArgs.ThreadType:Cardinal
; -05C - Redir.ThreadArgs.Events:Longint
; -058 - Redir.ThreadArgs.EventHandle:THandle
; -054 - Redir.ThreadArgs.Active:Boolean
; -050 - Redir.ThreadArgs.Host.sin_family:Word
; -04E - Redir.ThreadArgs.Host.sin_port:Word
; -04C - Redir.ThreadArgs.Host.sin_addr:TInAddr
; -048..-044 - Redir.ThreadArgs.Host.sin_zero:array[0..7]
; -040 - Redir.ThreadArgs.Socket
; -038 - Redir.ThreadID:Cardinal
; -034 - Client.ThreadArgs.MainItem:PTcpItem
; -030 - Client.ThreadArgs.OtherItem:PTcpItem
; -02C - Client.ThreadArgs.ThreadType:Cardinal
; -028 - Client.ThreadArgs.Events:Longint
; -024 - Client.ThreadArgs.EventHandle:THandle
; -020 - Client.ThreadArgs.Active:Boolean
; -01C - Client.ThreadArgs.Host.sin_family:Word
; -01A - Client.ThreadArgs.Host.sin_port:Word
; -018 - Client.ThreadArgs.Host.sin_addr:TInAddr
; -014..-010 - Client.ThreadArgs.Host.sin_zero:array[0..7]
; -00C - Client.ThreadArgs.Socket
; -008 - Client.ThreadArgs.Connected
; -004 - Client.ThreadID:Cardinal
; +004 - AArgs:Pointer
; +000 AArgs.NewSocket
; +004 AArgs.NewHost.sin_family:Word
; +006 AArgs.NewHost.sin_port:Word
; +008 AArgs.NewHost.sin_addr:TInAddr
; +00C..+010 AArgs.NewHost.sin_zero:array[0..7] of Char
; +014 AArgs.FinalAddr:TInAddr
; +018 AArgs.ListenPort:Word
; +01A AArgs.FinalPort:Word
xor eax,eax
lea edi,[ebp-070h]
push 01Ch
pop ecx
rep stosd ;初始化堆栈0x70-0x54的部分
push eax
push eax
push eax
push IPPROTO_TCP
push SOCK_STREAM
push AF_INET
call WSASocketA; 建立一个client套接字 WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,0,0,0)
mov [ebp-00Ch],eax
inc eax
jz @NewClientThread_close_newsock;创建错误,清理
push 001h
pop eax ;为eax赋值
mov [ebp-020h],eax;将BOOLEN值都设为真
mov [ebp-054h],eax
mov [ebp-060h],eax
mov edx,[ebp+004h]; 把新套接字的指针装入edx
movzx ax,byte ptr [edx+01Ah]
xchg ah,al ;转为网络地址
mov [ebp-01Ah],ax ;送回到缓冲区中
mov word ptr [ebp-01Ch],AF_INET ;使用IP地址家族
mov eax,[edx+014h] ;把新套接字的地址入eax
mov [ebp-018h],eax ;存入缓冲区
mov eax,[edx]
mov [ebp-040h],eax ;新套接字存入缓冲区
lea esi,[edx+004h] ;新套接字地址移动到缓冲区
lea edi,[ebp-050h]
movsd ;--------------------------+
movsd ; +-----------开始移动
movsd ; +
movsd ;--------------------------+
lea eax,[ebp-058h] ;取事件句柄地址
push eax ;压入
push dword ptr [ebp-040h] ;原来的那个套接字
call @EventSelect ;暴汗!!!!!!怎么又进入事件体了
test eax,eax
jz @NewClientThread_close_clientsock
lea eax,[ebp-068h] ;取PTcpItem看来要替换TCP里的西西了,继续看他干什么,不过ptcpitem里面不是0吗??
mov [ebp-030h],eax ;把地址装入了客户端的otheritem.PTcpItem
mov [ebp-068h],eax ;地址又回送了,看来构造了个指向指针的指针
lea eax,[ebp-034h] ;取客户端mainitem.ptcpitem地址
mov [ebp-034h],eax ;再次构造了一个指针指针
mov [ebp-064h],eax ;送入otheritem.ptcpitem中; 看来运行后,地址被替换了other->main main->other
;他要干什么???????
lea eax,[ebp-004h] ;客户端线程ID地址
push eax
push 000h
lea eax,[ebp-034h] ;压入MainItem:PTcpItem地址
push eax
push offset @ThreadProc ;压入线程处理函数地址
push 000h
push 000h
call CreateThread; 晕迷~~~又建了个线程
test eax,eax
jz @NewClientThread_close_clientsock
mov [ebp-06Ch],eax ;保存客户端线程句柄
push 019h
call Sleep ;终于休息了,防止占用过多的资源
lea eax,[ebp-038h]
push eax
push 000h
lea eax,[ebp-068h]
push eax
push offset @ThreadProc
push 000h
push 000h
call CreateThread; 再次创建线程,是不是他打算为接受和转发个创建一个线程
test eax,eax
jz @NewClientThread_term_clientthread
mov [ebp-070h],eax ;句柄保存
push -001h
push 000h
lea eax,[ebp-070h]
push eax
push 002h
call WaitForMultipleObjects; 有是这个偶不熟悉的API,不多说了,避免误人子弟
xor eax,eax
mov [ebp-054h],eax ;如果句柄创建成功就保存参数
mov [ebp-020h],eax
mov [ebp-008h],eax
push 032h ;休息
call Sleep
push dword ptr [ebp-040h] ;清理套接字,主套接字和新套接字
call CloseSocket
push dword ptr [ebp-00Ch]
call CloseSocket
push 0FAh ;防止线程退出过快,呼呼一段时间,给系统清理的时间
call Sleep
push 000h ; 终止线程,个人认为这是一种比较不好的退出线程的方法,建议看下win32多线程编程
push dword ptr [ebp-070h]
call TerminateThread;------------------------------------------+
@NewClientThread_term_clientthread:; +
push 000h ; +
push dword ptr [ebp-06Ch]: ; +
call TerminateThread; +
@NewClientThread_close_clientsock:; +
push dword ptr [ebp-00Ch]; +----------线程和套接字清理的西西,没什么好说的
call CloseSocket; +
; +
push dword ptr [ebp-058h]; +
call CloseHandle; +
push dword ptr [ebp-024h]; +
call CloseHandle;----------------------------------------------+
@NewClientThread_close_newsock:
mov eax,[ebp+004h]
push dword ptr [eax]
call CloseSocket
push dword ptr [ebp+004h]
call LocalFree;释放内存
push 000h
call ExitThread;清理线程
@ThreadProc:
mov ebp,esp
sub esp,00Ch
; -00C - LBuffer:Pointer
; -008 - LBytes:Cardinal
; -004 - LSocket:TSocket
; +004 - AArgs:Pointer
; +000 AArgs.ThreadArgs.MainItem:PTcpItem
; +004 AArgs.ThreadArgs.OtherItem:PTcpItem
; +008 AArgs.ThreadArgs.ThreadType:Cardinal
; +00C AArgs.ThreadArgs.Events:Longint
; +010 AArgs.ThreadArgs.EventHandle:THandle
; +014 AArgs.ThreadArgs.Active:Boolean
; +018 AArgs.ThreadArgs.Host.sin_family:Word
; +01A AArgs.ThreadArgs.Host.sin_port:Word
; +01C AArgs.ThreadArgs.Host.sin_addr:TInAddr
; +020..+024 AArgs.ThreadArgs.Host.sin_zero:array[0..7]
; +028 AArgs.ThreadArgs.Socket
; +02C AArgs.ThreadArgs.Connected - client only
mov esi,[ebp+004h]
mov eax,[esi+008h]
test eax,eax
jnz @ThreadProc_redir ;这两个值是否相等,不等?修正
mov eax,[esi+02Ch] ;测试客户端是否被连接
test eax,eax
jnz @ThreadProc_client_connected
push eax
push eax
push eax
push eax
push SOCK_ADDR_SIZE
lea eax,[esi+018h]
push eax
push dword ptr [esi+028h]
call WSAConnect;如果为0,调用WSAConnect进行连接
inc eax
jz @ThreadProc_error;连接错误?跳
lea eax,[esi+010h]
push eax
push dword ptr [esi+028h]
call @EventSelect;继续使用EventSelect筛选事件
mov [esi+02Ch],eax
test eax,eax
jz @ThreadProc_error
jmp @ThreadProc_client_connected;找到事件,跳
@ThreadProc_redir:
mov edi,[esi+004h]
@ThreadProc_redir_waitforcon:
push 019h
call Sleep
mov eax,[edi+02Ch]
test eax,eax
jz @ThreadProc_redir_waitforcon
@ThreadProc_client_connected:
mov eax,[esi+014h];测试下是否处于活跃状态
test eax,eax
jz @ThreadProc_closesock;程序已经关闭,清理套接字
mov eax,[esi+004h];
mov eax,[eax+014h]
test eax,eax
jz @ThreadProc_closesock
push dword ptr [esi+010h]
push dword ptr [esi+028h]
call @WaitForEvents;已经连接,等待事件发生
test eax,eax ;测试是否有被筛选事件发生
jz @ThreadProc_client_connected;没有,跳,继续等待连接
mov [esi+00Ch],eax ;将WSANETWORKEVENTS的指针存入参数AArgs.ThreadArgs.Events:Longint
and eax,FD_READ ;测试是否含有FD_READ
jnz @ThreadProc_read ;含有,跳到该事件的例程中
@ThreadProc_af_read:
mov eax,[esi+00Ch]
and eax,FD_CLOSE ;是否已经关闭了?是,跳,继续等待(汗,变的不会这么块把)
jnz @ThreadProc_closesock
jmp @ThreadProc_client_connected
@ThreadProc_read:
push dword ptr [esi+028h] ;压入socket
call @BytesToRecv ;接收数据,得到接收的数据size
test eax,eax ;什么都没收到?
jz @ThreadProc_af_read ;跳,继续读
mov edi,eax ;接收的数据size保存到edi
push eax ;压入
push LMEM_FIXED ;为数据分配内存
call LocalAlloc
test eax,eax ;失败?
jz @ThreadProc_closesock ;清理套接字,跑路~
mov [ebp-00Ch],eax ;保存指针
push 000h
push edi
push eax
push dword ptr [esi+028h]
call recv; 用继续recv()接收剩下的
mov [ebp-008h],eax ;保存字节数
inc eax ;接收失败?跳
jz @ThreadProc_read_free
@ThreadProc_read_loop:
push 000h
push dword ptr [ebp-008h] ;压入接收的字节数
push dword ptr [ebp-00Ch] ;缓冲区地址,由LocalAlloc分配
mov eax,[esi+004h] ;OtherItem:PTcpItem保存到eax
mov eax,[eax+028h] ;压入套接字,其实偶也不知道如何得到的套接字
push eax
call send; 发送数据
inc eax
jz @ThreadProc_read_free ;发送失败?跳
dec eax ;恢复返回值
sub [ebp-008h],eax ;得到没有被发送的字节数
jnz @ThreadProc_read_loop ;是否该值为0,即是否全部发送,否?跳
@ThreadProc_read_free:
push dword ptr [ebp-00Ch] ;处理读数据失败的代码
call LocalFree; 清理下内存,然后继续跳
jmp @ThreadProc_read
@ThreadProc_closesock:
push dword ptr [esi+028h] ;压入套接字,关闭套接字,清理内存
call CloseSocket
@ThreadProc_error: ;退出线程
push 000h
call ExitThread
@BytesToRecv:; 这部分 没什么难度。自己看把
xor eax,eax
push eax
push eax
push eax
push eax
lea ecx,[esp+00Ch]
push ecx
push 004h
sub ecx,004h
push ecx
push eax
push eax
push FIONREAD
push [esp+02Ch]
call WSAIoctl
inc eax
jz @BytesToRecv_end
mov eax,[esp]
@BytesToRecv_end:
pop ecx
pop ecx
ret 004h
end start