Size_t _ thiscall sub_4015C0 (void * this, int a2, char a3, int a4) {void * v4; // esi @ 1 SOCKET v5; // ebx @ 2 const char * v6; // eax @ 4 unsigned _ int32 v7; // eax @ 4 u_short v8; // dx @ 4 size_t v9; // ebp @ 6 char * v11; // eax @ 9 char * v12; // esi @ 10 const char v13; // al @ 13 int * v14; // ecx @ 14 const char * v15; // esi @ 18 unsigned int v16; // kr18_4 @ 18 struct sockaddr name; // [sp + 10 h] [bp-9BCh] @ 4 int v18 ;/ /[Sp + 20 h] [bp-9ACh] @ 13 int v19; // [sp + 24 h] [bp-9A8h] @ 13 int v20; // [sp + 28 h] [bp-9A4h] @ 13 int v21; // [sp + 2Ch] [bp-9A0h] @ 13 char Str [1024]; // [sp + 30 h] [bp-99Ch] @ 6 char Src; // [sp + 430 h] [bp-59Ch] @ 6 struct WSAData; // [sp + 830 h] [bp-19Ch] @ 1 int v25; // [sp + 9C8h] [bp-4h] @ 1 v4 = this; v25 = 1; if (WSAStartup (0x202u, & WSAData) goto LABEL_8; v5 = socket (2, 1, 0); if (v5 & 0x80000000u )! = 0) {CString: operator _ ("failed to create SOCKET"); LABEL_8: WSACleanup (); LOBYTE (v25) = 0; sub_515C81 (& a2 ); v25 =-1; sub_515C81 (& a3); return 0;} v6 = (const char *) * (_ DWORD *) v4 + 4); * (_ DWORD *) & name. sa_family = 0; * (_ DWORD *) & name. sa_data [2] = 0; name. sa_family = 2; * (_ DWORD *) & name. sa_data [6] = 0; * (_ DWORD *) & name. sa_data [10] = 0; v7 = inet_addr (v6); v8 = * (_ WORD *) v4 + 2); * (_ DWORD *) & name. sa_data [2] = V7; * (_ WORD *) & name. sa_data [0] = htons (v8); if (connect (v5, & name, 16) <0) {CString: operator _ (LPCSTR) & unk_571438 ); goto LABEL_8;} memset (Str, 0, sizeof (Str); sprintf (Str, "GET % s HTTP/1.1 \ r \ nHost: % s \ r \ nConnection: close \ r \ n ", a2, * (_ DWORD *) v4 + 4); send (v5, Str, strlen (Str) + 1, 0); memset (Str, 0, sizeof (Str); memset (& Src, 0, 0x400u); v9 = recv (v5, Str, 0x3FFu, 0 ); str [v9] = 0; If (v9 & 0x80000000u )! = 0) {CString: operator _ ("no data"); goto LABEL_8;} v11 = strstr (Str, "\ r \ n "); if (v11) {v12 = v11 + 4; v9 = strlen (v11 + 4);} else {v12 = Str;} if (strstr (Str, "Transfer-Encoding: chunked ") {v13 = * v12; v18 = 0; v19 = 0; v20 = 0; v21 = 0; if (v13) {v14 = & v18; do {if (v13 = '\ R') break; if (v13 =' \ n') break; * (_ BYTE *) v14 = v13; v13 = v12 [1]; v14 = (int *) (char *) v14 + 1); + + v12 ;}while (v13);} v15 = v12 + 2; v9 = strtol (const char *) & v18, 0, 0x10u); v16 = strlen (v15) + 1; if (signed int) v9> (signed int) (v16-1) v9 = v16-1; strncpy (& Src, v15, v9);} else {strcpy (& Src, v12);} CString :: operator _ (& Src); closesocket (v5); WSACleanup (); LOBYTE (v25) = 0; sub_515C81 (& a2); v25 =-1; sub_515C81 (& a3 ); return v9 ;}
We can see that after receiving the data, find strstr (Str, "Transfer-Encoding: chunked"), and then find the length field based on the data format, call v9 = strtol (const char *) & v18, 0, 0x10u) to obtain the length without verification. if the length string is-1, the final if (signed int) the v9> (signed int) (v16-1) condition is invalid. Therefore, the number of bytes copied by strncpy (& Src, v15, v9) is 0 xFFFFFFFF, resulting in DOS. A small bug was also found.
Signed int _ cdecl sub_406810 (int a1) {SOCKET v1; // esi @ 4 signed int v3; // edx @ 10 signed int I; // esi @ 10 char v5; // al @ 11 char * v6; // edx @ 17 const char * v7; // edi @ 17 int fromlen; // [sp + 4 h] [bp-11BCh] @ 8 SOCKET s; // [sp + 8 h] [bp-11B8h] @ 4 int v10; // [sp + Ch] [bp-11B4h] @ 10 struct sockaddr name; // [sp + 10 h] [bp-11B0h] @ 4 struct sockaddr from; // [sp + 20 h] [bp-11A0h] @ 9 char lParam [2048]; // [sp + 30 h] [Bp-1190h] @ 9 struct WSAData; // [sp + 830 h] [bp-990h] @ 1 char v15 [2048]; // [sp + 9C0h] [bp-800h] @ 10 if (WSAStartup (0x202u, & WSAData) | (_ BYTE) WSAData. wVersion! = 2 | HIBYTE (WSAData. wVersion )! = (_ BYTE) WSAData. wVersion) {sub_5138E0 (void *) a1, "listener initialization failed", 0, 0); goto LABEL_37;} v1 = socket (2, 2, 0 ); s = v1; * (_ DWORD *) & name. sa_data [2] = 0; name. sa_family = 2; * (_ WORD *) & name. sa_data [0] = ntohs (10333u); if (v1! =-1) {if (bind (v1, & name, 16) {sub_5138E0 (void *) a1, "SOCKET binding failed", 0, 0 ); WSACleanup (); return-1;} fromlen = 16; while (1) {do {memset (lParam, 0, sizeof (lParam); memset (& from, 0, fromlen); recvfrom (s, lParam, 2048, 0, & from, & fromlen);} while (strcmp (cp, inet_ntoa (* (struct in_addr *) & from. sa_data [2]); memset (v15, 0, sizeof (v15); sscanf (lParam, "% d & % s", & v10, v15 ); memset (lPara M, 0, sizeof (lParam); v3 = 0; for (I = 0; I <(signed int) strlen (v15); ++ I) {v5 = v15 [I]; if (v5 = ''') {lParam [v3 ++] = '\ R '; lParam [v3] = '\ n';} else {lParam [v3] = v5; }++ v3; if (v3> = 2048) break ;} if (strcmp (lParam, "timeout_error") {if (strcmp (lParam, "time_policy_error") {if (strcmp (lParam, "max_flux_error ")) {if (strcmp (lParam, "max_hours_error") {if (strcmp (lPa Ram, "remain_seconds_error") {if (strcmp (lParam, "remain_flux_error") {if (strcmp (lParam, "flux_switch_error") {if (strcmp (lParam, "timelong_switch_error") goto LABEL_33; v6 = lParam; v7 = "the billing group has been switched. ";}Else {v6 = lParam; v7 =" The rated traffic is exhausted and the billing group has been switched. ";}} Else {v6 = lParam; v7 = (const char *) & unk_571FB0 ;}} else {v6 = lParam; v7 = (const char *) & unk_571FEC ;}} else {v6 = lParam; v7 = (const char *) & unk_57202C ;}} else {v6 = lParam; v7 = (const char *) & unk_57206C ;}} else {v6 = lParam; v7 = (const char *) & unk_5720AC;} else {v6 = lParam; v7 = (const char *) & unk_5720FC;} strcpy (v6, v7); LABEL_33: if (! V10) {SendMessageA (* (HWND *) (a1 + 28), 0x0000u, 5u, 0); SendMessageA (* (HWND *) (* (_ DWORD *) (a1 + 596) + 28), 0x0000u, 5u, 0);} SendMessageA (* (HWND *) (a1 + 28), 0x0000u, 3u, (LPARAM) lParam) ;}} sub_5138E0 (void *) a1, "SOCKET creation failed", 0, 0); LABEL_37: WSACleanup (); return-1 ;}
A bug exists in the for loop processing process, which can overwrite one byte of the returned address. This bug can be triggered when the data in v15 is '\ x60' * 1023 + 'A' +' \ x60 '.
for ( i = 0; i < (signed int)strlen(v15); ++i ) { v5 = v15[i]; if ( v5 == 0x60 ) { lParam[v3++] = '\r'; lParam[v3] = '\n'; } else { lParam[v3] = v5; } ++v3; if ( v3 >= 2048 ) break; }