xfocus logo xfocus title
首页 焦点原创 安全文摘 安全工具 安全漏洞 焦点项目 焦点论坛 关于我们
添加文章 Xcon English Version

Radmin服务端保持连接不断问题分析与解决


创建时间:2006-07-15
文章属性:原创
文章提交:grassgrass (kityest_at_163.com)

Radmin服务端保持连接不断问题分析与解决
作者:        grassgrass
Email:     kityest@163.com
1、问题描述
    Radmin是一个绝佳的远程控制软件,用来做跳板的后门再好不过了,不过每次连过跳板后,察看跳板连线,可以仍然看见我们和跳板上Radmin的连接,只不过显示为TIME_WAIT,且一直这样。
Proto  Local Address          Foreign Address        State
TCP    0.0.0.0:135            0.0.0.0:0              LISTENING
TCP    0.0.0.0:445            0.0.0.0:0              LISTENING
TCP    0.0.0.0:1030           0.0.0.0:0              LISTENING
TCP    127.0.0.1:1031         0.0.0.0:0              LISTENING
TCP    192.168.11.1:139       0.0.0.0:0              LISTENING
TCP    192.168.72.1:139       0.0.0.0:0              LISTENING
TCP    192.168.168.220:1030   192.168.168.221:1034   TIME_WAIT
UDP    0.0.0.0:445            *:*
UDP    0.0.0.0:1026           *:*
UDP    127.0.0.1:123          *:*
UDP    127.0.0.1:1900         *:*
UDP    192.168.11.1:123       *:*
UDP    192.168.11.1:137       *:*
UDP    192.168.11.1:138       *:*
UDP    192.168.11.1:1900      *:*
UDP    192.168.72.1:123       *:*
UDP    192.168.72.1:137       *:*
UDP    192.168.72.1:138       *:*
UDP    192.168.72.1:1900      *:*
UDP    192.168.168.220:123    *:*
UDP    192.168.168.220:1900   *:*
2、问题分析
    初步猜测应该是setsocketopt设置超时有问题,可能是设置了无限超时?
    调试Radmin服务端,下断点在setsocketopt,结果如下:
第一次断下来
71A42E30 >  8BFF            MOV EDI,EDI
71A42E32    55              PUSH EBP
71A42E33    8BEC            MOV EBP,ESP
71A42E35    837D 0C 00      CMP DWORD PTR SS:[EBP+C],0
71A42E39    0F84 25010000   JE WSOCK32.71A42F64
71A42E3F    8B45 10         MOV EAX,DWORD PTR SS:[EBP+10]
71A42E42    837D 0C 06      CMP DWORD PTR SS:[EBP+C],6
71A42E46    8B4D 14         MOV ECX,DWORD PTR SS:[EBP+14]
71A42E49    74 75           JE SHORT WSOCK32.71A42EC0
71A42E4B    FF75 18         PUSH DWORD PTR SS:[EBP+18]
71A42E4E    51              PUSH ECX
71A42E4F    50              PUSH EAX
71A42E50    FF75 0C         PUSH DWORD PTR SS:[EBP+C]
71A42E53    FF75 08         PUSH DWORD PTR SS:[EBP+8]
71A42E56    E8 09000000     CALL <JMP.&WS2_32.#21__setsockopt@20>
71A42E5B    5D              POP EBP
71A42E5C    C2 1400         RETN 14
71A42E5F    90              NOP
71A42E60    90              NOP
71A42E61    90              NOP
71A42E62    90              NOP
71A42E63    90              NOP
71A42E64  - FF25 0010A471   JMP DWORD PTR DS:[<&WS2_32.#21__setsocko>; WS2_32.setsockopt
察看堆栈:
0012F808   0096D367  /CALL 到 setsockopt 来自 0096D362
0012F80C   0000007C  |Socket = 7C
0012F810   0000FFFF  |Level = SOL_SOCKET
0012F814   00000080  |Option = SO_LINGER
0012F818   0012F844  |Data = 0012F844
0012F81C   00000004  \DataSize = 4
0012F820   0000FFFF
0012F824   0012F84C
0012F828  /0012F850
0012F82C  |009652F2  返回到 009652F2 来自 0096D340
0012F830  |00000080
0012F834  |0012F844
0012F838  |00000004
0012F83C  |0012F870
0012F840  |001D0406
0012F844  |00010001
0012F848  |0012F870
0012F84C  |0000007C
0012F850  ]0012F884
可以看到,它设置了SO_LINGER选项,值为0x00010001
第二次断点:
71A42E30 >  8BFF            MOV EDI,EDI
71A42E32    55              PUSH EBP
71A42E33    8BEC            MOV EBP,ESP
71A42E35    837D 0C 00      CMP DWORD PTR SS:[EBP+C],0
71A42E39    0F84 25010000   JE WSOCK32.71A42F64
71A42E3F    8B45 10         MOV EAX,DWORD PTR SS:[EBP+10]
71A42E42    837D 0C 06      CMP DWORD PTR SS:[EBP+C],6
71A42E46    8B4D 14         MOV ECX,DWORD PTR SS:[EBP+14]
71A42E49    74 75           JE SHORT WSOCK32.71A42EC0
71A42E4B    FF75 18         PUSH DWORD PTR SS:[EBP+18]
71A42E4E    51              PUSH ECX
71A42E4F    50              PUSH EAX
71A42E50    FF75 0C         PUSH DWORD PTR SS:[EBP+C]
71A42E53    FF75 08         PUSH DWORD PTR SS:[EBP+8]
71A42E56    E8 09000000     CALL <JMP.&WS2_32.#21__setsockopt@20>
71A42E5B    5D              POP EBP
71A42E5C    C2 1400         RETN 14
堆栈:
0012F80C   0096D367  /CALL 到 setsockopt 来自 0096D362
0012F810   00000078  |Socket = 78
0012F814   0000FFFF  |Level = SOL_SOCKET
0012F818   00000080  |Option = SO_LINGER
0012F81C   0012F84C  |Data = 0012F84C
0012F820   00000004  \DataSize = 4
0012F824   0000FFFF
0012F828   0012F848
0012F82C  /0012F850
0012F830  |00965419  返回到 00965419 来自 0096D340
0012F834  |00000080
0012F838  |0012F84C
0012F83C  |00000004
0012F840  |0012F864
0012F844  |0012F870
0012F848  |00000078
0012F84C  |00010001
0012F850  ]0012F884
可见第一次与第二次相同
F9,没有下个断点,可见只有这两处,上网搜索SO_LINGER选项,其描述如下:

     /* 当连接中断时,需要延迟关闭(linger)以保证所有数据都
   * 被传输,所以需要打开SO_LINGER这个选项        //注:大致意思就是说SO_LINGER选项用来设置当调用closesocket时是否马上关闭socket
   * linger的结构在/usr/include/linux/socket.h中定义://注:这个结构就是SetSocketOpt中的Data的数据结构
   *  struct linger
   *  {
   *   int l_onoff;  /* Linger active */         //低字节,0和非0,用来表示是否延时关闭socket
   *   int l_linger; /* How long to linger */     //高字节,延时的时间数,单位为秒
   *  };
   *  如果l_onoff为0,则延迟关闭特性就被取消。如果非零,则允许套接口延迟关闭。
   *  l_linger字段则指明延迟关闭的时间
   */
