The MASM Forum

General => The Campus => Topic started by: Zen on July 04, 2014, 09:19:34 AM

Title: RtlCopyMemory
Post by: Zen on July 04, 2014, 09:19:34 AM
 :biggrin:
Title: Re: RtlCopyMemory
Post by: nidud on July 04, 2014, 09:30:00 AM
deleted
Title: Re: RtlCopyMemory
Post by: jj2007 on July 04, 2014, 09:36:09 AM
Try
   RtlCopyMemory equ crt_memcpy
   invoke RtlCopyMemory, addr dest, addr src, sizeof dest
(more (http://stackoverflow.com/questions/1937173/does-rtlcopymemory-work-in-vista))

MemCopy is also fine, so is rep movsb:
   push esi
   push edi
   mov esi, offset src
   mov edi, offset dest
   mov ecx, sizeof dest
   rep movsb
   pop edi
   pop esi

If speed matters, use rep movsd.
Title: Re: RtlCopyMemory
Post by: MichaelW on July 04, 2014, 04:49:10 PM
I was hoping to test the speed of RtlCopyMemory, but in my tests under Windows XP and Windows 7 ntoskrnl.exe did not export the function RtlCopyMemory, but did export the function RtlMoveMemory (along with a long list of other functions).

;==============================================================================
include \masm32\include\masm32rt.inc
;==============================================================================
.data
    hModule         HMODULE 0
    pRtlCopyMemory  dd      0
    pRtlMoveMemory  dd      0
    buff1           db      "my other brother darryl",0
    buff2           db      "                       ",0
.code
;==============================================================================
start:
;==============================================================================
    invoke LoadLibrary, chr$("ntoskrnl.exe")
    mov   hModule, eax
    invoke GetProcAddress, hModule, chr$("RtlCopyMemory")
    mov   pRtlCopyMemory, eax
    .IF eax == 0
        printf("%s\n",LastError$())
        jmp   @F
    .ENDIF
    push  SIZEOF buff1
    push  OFFSET buff1
    push  OFFSET buff2
    call  pRtlCopyMemory
  @@:
    invoke GetProcAddress, hModule, chr$("RtlMoveMemory")
    mov   pRtlMoveMemory, eax
    .IF eax == 0
        printf("%s\n",LastError$())
        jmp   @F
    .ENDIF
    push  SIZEOF buff1
    push  OFFSET buff1
    push  OFFSET buff2
    call  pRtlMoveMemory
    printf("%s\n\n", ADDR buff2)
  @@:
    inkey
    exit
;==============================================================================
end start

Title: Re: RtlCopyMemory
Post by: jj2007 on July 04, 2014, 05:51:18 PM
Quote from: MichaelW on July 04, 2014, 04:49:10 PM
I was hoping to test the speed of RtlCopyMemory

You can test it easily ;-) (http://www.masmforum.com/board/index.php?topic=4293.msg32162#msg32162)
Title: Re: RtlCopyMemory
Post by: hutch-- on July 04, 2014, 07:38:07 PM
Its a bit to do with the hardware, long ago a DWORD copy was faster but at least some of the later processors had special case circuitry that made REP MOVSB as fast as REP MOVSD. We did tests years ago that showed that under about 500 bytes incremented pointers were faster but over that the special case circuitry kicked in and was faster. You MAY get faster with an SSE copy but from the test I saw years ago this was barely the case.

If reliability is the main issue, REP MOVSB does the job fine. Its small and it can easily be inlined if it matters.
Title: Re: RtlCopyMemory
Post by: MichaelW on July 04, 2014, 08:23:27 PM
Quote from: jj2007 on July 04, 2014, 05:51:18 PM
You can test it easily...

I'm not convinced that it's so simple. I need to examine ntoskrnl.lib.
Title: Re: RtlCopyMemory
Post by: nidud on July 04, 2014, 08:43:02 PM
deleted
Title: Re: RtlCopyMemory
Post by: nidud on July 04, 2014, 11:21:26 PM
deleted
Title: Re: RtlCopyMemory
Post by: ragdog on July 04, 2014, 11:30:49 PM
Hi

Quote
Microsoft plans to formally banish the popular programming function that's been responsible for an untold number of security vulnerabilities over the years, not just in Windows but in countless other applications based on the C language. Effective later this year, Microsoft will add memcpy(), CopyMemory(), and RtlCopyMemory() to its list of function calls banned under its secure development lifecycle.

http://msdn.microsoft.com/en-us/library/bb288454.aspx
Title: Re: RtlCopyMemory
Post by: MichaelW on July 05, 2014, 12:09:50 AM
I finally managed to get a Windows 7 SDK installed, and in winnt.h RtlCopyMemory is defined as memcpy, and inlined only if _DBG_MEMCPY_INLINE_ is defined. The inline version checks for the source and destination overlapping, so it's apparently inlined only for convenience.

And there is no ntoskrnl.lib.
Title: Re: RtlCopyMemory
Post by: Tedd on July 05, 2014, 01:05:50 AM
RtlCopyMemory/memcpy copies memory from A to B, under the assumption they do not overlap.
RtlMoveMemory/memmove copies memory from A to B, under the assumption they do overlap.

The latter will still work if they are not overlapping, but takes extra unnecessary steps in that case.
Title: Re: RtlCopyMemory
Post by: jj2007 on July 05, 2014, 01:10:19 AM
QuoteMicrosoft plans to formally banish ... memcpy(), CopyMemory(), and RtlCopyMemory()

And Intel & AMD will ban rep movsb :lol:

Quote from: MichaelW on July 05, 2014, 12:09:50 AM
And there is no ntoskrnl.lib.

But there is ..\system32\ntoskrnl.exe, and it's crammed full of interesting exports. No RtlCopyMemory, however :(

Just for fun:

include \masm32\MasmBasic\MasmBasic.inc      ; download (http://masm32.com/board/index.php?topic=94.0)
NtSTRING STRUCT
NtLength          USHORT ?
NtMaxLength       USHORT ?
NtBuffer          PCHAR ?
NtSTRING ENDS

.data
src      NtSTRING <sizeof xsrc, sizeof xsrc, xsrc>
dest     NtSTRING <0, sizeof xdest, xdest>
xsrc     db "This is a string", 0
xdest    db 100 dup(?)

  Init                  ; ### RtlCopyString example ###
  Dll "ntoskrnl.exe"
  Declare RtlCopyString, 2
  void RtlCopyString(addr dest, addr src)
  Print Str$("%i bytes copied, result: [", dest.NtLength), offset xdest, "]"
  Exit
end start
Title: Re: RtlCopyMemory
Post by: guga on July 05, 2014, 01:25:51 AM
RtlCOpyMemory and some others are only macros as defined in ntrtl.h and winnt.h


#else
#define RtlEqualMemory(Destination,Source,Length) (!memcmp((Destination),(Source),(Length)))
#endif

#define RtlMoveMemory(Destination,Source,Length) memmove((Destination),(Source),(Length))
#define RtlCopyMemory(Destination,Source,Length) memcpy((Destination),(Source),(Length))
#define RtlFillMemory(Destination,Length,Fill) memset((Destination),(Fill),(Length))
#define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length))
Title: Re: RtlCopyMemory
Post by: nidud on July 05, 2014, 02:09:57 AM
deleted
Title: Re: RtlCopyMemory
Post by: ragdog on July 05, 2014, 02:17:10 AM
QuoteAnd Intel & AMD will ban rep movsb :lol:

:biggrin:

but you can read it by http://msdn.microsoft.com/en-us/library/bb288454.aspx
Title: Re: RtlCopyMemory
Post by: dedndave on July 05, 2014, 03:09:13 AM
sounds to me like that breaks a lot of existing software   :(
Title: Re: RtlCopyMemory
Post by: jj2007 on July 05, 2014, 03:22:48 AM
Quote from: ragdog on July 05, 2014, 02:17:10 AM
but you can read it by http://msdn.microsoft.com/en-us/library/bb288454.aspx

QuoteWhen the C runtime library (CRT) was first created over three decades ago, the threats to computers were different; computers were not as interconnected as they are today, and attacks were not as prevalent.

The documentation is incorrect, it should read as follows:
QuoteWhen the C runtime library (CRT) was first created over three decades ago, C++ was not yet around, and C coders still knew what they were doing
Title: Re: RtlCopyMemory
Post by: Zen on July 06, 2014, 03:17:04 AM
 :biggrin:
Title: Re: RtlCopyMemory
Post by: Zen on July 06, 2014, 06:52:49 AM
 :biggrin:
Title: Re: RtlCopyMemory
Post by: MichaelW on July 06, 2014, 08:49:41 AM
I had trouble understanding the portion of your code that you posted, so I rolled my own (it's ridiculous, but it did entertain me for a while).

;=======================================================================================================
include \masm32\include\masm32rt.inc
;=======================================================================================================
.data
.code
;=======================================================================================================
HEXDUMP MACRO address, paragraphs, zerobase
    invoke HexAsciiDump, address, paragraphs, zerobase
ENDM
;-----------------------------------------------------------------------
; This longer name avoids a conflict with the MASM32 HexDump procedure.
;-----------------------------------------------------------------------
HexAsciiDump proc startAddress:DWORD, nParagraphs:DWORD, fZeroBase:DWORD
    push ebx
    push edi
    push esi
    mov esi, startAddress
    xor ebx, ebx
    .WHILE ebx < nParagraphs
        mov eax, esi
        mov ecx, ebx
        shl ecx, 4
        .IF fZeroBase
            printf( "%08X  ", ecx )
        .ELSE
            add eax, ecx
            printf( "%08X  ", eax )
        .ENDIF
        xor edi, edi
        .WHILE edi < 16
            mov ecx, ebx
            shl ecx, 4
            add ecx, edi
            movzx eax, BYTE PTR [esi+ecx]
            printf( "%02X ", eax )
            .IF edi == 7
                printf( "- " )
            .ENDIF
            inc edi
        .ENDW
        printf( "  " )
        xor edi, edi
        .WHILE edi < 16
            mov ecx, ebx
            shl ecx, 4
            add ecx, edi
            movzx eax, BYTE PTR [esi+ecx]
            .IF eax > 31 && eax < 127
                printf( "%c", eax )
            .ELSE
                printf( "." )
            .ENDIF
            inc edi
        .ENDW
        printf( "\n" )
        inc ebx
    .ENDW
    pop esi
    pop edi
    pop ebx
    ret
HexAsciiDump endp
;=======================================================================================================
start:
;=======================================================================================================
    printf("%d\n", SIZEOF TOKEN_PRIVILEGES)
    printf("%d\n", SIZEOF LUID_AND_ATTRIBUTES)
    printf("%d\n", SE_PRIVILEGE_ENABLED)

    mov esi, halloc(SIZEOF TOKEN_PRIVILEGES + SIZEOF LUID_AND_ATTRIBUTES * 3)
    mov [esi].TOKEN_PRIVILEGES.PrivilegeCount, 4

    printf("%d\n\n", [esi].TOKEN_PRIVILEGES.PrivilegeCount)

    ; MOV DWORD PTR DS:[ESI+4],1
    mov [esi].TOKEN_PRIVILEGES.Privileges[0].LUID_AND_ATTRIBUTES.Luid.LUID.LowPart, 1
    mov [esi].TOKEN_PRIVILEGES.Privileges[0].LUID_AND_ATTRIBUTES.Luid.LUID.HighPart, 2
    mov [esi].TOKEN_PRIVILEGES.Privileges[0].LUID_AND_ATTRIBUTES.Attributes, SE_PRIVILEGE_ENABLED
    mov [esi].TOKEN_PRIVILEGES.Privileges[12].LUID_AND_ATTRIBUTES.Luid.LUID.LowPart, 3
    mov [esi].TOKEN_PRIVILEGES.Privileges[12].LUID_AND_ATTRIBUTES.Luid.LUID.HighPart, 4
    mov [esi].TOKEN_PRIVILEGES.Privileges[12].LUID_AND_ATTRIBUTES.Attributes, SE_PRIVILEGE_ENABLED
    mov [esi].TOKEN_PRIVILEGES.Privileges[24].LUID_AND_ATTRIBUTES.Luid.LUID.LowPart, 5
    mov [esi].TOKEN_PRIVILEGES.Privileges[24].LUID_AND_ATTRIBUTES.Luid.LUID.HighPart, 6
    mov [esi].TOKEN_PRIVILEGES.Privileges[24].LUID_AND_ATTRIBUTES.Attributes, SE_PRIVILEGE_ENABLED
    mov [esi].TOKEN_PRIVILEGES.Privileges[36].LUID_AND_ATTRIBUTES.Luid.LUID.LowPart, 7
    mov [esi].TOKEN_PRIVILEGES.Privileges[36].LUID_AND_ATTRIBUTES.Luid.LUID.HighPart, 8
    mov [esi].TOKEN_PRIVILEGES.Privileges[36].LUID_AND_ATTRIBUTES.Attributes, SE_PRIVILEGE_ENABLED

    mov ebx, esi
    add ebx, 4
    HEXDUMP ebx, 1, 1
    add ebx, 12
    HEXDUMP ebx, 1, 1
    add ebx, 12
    HEXDUMP ebx, 1, 1
    add ebx, 12
    HEXDUMP ebx, 1, 1

    printf("\n")

    hfree esi

    mov esi, halloc(SIZEOF TOKEN_PRIVILEGES + SIZEOF LUID_AND_ATTRIBUTES * 3)
    mov [esi].TOKEN_PRIVILEGES.PrivilegeCount, 4

    printf("%d\n\n", [esi].TOKEN_PRIVILEGES.PrivilegeCount)

    xor edi, edi
   
    ; MOV DWORD PTR DS:[EDI+ESI+4],1
    mov [esi].TOKEN_PRIVILEGES.Privileges[edi].LUID_AND_ATTRIBUTES.Luid.LUID.LowPart, 1
    mov [esi].TOKEN_PRIVILEGES.Privileges[edi].LUID_AND_ATTRIBUTES.Luid.LUID.HighPart, 2
    mov [esi].TOKEN_PRIVILEGES.Privileges[edi].LUID_AND_ATTRIBUTES.Attributes, SE_PRIVILEGE_ENABLED
    mov [esi].TOKEN_PRIVILEGES.Privileges[edi+12].LUID_AND_ATTRIBUTES.Luid.LUID.LowPart, 3
    mov [esi].TOKEN_PRIVILEGES.Privileges[edi+12].LUID_AND_ATTRIBUTES.Luid.LUID.HighPart, 4
    mov [esi].TOKEN_PRIVILEGES.Privileges[edi+12].LUID_AND_ATTRIBUTES.Attributes, SE_PRIVILEGE_ENABLED
    mov [esi].TOKEN_PRIVILEGES.Privileges[edi+24].LUID_AND_ATTRIBUTES.Luid.LUID.LowPart, 5
    mov [esi].TOKEN_PRIVILEGES.Privileges[edi+24].LUID_AND_ATTRIBUTES.Luid.LUID.HighPart, 6
    mov [esi].TOKEN_PRIVILEGES.Privileges[edi+24].LUID_AND_ATTRIBUTES.Attributes, SE_PRIVILEGE_ENABLED
    mov [esi].TOKEN_PRIVILEGES.Privileges[edi+36].LUID_AND_ATTRIBUTES.Luid.LUID.LowPart, 7
    mov [esi].TOKEN_PRIVILEGES.Privileges[edi+36].LUID_AND_ATTRIBUTES.Luid.LUID.HighPart, 8
    mov [esi].TOKEN_PRIVILEGES.Privileges[edi+36].LUID_AND_ATTRIBUTES.Attributes, SE_PRIVILEGE_ENABLED

    mov ebx, esi
    add ebx, 4
    HEXDUMP ebx, 1, 1
    add ebx, 12
    HEXDUMP ebx, 1, 1
    add ebx, 12
    HEXDUMP ebx, 1, 1
    add ebx, 12
    HEXDUMP ebx, 1, 1

    printf("\n\n")

    hfree esi

    inkey
    exit
;=======================================================================================================
end start


16
12
2
4

00000000  01 00 00 00 02 00 00 00 - 02 00 00 00 03 00 00 00   ................
00000000  03 00 00 00 04 00 00 00 - 02 00 00 00 05 00 00 00   ................
00000000  05 00 00 00 06 00 00 00 - 02 00 00 00 07 00 00 00   ................
00000000  07 00 00 00 08 00 00 00 - 02 00 00 00 00 00 00 00   ................

4

00000000  01 00 00 00 02 00 00 00 - 02 00 00 00 03 00 00 00   ................
00000000  03 00 00 00 04 00 00 00 - 02 00 00 00 05 00 00 00   ................
00000000  05 00 00 00 06 00 00 00 - 02 00 00 00 07 00 00 00   ................
00000000  07 00 00 00 08 00 00 00 - 02 00 00 00 00 00 00 00   ................

Title: Re: RtlCopyMemory
Post by: Tedd on July 07, 2014, 10:05:29 PM
Quote from: nidud on July 05, 2014, 02:09:57 AM
Quote from: Tedd on July 05, 2014, 01:05:50 AM
RtlCopyMemory/memcpy copies memory from A to B, under the assumption they do not overlap.
RtlMoveMemory/memmove copies memory from A to B, under the assumption they do overlap.

The latter will still work if they are not overlapping, but takes extra unnecessary steps in that case.
If you look at the source code (.\crt\string\I386\MEMCPY.ASM) you will see it's the same code. So both of them check for overlap.
That's an implementation detail. It just happens that in the Microsoft C runtime, they chose to implement them both using the same function that checks for overlap and then jumps to the appropriate method (copy forwards or backwards), but it doesn't have to be implemented that way. Another version could very well implement them separately, without any direct checking for overlap.
Title: Re: RtlCopyMemory
Post by: Zen on July 08, 2014, 09:24:24 AM
 :biggrin: