0

So I am currently in the stages of creating binexact version of functions in decompiled code. I noticed that in this function the rep movsd is called and logically this is translated as Qmemcpy/memcpy when transformed to Pcode in IDA. In order to bin exact this , I cannot use memcopy because a function will be called and the code wont be bin exact. Is there a way to try to force the use of rep movsd ? I understand this is somewhat compiler dependent, but I was thinking I could write this differently to force the same effect.

C code This is what I need to change to match original assembly

BOOL NetSendCmdReq2(BYTE bCmd, BYTE mast, BYTE pnum, TCmdGItem *p)
{
    DWORD ticks;
    TCmdGItem cmd;

    memcpy(&cmd, p, sizeof(cmd));
    cmd.bCmd = bCmd;
    cmd.bPnum = pnum;
    cmd.bMaster = mast;

    ticks = GetTickCount();
    if (!cmd.dwTime) {
        cmd.dwTime = ticks;
    } else if (ticks - cmd.dwTime > 5000) {
        return FALSE;
    }

    multi_msg_add((BYTE *)&cmd.bCmd, sizeof(cmd));

    return TRUE;
}

Compare Assembly: (This is what the C above compiles to)

push ebp
mov ebp, esp
sub esp, 0x28
push ebx
push esi
push 0x26
lea eax, [ebp-0x28]
push [ebp+0x10]
mov bl, dl
mov esi, ecx
push eax
call <imm_fn> <------ This should be rep movsd rather than a call.
mov al, [ebp+0x0C]
add esp, 0x0C
mov [ebp-0x26], al
mov al, [ebp+0x08]
test esi, esi
mov [ebp-0x28], bl
mov [ebp-0x27], al
jnz $+0xF
and [ebp-0x0E], esi
mov dl, 0x26
lea ecx, [ebp-0x28]
call <imm_fn>
jmp $+0x25
call [<indir_fn>]
cmp dword ptr [ebp-0x0E], 0x00
jnz $+0x5
mov [ebp-0x0E], eax
jmp $+0xA
sub eax, [ebp-0x0E]
cmp eax, 0x1388
jnle $+0xA
mov dl, 0x26
lea ecx, [ebp-0x28]
call <imm_fn>

pop esi
pop ebx
leave
ret 0x0C

Origional Assembly : This is what should be matched .

push ebp 
mov ebp, esp
sub esp, 0x28

push esi
mov esi, [ebp+0x10]
push edi
mov eax, ecx
push 0x09
lea edi, [ebp-0x28]
pop ecx
rep movsd < ----- Notice this doesn't make an actual call.
mov cl, [ebp+0x0C]
movsw  
mov [ebp-0x26], cl
mov cl, [ebp+0x08]
test eax, eax
mov [ebp-0x28], dl
mov [ebp-0x27], cl
jnz $+0xF
and [ebp-0x0E], eax
mov dl, 0x26
lea ecx, [ebp-0x28]
call <imm_fn>
jmp $+0x25
call [<indir_fn>]
cmp dword ptr [ebp-0x0E], 0x00
jnz $+0x5
mov [ebp-0x0E], eax
jmp $+0xA
sub eax, [ebp-0x0E]
cmp eax, 0x1388
jnle $+0xA
mov dl, 0x26
lea ecx, [ebp-0x28]
call <imm_fn>
pop edi
pop esi

leave
ret 0x0C 
2
0

here is a sample code that will emit rep movsd instead of memcpy() function

the src const char * is deliberately kept large enough to avoid unrolling and using simple mov [dest++] ,const

source

:\>cat memcopin.cpp
#include <memory.h>
#pragma intrinsic( memcpy )

char *src ="\
I am Source And I Will be truncated by memcpy\n\
I am Source And I Will be truncated by memcpy\n";

char dest[128];

int main(void) {
    memcpy(dest,src,64);
    return 0;
}

compiled and linked with vscommunity 2017 dev cmd prompt as x86 on x86

:\>cl /Zi /W4 /analyze /EHsc /Od /nologo memcopin.cpp /link /release
memcopin.cpp

executed under debugger cdb.exe(windbg console) awk is not a necessity it is there to get only relevent output and awk is availble for windows x86 and x64

:\>cdb -c "g memcopin!main;uf .;pt;da /c 64 poi(src);da /c 64 dest;q" memcopin.exe |awk "/Reading/,/quit:/"

0:000> cdb: Reading initial command 'g memcopin!main;uf .;pt;da /c 64 poi(src);da /c 64 dest;q'
disassembly  of main()

memcopin!main:
01291000 55              push    ebp
01291001 8bec            mov     ebp,esp
01291003 56              push    esi
01291004 57              push    edi
01291005 b910000000      mov     ecx,10h
0129100a 8b3500902d01    mov     esi,dword ptr [memcopin!src (012d9000)]
01291010 bfe0992d01      mov     edi,offset memcopin!dest (012d99e0)
01291015 f3a5            rep movs dword ptr es:[edi],dword ptr [esi]
01291017 33c0            xor     eax,eax
01291019 5f              pop     edi
0129101a 5e              pop     esi
0129101b 5d              pop     ebp
0129101c c3              ret
src 
012d0190  "I am Source And I Will be truncated by memcpy.I am Source And I Will be truncated by memcpy."
dest
012d99e0  "I am Source And I Will be truncated by memcpy.I am Source And I "
quit:
2
  • Your idea works. But it wasn't the solution for me . Apparently the original developers just made a pointer to the struct to copy it. – LUser Nov 6 '20 at 21:05
  • cmd = *pcmditem; instead of memcpy . – LUser Nov 6 '20 at 21:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.