Masm 64 call native API (NtOpenFile/NtWrteFile)

Building your code with /FA is your friend in this case…

Peter
OSR
@OSRDrivers

xxxxx@gmail.com wrote:

; init structs once
mov UnicodeFile.woLength, 64d ; 24 * 2 (24 caracter of 2 bytes (WCHAR))
mov UnicodeFile.MaxLength, 66h
lea rax, file
mov UnicodeFile.Buffer, rax

As a side note, your MaxLength should be 66d, not 66h. That won’t
affect anything here.

It is quite error-prone to compute these things by hand and embed a
hardcoded number. Better is something like:

file dw “",“D”,“o”,“s”,“D”,“e”,“v”,“i”,“c”,“e”,“s”,”",“D”,“:”,“",“r”,“o”,“o”,“t”,”_“,“t”,“m”,“p”,”",“y”,“o”,“l”,“o”,“.”,“t”,“x”,“t”,0
file_length equ $-file

However, I can’t get this to assemble, apparently because of an ml64
bug. It complains about operand sizes, even though the type and opattr
codes for those two symbols are both identical.

Better yet is to define a macro to create this from the string. You
could create something to let you do:

file UnicodeLiteral <\DosDevices\D:\root_tmp\yolo.txt>

that could iterate the characters, create the string, and define the length.

Ah, assembler. The good old days. Or were they?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Alex Grig
xxxxx@broadcom.com
Join Date: 14 Apr 2008
Posts To This List: 3085
Masm 64 call native API (NtOpenFile/NtWrteFile)
Is there any good reason you need to write that code in MASM?

Just to learn asambly and malware obfuscation technics. i want to makee syscalls. I can lookup on run time the number of syscall. I want to build a complet standalone shellcode without any lib for windows

Tim Roberts
xxxxx@probo.com
Join Date: 28 Jan 2005
Posts To This List: 11203
Masm 64 call native API (NtOpenFile/NtWrteFile)
xxxxx@gmail.com wrote:

For several weeks I have been trying to interact directly with the Windows
native API. Indeed I have code C which runs without problem but impossible to do
the same operations in asambly (MASM64).

NtWriteFile always returns “0xC000000D STATUS_INVALID_PARAMETER” while in C
everything runs without worries

; write into
mov qword ptr [rsp + 40h], 0h ; key
mov qword ptr [rsp + 38h], 10h ; byte offset
mov dword ptr [rsp + 30h], 64d ; length

The ByteOffset parameter to NtWriteFile is a pointer to a LARGE_INTEGER
structure, not a number passed by value.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

The byte offset origialy is set to 0, i just test with 10h, but your right!
With 0h byte offset (like in C) is didnt work is asm

Peter Viscarola (OSR)
xxxxx@osr.com
Join Date:
Posts To This List: 5718
List Moderator
Masm 64 call native API (NtOpenFile/NtWrteFile)

Building your code with /FA is your friend in this case…

Peter
OSR
@OSRDrivers

Thank you for /FA, i have the disassably window in VS2015 but with /FA i have this code for NtWriteFile:

mov QWORD PTR [rsp+64], 0
mov QWORD PTR [rsp+56], 0
mov eax, DWORD PTR MessageLength$[rbp]
mov DWORD PTR [rsp+48], eax
mov rax, QWORD PTR Message
mov QWORD PTR [rsp+40], rax
lea rax, QWORD PTR Iosb$[rbp]
mov QWORD PTR [rsp+32], rax
xor r9d, r9d
xor r8d, r8d
xor edx, edx
mov rcx, QWORD PTR FileHandle$[rbp]
call QWORD PTR NtWriteFile$[rbp]

64-32 rsp ? Weird? not? and for NtCreateFile :
mov DWORD PTR [rsp+80], 0
mov QWORD PTR [rsp+72], 0
mov DWORD PTR [rsp+64], 32 ; 00000020H
mov DWORD PTR [rsp+56], 0
mov DWORD PTR [rsp+48], 0
mov DWORD PTR [rsp+40], 128 ; 00000080H
mov QWORD PTR [rsp+32], 0
lea r9, QWORD PTR Iosb$[rbp]
lea r8, QWORD PTR ObjectAttributes$[rbp]
mov edx, 34603008 ; 02100000H
lea rcx, QWORD PTR FileHandle$[rbp]
call QWORD PTR NtCreateFile$[rbp]

i am gone explore this piste…

xxxxx@gmail.com wrote:

The byte offset origialy is set to 0, i just test with 10h, but your right!
With 0h byte offset (like in C) is didnt work is asm

0 in that case does not mean the integer 0. It means you are passing a
null pointer.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Tim Roberts
xxxxx@probo.com
Join Date: 28 Jan 2005
Posts To This List: 11204
Masm 64 call native API (NtOpenFile/NtWrteFile)
xxxxx@gmail.com wrote:

