为什么在缓冲区小于使用recv时的消息时循环?

时间:2017-01-22 05:36:16

标签: assembly recv

我正在为服务器二进制文件进行逆向工程,并且在查看recv调用的某些代码时遇到了一些麻烦。

我从程序集中派生了以下伪代码,而while循环条件让我困惑:

     func_804a890(int socket, void *buffer_start, size_t buffer_len, int num_open_descriptors) {
  int a, b, c;

  if (buffer_start == 0 || buffer_len == 0)
    //goto 0x804a8e8

  size_t msg_len = 0;
  void* buffer;
  ssize_t packet_len = 0;

  do {
    buffer_len -= packet_len;
    buffer = buffer_start + msg_len;
    packet_len = recv(socket, buffer, buffer_len, 0);
    if (packet_len == -1) {
      return -1;
    }
    else if (packet_len == 0) {
      //goto 0x804a8f8
    }
    else {
      //goto 0x804a8bc
    }

    msg_len += packet_len;

  } while(buffer_len > msg_len);
}

如果缓冲区大于来自客户端的消息,为什么我会循环?接下来是相关的汇编函数,以防我在伪代码中正确解释其中一个变量:

.text:0804a890 55                               push   ebp
.text:0804a891 57                               push   edi
.text:0804a892 56                               push   esi
.text:0804a893 53                               push   ebx
.text:0804a894 83 ec 0c                         sub    esp,0xc
.text:0804a897 8b 74 24 24                      mov    esi,DWORD PTR [esp+0x24]
.text:0804a89b 8b 7c 24 20                      mov    edi,DWORD PTR [esp+0x20]
.text:0804a89f 8b 5c 24 28                      mov    ebx,DWORD PTR [esp+0x28]
.text:0804a8a3 85 f6                            test   esi,esi
.text:0804a8a5 74 41                            je     0x0804a8e8
.text:0804a8a7 85 db                            test   ebx,ebx
.text:0804a8a9 74 3d                            je     0x0804a8e8
.text:0804a8ab 31 c0                            xor    eax,eax
.text:0804a8ad 31 ed                            xor    ebp,ebp
.text:0804a8af eb 13                            jmp    0x0804a8c4
.text:0804a8b1 8d b4 26 00 00 00 00             lea    esi,[esi+eiz*1+0x0]
.text:0804a8b8 85 c0                            test   eax,eax
.text:0804a8ba 74 3c                            je     0x0804a8f8
.text:0804a8bc 01 c5                            add    ebp,eax
.text:0804a8be 39 eb                            cmp    ebx,ebp
.text:0804a8c0 89 e8                            mov    eax,ebp
.text:0804a8c2 76 24                            jbe    0x0804a8e8
.text:0804a8c4 89 da                            mov    edx,ebx
.text:0804a8c6 6a 00                            push   0x0
.text:0804a8c8 29 c2                            sub    edx,eax
.text:0804a8ca 01 f0                            add    eax,esi
.text:0804a8cc 52                               push   edx
.text:0804a8cd 50                               push   eax
.text:0804a8ce 57                               push   edi
.text:0804a8cf e8 3c ec ff ff                   call   0x08049510
.text:0804a8d4 83 c4 10                         add    esp,0x10
.text:0804a8d7 83 f8 ff                         cmp    eax,0xffffffff
.text:0804a8da 75 dc                            jne    0x0804a8b8
.text:0804a8dc 83 c4 0c                         add    esp,0xc
.text:0804a8df 5b                               pop    ebx
.text:0804a8e0 5e                               pop    esi
.text:0804a8e1 5f                               pop    edi
.text:0804a8e2 5d                               pop    ebp
.text:0804a8e3 c3                               ret    

1 个答案:

答案 0 :(得分:2)

您似乎已将名称 'urlManager' => [ 'enablePrettyUrl' => true, 'showScriptName' => false, 'rules' => [ ['class' => 'yii\rest\UrlRule', 'pluralize'=>false, 'controller' => 'v1/app', 'patterns' => [ 'OPTIONS <action>' => 'options', ], ], ], 应用于程序中的两个不同值。其中buffer_len传递参数,第二个buffer_lenbuffer_len的参数。这实际上是两件不同的事情。第一个存储在EBX中,永远不会改变。在调用recv之前,第二个临时存储在EDX中。

该函数的更直译是:

recv

简化为:

int
func_804a890(int arg1, int arg2, int arg3) {
    int esi = arg2;
    int edi = arg1;
    unsigned ebx = arg3;

    if (esi != 0 && ebx != 0) {
        int eax = 0;
        unsigned ebp = 0;
        while(1) {
            int edx = ebx;
            edx -= eax;
            eax += esi;
            eax = recv(edi, (void *) eax, edx, 0);
            if (eax == -1) {
                return eax;
            }
            if (eax == 0) {
                /* ??? */
            }
            ebp += eax;
            eax = ebp;
            if (ebx <= ebp) {
                break;
            }
        }
    }
    /* ??? */
}

循环继续,而接收的总金额(int func_804a890(int socket, char *buffer, unsigned len) { if (buffer != 0 && len != 0) { unsigned pos = 0; while(1) { int recv_len = recv(socket, buffer + pos, len - pos, 0); if (recv_len == -1) { return recv_len; } if (recv_len == 0) { /* ??? */ } pos += recv_len; if (len <= pos) { break; } } } /* ??? */ } )小于传递给函数(pos)的缓冲区的长度。