Hello everybody,
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
I am new to the forum, I registered because I found a lot of information on osronline, thank you for sharing
Sorry for my English. From Paris with love
ASM code:
OPTION CASEMAP:none
EXTERN ApiLookup: PROC
PUBLIC ntDllTest
OBJECT_ATTRIBUTES STRUC QWORD
oLength DWORD ? ; 4
DWORD ? ; 4
RootDirectory QWORD ? ; 8
ObjectName QWORD ? ; 8
Attributes DWORD ? ; 4
DWORD ? ; 4
SecurityDescriptor QWORD ? ; 8
SecurityQualityOfService QWORD ? ; 8 => Intra-structure alignment OK
OBJECT_ATTRIBUTES ENDS ; => Inter-structure alignment, total 48 and largest memeber size 8. 48 mod 8 = 0 OK
IO_STATUS_BLOCK struct QWORD
UNION u
Status DWORD ?
Pointer QWORD ?
ENDS
Information QWORD ?
IO_STATUS_BLOCK ends
UNICODE_STRING STRUC QWORD
woLength WORD ?
MaxLength WORD ?
DWORD ?
Buffer QWORD ?
UNICODE_STRING ENDS
.data
ntdll db “NTDLL.DLL”,0
NtCreateFile db “NtCreateFile”,0
NtWriteFile db “NtWriteFile”,0
NtClose db “NtClose”,0
NtOpenFile db “NtOpenFile”,0
NtReadFile db “NtReadFile”,0
align 16 ; There seems to be a problem in Win2k (at least) when api function is called to use unicode.
; Under certain conditions, if the unicode line isn’t word-aligned then function fails.
; Reading loaded file data posed no problem because the system will always load it onto the
; correct boundary. But the alignment of any given .DATA entry is based on what’s ahead of it.
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
align 8
Message db “Hello world! I was written using dos syscall mouhahahahahaha…”;,0;, 0,0,0,0,0;,0,0,0
align 16
UnicodeFile UNICODE_STRING <>
align 16
ObjA OBJECT_ATTRIBUTES <>
align 16
Iosb IO_STATUS_BLOCK <>
.data?
buff db 128 dup(?) ; read if write works …
hFile dq ?
.code
ntDllTest PROC
;=== start prolog
;mov [rsp + 20h], r9 ; save the first four parameters on the stack in the shadow space allocated by caller
;mov [rsp + 18h], r8
;mov [rsp + 10h], rdx
;mov [rsp + 8h], rcx
;push r15 ; saves any non-volatile registers that plans to use during this function execution
;push r14
;push r13
sub rsp, 0Bh * 8h; + 8h ; called function with the maximum number of parameters * 8 => 11 * 8 + 8 to aligne stack on 16 bit (api call need it)
lea rbp, [rsp + 60h] ; establishes a frame pointer that points 128 bytes into the fixed allocation area
; 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
mov ObjA.oLength, 30h ; sizeof(OBJECT_ATTRIBUTES)
mov ObjA.RootDirectory, 0h ; NULL
mov ObjA.Attributes, 40h ; OBJ_CASE_INSENSITIVE
lea rax, UnicodeFile
mov ObjA.ObjectName, rax ; &UnicodeFilespec;
mov ObjA.SecurityDescriptor, 0h ; NULL;
mov ObjA.SecurityQualityOfService, 0h ; NULL;
; get address of NtCreateFile
lea rdx, NtCreateFile
lea rcx, ntdll
call ApiLookup
cmp rax, 0
jz fatal_error_exit
; create file
mov dword ptr [rsp + 50h], 0h ; Length of the EA buffer.
mov qword ptr [rsp + 48h], 0h ; Pointer to an EA buffer used to pass extended attributes.
mov dword ptr [rsp + 40h], 20h ; FILE_SYNCHRONOUS_IO_NONALERT
mov dword ptr [rsp + 38h], 5h ; FILE_OVERWRITE_IF
mov dword ptr [rsp + 30h], 0h ; The type of share access that the caller would like to use in the file
mov dword ptr [rsp + 28h], 80h ; FILE_ATTRIBUTE_NORMAL
mov qword ptr [rsp + 20h], 0h ; The initial allocation size in bytes for the file
lea r9, Iosb ; A pointer to a variable that receives the final completion status and information about the requested operation.
lea r8, ObjA ; A pointer to a structure already initialized with InitializeObjectAttributes.
mov edx, 2100000h ; MAXIMUM_ALLOWED | SYNCHRONIZE
lea rcx, hFile ; A pointer to a variable that receives the file handle if the call is successful.
call rax
;mov r10, rcx
;mov eax, 55h
;push rbp ; dummy … (this => ntdll => syscall, 16 byte aligne stack + 8 ret ntdll)
;syscall
;pop rbp
shr eax, 1Eh ; #define NT_ERROR(Status) ((((ULONG)(Status)) >> 30) == 3)
cmp eax, 3
jz fatal_error_exit
cmp hFile, 0
jz fatal_error_exit
; get address of NtWriteFile
lea rdx, NtWriteFile
lea rcx, ntdll
call ApiLookup
cmp rax, 0
jz fatal_error_exit
; write into
mov qword ptr [rsp + 40h], 0h ; key
mov qword ptr [rsp + 38h], 10h ; byte offset
mov dword ptr [rsp + 30h], 64d ; length
mov rcx, offset Message
mov qword ptr [rsp + 28h], rcx ; ptr to data buffer
lea rcx, Iosb
mov qword ptr [rsp + 20h], rcx ; IOSB address
xor r9, r9 ; APC context
xor r8, r8 ; APC entry point
xor rdx, rdx ; event Handle
mov rcx, hFile ; file Handle
call rax
mov qword ptr rcx, 0h
cmp rcx, rax ; #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
jl fatal_error_exit ; jl ? jump if less than, if second parameter is less than the first
; get address of NtClose
lea rdx, NtClose
lea rcx, ntdll
call ApiLookup
cmp rax, 0
jz fatal_error_exit
; close file
mov rcx, hFile ; file Handle
call rax
fatal_error_exit:
mov rax, 0DEADBEEFh
;=== start epilogue
lea rsp, [rbp - 80h] ; trim the stack to its fixed allocation
add rsp, 8h * 0Bh ;+ 8h ; deallocate the fixed part of the stack
;pop R13 ; restore any non-volatile registers that used during this function execution
;pop R14
;pop R15
ret ; return control to the caller
ntDllTest ENDP
end
================================================================================
I can also share my C code who works perfect (Create file/write into/close/reopen/read/close).
thank you in advance for your help