The byte offset origialy is set to 0, i just test with 10h, but your right!
With 0h byte offset (like in C) is didnt work is asm

0 in that case does not mean the integer 0. It means you are passing a
null pointer.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Totally agree with you

I always have the same error. With the option / FA the code is exactly the same as my code in MASM…

I do not know what to do. Do you have any leads please?

xxxxx@gmail.com wrote:

I always have the same error. With the option / FA the code is exactly the same as my code in MASM…

I do not know what to do. Do you have any leads please?

Have you changed the ByteOffset parameter to be a pointer to a 64-bit
integer, instead of passing an integer directly?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

>Have you changed the ByteOffset parameter to be a pointer to a 64-bit

integer, instead of passing an integer directly?

Yes, i pass a 0h, like no ByteOffset need. Its an optional parameter, no change.
I try also passe valid ptr to QWORD, same error …

Why don’t you want simply to disassemble C code and see how it translates to assembly???

I did not look through your code thoroughly, but you seem to be passing function parameters on the stack. Although it is OK to do so under 32-bit Windows where API is based, IIRC, upon _stdcall convention (i.e the one where you pass all parameters on the stack), doing it under 64-bit OS is not going to work, because a callee expects to find first few parameters in registers ( which is true for both Windows and UNIX-like systems, although the actual ways of how the parameters are passed are different for MSFT and UNIX calling conventions)…

Anton Bassov

This code may crash:

call rax ; rax is NtCreateFile
mov qword ptr rcx, 0h ; BOOOOOOOMMMMM!!!
cmp rcx, rax ; #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
jl fatal_error_exit

RCX is volatile. When NtCreateFile has returned, the content of RCX is undefined, so accessing the address contained in RCX could cause an access violation. And as the comment suggests, an error is a negative NTSTATUS, so you should have:

call rax ; rax is NtCreateFile
test eax,eax ; NTSTATUS is a ULONG, DWORD or 32 bits long type.
js fatal_error_exit // if signed, the call has failed.

As Anton suggested, use the assembly generated by CL.EXE. DUMPBIN.EXE can disas the whole exec. And if the PDB file is present alongside the exec (in the same dir), you will get a disassembly with symbols, just like the ‘uf’ command in WinDbg, great.

Would this just compile ?

mov qword ptr rcx, 0h

This is probably better:

mov qword ptr [rcx], 0h

> Why don’t you want simply to disassemble C code and see how it translates to

assembly???

I did not look through your code thoroughly, but you seem to be passing function
parameters on the stack. Although it is OK to do so under 32-bit Windows where
API is based, IIRC, upon _stdcall convention (i.e the one where you pass all
parameters on the stack), doing it under 64-bit OS is not going to work, because
a callee expects to find first few parameters in registers ( which is true for
both Windows and UNIX-like systems, although the actual ways of how the
parameters are passed are different for MSFT and UNIX calling conventions)…

I know the calling conventions for 64 bit masm. There is only one fastcall

-> https://msdn.microsoft.com/en-us/library/ms235286.aspx

  1. Allocate stack space for the parameters that won’t be passed in registers.
  2. Align the stack pointer RSP on 16 byte boundary.
  3. Copy the 5th, 6th, ? arguments to the stack.
  4. Copy the first four arguments to the registers RAX, RDX, R8 and R9.
  5. Call the execute handler.

I have disassemble my C code, its the same as my MASM code…

mov DWORD PTR [rsp+80], 0
mov QWORD PTR [rsp+72], 0
mov DWORD PTR [rsp+64], 32 ; 00000020H
mov DWORD PTR [rsp+56], 0
mov DWORD PTR [rsp+48], 0
mov DWORD PTR [rsp+40], 128 ; 00000080H
mov QWORD PTR [rsp+32], 0
lea r9, QWORD PTR Iosb$[rbp]
lea r8, QWORD PTR ObjectAttributes$[rbp]
mov edx, 34603008 ; 02100000H
lea rcx, QWORD PTR FileHandle$[rbp]
call QWORD PTR NtCreateFile$[rbp]
mov DWORD PTR Status$[rbp], eax
; Line 125
mov eax, DWORD PTR Status$[rbp]
shr eax, 30
cmp eax, 3
jne SHORT $xxxxx@run_nt_nat
mov edx, DWORD PTR Status$[rbp]
lea rcx, OFFSET FLAT:??xxxxx@xxxxx@xxxxx@NtCreateFile?5FAILED?5?3?5status?5?$DN?50@
call printf
mov ecx, 3
call my_exit
$xxxxx@run_nt_nat:
; Line 126
mov eax, DWORD PTR Iosb$[rbp]
shr eax, 30
cmp eax, 3
jne SHORT $xxxxx@run_nt_nat
mov edx, DWORD PTR Iosb$[rbp]
lea rcx, OFFSET FLAT:??xxxxx@xxxxx@xxxxx@NtCreateFile?5FAILED?5?3?5Iosb?4Statu@
call printf
mov ecx, 3
call my_exit
$xxxxx@run_nt_nat:
; Line 148
lea rcx, OFFSET FLAT:??xxxxx@xxxxx@xxxxx@NtWriteFile?4?4?4?6?$AA@
call printf
; Line 149
mov QWORD PTR [rsp+64], 0
mov QWORD PTR [rsp+56], 0
mov eax, DWORD PTR MessageLength$[rbp]
mov DWORD PTR [rsp+48], eax
mov rax, QWORD PTR Message
mov QWORD PTR [rsp+40], rax
lea rax, QWORD PTR Iosb$[rbp]
mov QWORD PTR [rsp+32], rax
xor r9d, r9d
xor r8d, r8d
xor edx, edx
mov rcx, QWORD PTR FileHandle$[rbp]
call QWORD PTR NtWriteFile$[rbp]
mov DWORD PTR Status$[rbp], eax

