News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

NULL pointer

Started by mineiro, September 15, 2020, 07:58:28 PM

Previous topic - Next topic

mineiro

Can I create a pointer to zero?
When using invoke with proto I face some problems.
Some functions accept a pointer to some function address or NULL if that is not being used. So, I need change prototype to use invoke wich is not a good pratice.
I was thinking if you guys know some way to bypass that.
Follow a code:

;uasm -elf64 -pie test2.uasm
;ld test2.o -o test2
;./test2 ; echo $?

.X64
option casemap:none

;null.uasm(22) : Error A2245: Invalid symbol type in expression: NULL
;null.uasm(22) : Error A2147: Too few arguments to INVOKE: nullptr
NULL macro
org 0
NILL label qword
exitm <offset NILL>
endm

;NULL equ 0      ;Error A2145: INVOKE argument type mismatch: argument 1

nullptr proto :ptr

.code

_start:

invoke nullptr,NULL     ;return code
invoke nullptr,addr NULL         ;dont work too
mov rax,60  ;sysexit
syscall


nullptr proc p_something:ptr
mov rdi,p_something
ret
nullptr endp

end _start

I'd rather be this ambulant metamorphosis than to have that old opinion about everything

hutch--

I would be inclined to look up the documentation (if it exists) on the function to see what the options were. Depending on how it was written, some functions in C take either an address OR a 0 to indicate that no address is being passed. Passing the ADDRESS of 0 is almost exclusively an error.

mineiro

