正在加载...
 
    i'm a pig,stupid pig(注释的转发程序,感谢XX总,热情加上题目)  

    ////////////////////////////////////////////////////////////////////////////////////

    注释了holy_father写的这个端口转发的程序,虽然注释了大部分代码,本人还是不敢说把代码完全

    搞懂了,比如转发的过程偶就不是很明白,如果那个大牛了解这个程序端口转发的过程,请指导偶一

    下下,如果那个朋友有不懂得地方或者发现偶注释错误的地方,欢迎email偶

    goblin.azrael@yahoo.com.cn

    //////////////////////////////////////////////////////////////////////////////////


    ;====================[ The Smallest TCP Port Redirector ]=======================
    ;
    ;
    ;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

    浏览数(422) | 评论数(0) | 2006-11-20

      Powered by Haiwit