更具体的描述如下:
若设置了SO_LINGER(亦即linger结构中的l_onoff域设为非零,参见2.4,4.1.7和4.1.21各节),并设置了零超时间隔,则closesocket()不被阻塞立即执行,不论是否有排队数据未发送或未被确认。这种关闭方式称为“强制”或“失效”关闭,因为套接口的虚电路立即被复位,且丢失了未发送的数据。在远端的recv()调用将以WSAECONNRESET出错。

若设置了SO_LINGER并确定了非零的超时间隔,则closesocket()调用阻塞进程,直到所剩数据发送完毕或超时。这种关闭称为“优雅的”关闭。请注意如果套接口置为非阻塞且SO_LINGER设为非零超时,则closesocket()调用将以WSAEWOULDBLOCK错误返回。

若在一个流类套接口上设置了SO_DONTLINGER(也就是说将linger结构的l_onoff域设为零;参见2.4,4.1.7,4.1.21节),则closesocket()调用立即返回。但是,如果可能,排队的数据将在套接口关闭前发送。请注意,在这种情况下WINDOWS套接口实现将在一段不确定的时间内保留套接口以及其他资源,这对于想用所以套接口的应用程序来说有一定影响。

这是网上的解释
主要是影响close socket时的动作
知道了问题的原因,我们就动手修改一下试试
0012F80C   0096D367  /CALL 到 setsockopt 来自 0096D362
0012F810   00000078  |Socket = 78
0012F814   0000FFFF  |Level = SOL_SOCKET
0012F818   00000080  |Option = SO_LINGER
0012F81C   0012F84C  |Data = 0012F84C
0012F820   00000004  \DataSize = 4
0012F824   0000FFFF
0012F828   0012F848
0012F82C  /0012F850
0012F830  |00965419  返回到 00965419 来自 0096D340
0012F834  |00000080
0012F838  |0012F84C
0012F83C  |00000004
0012F840  |0012F864
0012F844  |0012F870
0012F848  |00000078
0012F84C  |00010100      //原来的00010001表示延时256秒,将延时改为1秒
F9运行,用客户端连接,连上后再断开,察看服务端连线,发现以前总是显示为TIME_WAIT的连接,现在马上消失了,至此问题解决:)
3、Radmin修改
Radmin的保护措施做的还是很不错的,它的真正的执行程序是一个RES资源,主程序只负责将其解压缩到内存中并执行,如果要修改就需要自己解压缩,修改后再自己压缩了放回去,具体怎么做我就不说了:)
提示:如果要重复我一样步骤,直接下setsocketopt是断不下来的,先下jmp eax ,断下来后F8一次,再下setsoketopt断点,好了,就提示这么多了。