> D. T.

xxxxx@gmail.com
Join Date: 16 Aug 2016
Posts To This List: 62
Masm 64 call native API (NtOpenFile/NtWrteFile)
This code may crash:

call rax ; rax is NtCreateFile
mov qword ptr rcx, 0h ; BOOOOOOOMMMMM!!!
cmp rcx, rax ; #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
jl fatal_error_exit

RCX is volatile. When NtCreateFile has returned, the content of RCX is
undefined, so accessing the address contained in RCX could cause an access
violation. And as the comment suggests, an error is a negative NTSTATUS, so you
should have:

call rax ; rax is NtCreateFile
test eax,eax ; NTSTATUS is a ULONG, DWORD or 32 bits long type.
js fatal_error_exit // if signed, the call has failed.

As Anton suggested, use the assembly generated by CL.EXE. DUMPBIN.EXE can disas
the whole exec. And if the PDB file is present alongside the exec (in the same
dir), you will get a disassembly with symbols, just like the ‘uf’ command in
WinDbg, great.

I dont need the content of RCX after NtCreateFile. I just put 0 in RCX to compare
the return of NtCreateFile (RAX) with 0 (cmp rax, 0 ; MASM dont like it).
See my disassambled C code. its the same :confused:

> Yesterday 19:15

D. T.
xxxxx@gmail.com
Join Date: 16 Aug 2016
Posts To This List: 62
Masm 64 call native API (NtOpenFile/NtWrteFile)
Would this just compile ?

mov qword ptr rcx, 0h

This is probably better:

Not realy ^

mov qword ptr [rcx], 0h ;

–> Exception thrown at 0x00007FF7D7A212E9 in masm64_ntdll.exe: 0xC0000005:
Access violation writing location 0x00007FF9F8A951C4.

mov qword ptr rcx, 0h

RAX?=?00000000C000000D RBX?=?00007FF9F89F0000 RCX?=?0000000000000000 RDX?=?0000000000000000 RSI?=?00007FF7A3594022
RDI?=?00007FF9F8B327DF R8 ?=?000000733755FB98 R9 ?=?000000733755FC00 R10?=?0000000000000000 R11?=?0000000000000246
R12?=?00007FF9F8B423B0 R13?=?00000000001399D0 R14?=?000000000014B295 R15?=?0000000000000000 RIP?=?00007FF7A35912F0
RSP?=?000000733755FBA0 RBP?=?000000733755FC00 EFL?=?00000246

>I have disassemble my C code, its the same as my MASM code…

You do realize what you are actually saying, right - it is,basically, “I’ve got two identical pieces of ASM code; however, one of them works and another does not; the whole thing is 100% reproducible and happens to be as predictable as a clock”.

Do you really think something like that may be feasible???

Anton Bassov

You have not written code to place a zero in RCX for use as a comparand. You have written code to write 0 to the qword at the address contained in rcx.

Good Luck.
Dave Cattley

if you want to make ecx 0 for comaprison
use mov ecx, 0 / mov rcx ,0 , xor ecx, ecx xor rcx rcx etc
do not write to bogus memory

ecx rcx is as DT said undefined and is a sure cause to crash

On 12/6/16, Dave Cattley wrote:
> You have not written code to place a zero in RCX for use as a comparand.
> You have written code to write 0 to the qword at the address contained in
> rcx.
>
> Good Luck.
> Dave Cattley
>
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list online at:
> http:
>
> MONTHLY seminars on crash dump analysis, WDF, Windows internals and software
> drivers!
> Details at http:
>
> To unsubscribe, visit the List Server section of OSR Online at
> http:</http:></http:></http:>

> mov qword ptr rcx, 0h

Ok this instruction does compile but it is not needed. To check for a NULL returned value do the following:

call RAX; RAX is loaded with GetProcessAddress
test RAX, RAX; if RAX is loaded with 0, the 0 flag bit is set by the test instruction
je _GetProcAddress_Failed; jump to the error Handler if GetProcAddress returned NULL