我正在为服务器二进制文件进行逆向工程,并且在查看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
答案 0 :(得分:2)
您似乎已将名称 'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule',
'pluralize'=>false,
'controller' => 'v1/app',
'patterns' => [
'OPTIONS <action>' => 'options',
],
],
],
应用于程序中的两个不同值。其中buffer_len
传递参数,第二个buffer_len
是buffer_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
)的缓冲区的长度。