Quote from: hutch-- on September 15, 2020, 08:55:43 PM
Depending on how it was written, some functions in C take either an address OR a 0 to indicate that no address is being passed.
Thank you sir hutch for answering. Yes, is this.
How can I do that? Invoke is checking for function prototypes about parameters types, and pass a zero instead of a pointer is giving me errors. So, how can I do like a void pointer to bypass checking?
I think in pass address zero, that is the same as passing unsigned 0 just to avoid rewrite a lot of functions prototype.
I can change "proto :ptr" to "proto :qword" or simply vararg to accept any number. Create a macro to not check function parameter types. But, using invoke is my point.
From glib types and constants, I get that FALSE=0, TRUE=!FALSE (I'm using 1), NULL = void pointer. So theres a difference between FALSE and NULL.
I'd rather be this ambulant metamorphosis than to have that old opinion about everything

hutch--

I don't understand how args are passed in Linux but if it is possible, try writing the code manually instead of using invoke. If its anything like Win64 you write the first arguments directly in registers and any further arguments at the correct locations on the stack. It very messy to do but that may get you around the invoke problem.

mineiro

Thank you again sir.
Like in windows, this question can also fit in masm32 too. This question can be in 32 or 64 bits, masm, uasm, jwasm,casm, ... .
I create a noob macro just to easy typing, but was thinking if you guys know a better way.

gpointer            g_object_new                        (GType object_type, const gchar *first_property_name,...);
In this function, first parameter is required, second is optional and its a pointer to a string.
I'd rather be this ambulant metamorphosis than to have that old opinion about everything

hutch--

Well, in a macro you can usually set a default argument if one is not provided or if the inserted argument is of the wrong type.

Adamanteus

  Looks like is need begin from theory  : NULL - not existing in program address (zero address is OS - so, not in program).
Pointer on not existing in program address could be, but the name NULL is reserved for value - 0.
In macro NULL - that is need to raname, you've made pointer NILL labeled current code, where called macro - so, it in program.

mineiro

hello sir Adamanteus; how are you, I hope fine.
I suppose to understand your comment. Let me explain.
In assembly language we don't have barriers. We control machine.
O.S. designers do O.S. based in machine allright. Adress 0 is the first memory address, being data or code, even knowing that boot starts in real mode code at offset 7c00h but segment 0.
I have tried your tips, imagebase + imagerel (400000h+1000h)(works in linux) imposed by O.S., output is zero but I think is fake because org 0 point to _start (rip). Have tried others variations like org -401000, org 0-401000h and remaping start point to 401000h without luck. Do you have a solution?
I only like to bypass (send number 0) to invoke while checking to ptr. I'm receiving error.
If I try to point to non existing address, you know, SEH, VEH, ..., or just address 0.
Thank you.
I'd rather be this ambulant metamorphosis than to have that old opinion about everything

TouEnMasm

Quote
In assembly language we don't have barriers. We control machine.
I don't agree with that.Barrier is exceptions (a lot),Barrier is prompt(You are not allowed to do that).
Barrier is signed.You need to signe your application (for example a file sys ).
Is there barriers who don't apply to asm,I don't know.

Fa is a musical note to play with CL

mineiro

Thank you sir's for answers, I continued trying.

This sounds possible, but I'm trying to find a more elegant way to do:

;uasm -elf64 -pie null.uasm
;ld null.o -o null
;./null ; echo $?

.X64
option casemap:none
nullptr proto :ptr

.code
org 0000000000000000h
NULL::

_start:
;address will be rip register + offset
invoke nullptr,addr NULL-401000h     ;401000h = program entry point
invoke nullptr,addr _start-401000h
;invoke nullptr,addr _start-_start      ;don't work
;invoke nullptr,addr rip-$                  ;don't work, tried $-rip too
mov rax,60                                      ;sysexit
syscall


nullptr proc p_something:ptr
mov rdi,p_something
ret
nullptr endp

end _start
I'd rather be this ambulant metamorphosis than to have that old opinion about everything

deeR44

I guess I need some assembly homework. I don't understand anything mineiro said nor anything about the posted code. Is it really masm32 stuff?

Vortex

Hi deeR44,

Can you examine mineiro under Ollydbg? This can help you a lot to study the code.

mineiro

Thank you sir Vortex.
Hello sir deeR44, well, let me try to explain whats happening:
Code below works in windows 32 bits, using masm32,uasm32, jwasm
;32 bits windows program

;ml /c /Cp /coff nullptr.asm
;jwasm /coff /Cp nullptr.asm
;uasm32 /coff /Cp nullptr.asm

;link /subsystem:console /out:null.exe nullptr.obj ;Microsoft (R) Incremental Linker Version 8.00.40310.39
;Microsoft (R) Incremental Linker Version 5.12.8078
;null | echo %errorlevel% ;execute program null and echo error code

include \masm32\include\masm32rt.inc

myproc proto :ptr

    .code
start:
invoke myproc,NULL ;MASM32 accepts NULL as being a pointer
    invoke ExitProcess,eax ;EAX== error code, should be 0 because "NULL EQU 0"
   
myproc proc someaddress:ptr

mov eax,someaddress
ret

myproc endp

end start

If you perceive, we can use invoke with a static number instead of an address thats expected by function prototype. So, this can be an error or not, depend of our point of view.

Now, if you try this with ml64, you will perceive that does not exist prototypes checking, so, no invoke. That's the Hutch answer; do that by hands or create an invoke macro.
kernel32.def
;lib /MACHINE:AMD64 /DEF:kernel32.def
LIBRARY kernel32.dll
EXPORTS
ExitProcess


nullptr64.asm
;64 bits masm windows program

;ml64 /c nullptr64.asm ;Microsoft (R) Macro Assembler (AMD64) Version 8.00.40310.39
;link /SUBSYSTEM:CONSOLE /machine:AMD64 nullptr64.obj ;Microsoft (R) Incremental Linker Version 8.00.40310.39
;nullptr64 | echo %errorlevel% ;execute program null and echo error code

option dotname
option casemap:none

library macro lib_name:REQ
                includelib <&lib_name.lib>
endm

;;experimental stage
import macro function_name:req
name TEXTEQU <__imp_&function_name>
;EXTERNDEF name:
EXTERNDEF function_name: PROTO
endm

library kernel32
        import ExitProcess

NULL equ 0

.code
public start
start:

sub rsp,28h ;shadow space, align stack

mov rax,NULL ;not following windows calling convention here, this procedure is internal to this program
call myproc

;error code in rcx register
call ExitProcess ;following windows calling convention here, first parameter is stored in rcx register


myproc proc
mov rcx,rax
ret
myproc endp

ALIAS <mainCRTStartup>=<start>         ;;console
;ALIAS <WinMainCRTStartup>=<start>      ;;windows gui
end



If we try that using uasm64, things works as before with few modifications.
I found a mistake in uasm when trying this, look below:
nulptr64.asm
;64 bits windows program
;uasm64 -win64 nulptr64.asm
;link /SUBSYSTEM:CONSOLE /machine:AMD64 nulptr64.obj ;Microsoft (R) Incremental Linker Version 8.00.40310.39
;nulptr64 | echo %errorlevel% ;execute program null and echo error code

.X64
option casemap:none
option win64:7

includelib kernel32.lib

ExitProcess proto :dword
myproc proto :ptr

NULL equ 3 ;should be 3 instead of 0, have tried with -nomlib comand line switch too
nada equ 3 ;ok

.code
public start
start:
invoke myproc,3 ;return 3 in rcx
invoke myproc,nada ;return 3 in rcx
invoke myproc,NULL ;return 0 in rcx, should be 3
    invoke ExitProcess,ecx

myproc proc someaddress:ptr
mov rcx,someaddress ;ambiguous
ret
myproc endp

end start

So, uasm64 internally is ignoring NULL value at some place.
But, the point here is: no assembler is checking to address in prototype. Should be an address offset or pointer, but we are inserting a static number and thats bypassing protoype checking.

-----------------------------------------------------------------------------------------
now, try this on linux, supose you're trying to port that simple program to linux.
First you need find a correlate to ExitProcess function, check calling convention of both O.S. and try to find a common way to work. So:
;uasm -elf64 -pie null.uasm
;ld null.o -o null
;./null ; echo $?

.X64
option casemap:none
myproc proto :ptr

.code
public _start
_start:
;both lines below dont work, so I comment that
invoke myproc,NULL  ;Error A2145: INVOKE argument type mismatch: argument 1 ;;;I don't have declared NULL
invoke myproc,0     ;Error A2145: INVOKE argument type mismatch: argument 1

;rdi=error code
mov rax,60  ;sysexit==ExitProcess
syscall

myproc proc someaddress:ptr
mov rdi,someaddress        ;ambiguous
ret
myproc endp
end _start

So, this is the problem. While on windows assemblers don't check ":ptr" in function prototype, in linux uasm is checking. To me this is right. So, how can I "address 0" to bypass function prototype checking by invoke.
After reading Adamanteus comment give to me some ideas, and after read TouEnMasm comment ("barrier is signed") some light happens in my mind.
So, the way I found was get program entry point and subtract from that entry point address. Sounds ambiguous, I know, but that was my solution to pass "zero"(NULL) without receiving errors.
I'd rather be this ambulant metamorphosis than to have that old opinion about everything

mineiro

So, this was the way I found:
NULL equ (offset main-$ and 0)
In linux, main entry point don't start at static address 401000h if we choose Position Independent Code (PIC), even because elf function table (plt)(procedure linkage table) comes before main entry point, so that address varies a lot.
;uasm -elf64 win.uasm
;gcc win.o -o win -no-pie -lc
;./win ; echo $?

.X64
option casemap:none

exit proto status:dword
myproc proto :ptr

NULL equ (offset main-$ and 0)

.code
public main
main proc argc:dword,argv:ptr
local _argv:ptr
local _argc:dword

mov _argc,argc
mov _argv,argv

invoke myproc,NULL

;--------------
;invoke exit,eax
;--------------
ret
;--------------
main endp

myproc proc someaddress:ptr
mov rax,someaddress
ret
myproc endp

end main
I'd rather be this ambulant metamorphosis than to have that old opinion about everything

deeR44

QuoteHello sir deeR44, well, let me try to explain whats happening:
Code below works in windows 32 bits, using masm32,uasm32, jwasm

No need to explain. I only see a bizarre program that accomplishes absolutely nothing. At least under Windows 10 Pro. Perhaps under other assemblers and operating systems, but I am unfamiliar with any of them.