Trying to understand a function thats responsible for sending out a packet. I don't understand could it be a integer array or something? or some inline function that's not properly getting rendered in Hex-Rays
I understand the else statement sends a 4 byte packet which contains a timestamp of the GetTickCount API.
The if statement should send the packet that comes in the a2
is the pointer to characters with a3 being the size for all the characters.
Usage is similar to this
char buffer[448];
memset(buffer, 0, sizeof(buffer));
//blah blah packet stuff here
strncpy(&buffer[90], "blah blah blah", 250u);
buffer[339] = 0;
//then the call below.
// 91+250+91 = 432, yet memset is 448, 16 extra probably stack padding.
test(*v28, buffer, strlen(&buffer[90]) + 91);
Here is the original code decompiled from Hex-Rays.
void __thiscall test(void *this, const void *a2, unsigned int a3)
{
void *v3; // ebx@1
char *v4; // eax@3
int v5; // [sp-8h] [bp-418h]@3
int v6; // [sp-4h] [bp-414h]@3
char v7[4]; // [sp+Ch] [bp-404h]@4
char buf[1024]; // [sp+10h] [bp-400h]@3
v3 = this;
if ( a2 && (signed int)a3 > 0 )
{
*(_DWORD *)buf = 0;
memcpy(&buf[4], a2, 4 * (a3 >> 2));
v6 = 0;
v5 = a3 + 4;
v4 = buf;
memcpy(&buf[4 * (a3 >> 2) + 4], (char *)a2 + 4 * (a3 >> 2), a3 & 3);// Looks like Copy by DWORDs, not by Bytes.
}
else
{
v6 = 0;
*(_DWORD *)v7 = GetTickCount() / 0xA;
v5 = 4;
v4 = v7;
}
send(*(_DWORD *)v3, v4, v5, v6);
}
Here I fixed it up a little by hand, still don't understand it.
void __thiscall test(void *this, const void *a2, unsigned int a3)
{
void *v3; // ebx@1
char *v4; // eax@3
int v5; // [sp-8h] [bp-418h]@3
int v6; // [sp-4h] [bp-414h]@3
char v7[4]; // [sp+Ch] [bp-404h]@4
char buf[1024]; // [sp+10h] [bp-400h]@3
v3 = this;
if ( a2 && (signed int)a3 > 0 )
{
*(_DWORD *)buf = 0;
//Might be a swap of the 5th offset DWORD to end of the packet?
//Or maybe it fills in the packet offsetted by the first 4 bytes?
memcpy(&buf[4], a2, 4 * (a3 / 4)); // Looks like Copy by DWORDs, not by Bytes.
v6 = 0;
v5 = a3 + 4;
v4 = buf;
//Might be a swap of the end of the packet to the 5th offset DWORD?
//Looks like some kind of footer to above memcpy function like to finish what the first function couldn't do?
memcpy(&buf[4 * (a3 / 4) + 4], (char *)a2 + 4 * (a3 / 4), a3 & 3);// Looks like Copy by DWORDs, not by Bytes.
}
else
{
v6 = 0;
*(_DWORD *)v7 = GetTickCount() / 0xA;
v5 = 4;
v4 = v7;
}
send(*(_DWORD *)v3, v4, v5, v6);
}
Okay I gave it some more time could this be the correct?
void __thiscall test(void *this, const void *a2, unsigned int a3)
{
void *v3; // ebx@1
char *v4; // eax@3
int v5; // [sp-8h] [bp-418h]@3
int v6; // [sp-4h] [bp-414h]@3
char v7[4]; // [sp+Ch] [bp-404h]@4
char buf[1024]; // [sp+10h] [bp-400h]@3
v3 = this;
if ( a2 && (signed int)a3 > 0 )
{
*(_DWORD *)buf = 0;
memmove(&buf[4],a2,a3 - 4);
v6 = 0;
v5 = a3 + 4;
v4 = buf;
}
else
{
v6 = 0;
*(_DWORD *)v7 = GetTickCount() / 0xA;
v5 = 4;
v4 = v7;
}
send(*(_DWORD *)v3, v4, v5, v6);
}
Assembly below
.text:00408750 ; =============== S U B R O U T I N E =======================================
.text:00408750
.text:00408750
.text:00408750 ; void __thiscall test(void *this, const void *a2, unsigned int a3)
.text:00408750 test proc near
.text:00408750 ; CODE XREF: ServerMainLoop+5DDp
.text:00408750 ; ServerMainLoop+64Dp
.text:00408750
.text:00408750 var_404 = byte ptr -404h
.text:00408750 buf = byte ptr -400h
.text:00408750 a2 = dword ptr 4
.text:00408750 a3 = dword ptr 8
.text:00408750
.text:00408750 sub esp, 404h
.text:00408756 push ebx
.text:00408757 push esi
.text:00408758 mov esi, [esp+40Ch+a2]
.text:0040875F push edi
.text:00408760 test esi, esi
.text:00408762 mov ebx, ecx
.text:00408764 jz short loc_408799
.text:00408766 mov eax, [esp+410h+a3]
.text:0040876D test eax, eax
.text:0040876F jle short loc_408799
.text:00408771 mov ecx, eax
.text:00408773 lea edi, [esp+410h+buf+4]
.text:00408777 mov edx, ecx
.text:00408779 mov dword ptr [esp+410h+buf], 0
.text:00408781 shr ecx, 2
.text:00408784 rep movsd
.text:00408786 mov ecx, edx
.text:00408788 push 0
.text:0040878A and ecx, 3
.text:0040878D add eax, 4
.text:00408790 push eax
.text:00408791 lea eax, [esp+418h+buf]
.text:00408795 rep movsb
.text:00408797 jmp short loc_4087B7
.text:00408799 ; ---------------------------------------------------------------------------
.text:00408799
.text:00408799 loc_408799: ; CODE XREF: test+14j
.text:00408799 ; test+1Fj
.text:00408799 call ds:GetTickCount
.text:0040879F mov edx, eax
.text:004087A1 mov eax, 0CCCCCCCDh
.text:004087A6 mul edx
.text:004087A8 shr edx, 3
.text:004087AB push 0 ; flags
.text:004087AD mov dword ptr [esp+414h+var_404], edx
.text:004087B1 push 4 ; len
.text:004087B3 lea eax, [esp+418h+var_404]
.text:004087B7
.text:004087B7 loc_4087B7: ; CODE XREF: test+47j
.text:004087B7 mov ecx, [ebx]
.text:004087B9 push eax ; buf
.text:004087BA push ecx ; s
.text:004087BB call send
.text:004087C0 pop edi
.text:004087C1 pop esi
.text:004087C2 pop ebx
.text:004087C3 add esp, 404h
.text:004087C9 retn 8
.text:004087C9 test endp
.text:004087C9
.text:004087C9 ; ---------------------------------------------------------------------------
DWORD
s and one byBYTE
s, is a common optimization technique. Hex-Rays is not infallible, it might be tricked by some instructions mixed into the middle of the loop. Since you're not providing the disassembled code, it's hard to tell for sure, butmemcpy
is more likely thanmemset
.memcpy
turned out to be amemset
undercover the>> 2
always revealed it, so I think it could be amemset
variant.rep movsd
andrep movsb
must be them.rep movs*
copies data from one buffer to another, likememcpy
.rep stos*
writes constant data to a buffer, likememset
does.memmove
thenmemset
.