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 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.
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 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.
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.
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.
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.
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.
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.
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 guess I need some assembly homework. I don't understand anything mineiro said nor anything about the posted code. Is it really masm32 stuff?
Hi deeR44,
Can you examine mineiro under Ollydbg? This can help you a lot to study the code.
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.
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
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.
I am not sure of your point here, the world is full of things that many people don't understand.
> I only see a bizarre program that accomplishes absolutely nothing.
It is probably the case that your value judgement about what and why the code was posted is not something you understand, many people write test code or demo code and there is no guarantee that many others will grasp what it is but they usually do and with a complex subject, this is nothing abnormal.
Quote...In linux, main entry point don't start at static address 401000h if we choose Position Independent Code...
You may be correct, since Linux was mentioned. I tried the version that mineiro said runs on Windows and all it did was call a procedure with an argument and the procedure returned the argument it received in a register. Now I may not understand something that complex as you pointed out, but that doesn't help me understand all the strange code in the program to accomplish that.