flat assembler
Message board for the users of flat assembler.

Index > Windows > why eax==-1?

Goto page 1, 2, 3  Next
Author
Thread Post new topic Reply to topic
yinke



Joined: 07 Jan 2010
Posts: 7
yinke
Code:
format pe gui
include 'win32ax.inc'
entry start

section '.data' data readable writeable
fileName db 'E:\text.exe',0
hFile dd ?

section '.code' code readable executable
start:
invoke CreateFileA,fileName,GENERIC_READ or GENERIC_WRITE ,\
FILE_SHARE_WRITE,\
NULL,OPEN_EXISTING,0,0
cmp eax,INVALID_HANDLE_VALUE
jz lppt

lppt:
ret


section '.import' import data readable
library kernel32,'kernel32.dll'
include 'api\kernel32.inc'    

why eax==-1
Post 09 Jan 2010, 09:15
View user's profile Send private message Reply with quote
bitshifter



Joined: 04 Dec 2007
Posts: 764
Location: Massachusetts, USA
bitshifter
Are you reading or writing?
Code:
GENERIC_READ or GENERIC_WRITE    


To read a file that exists already...
Code:
invoke  CreateFileA,fileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL    


To write a file that may or may not exist already...
Code:
invoke  CreateFileA,fileName,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL    


Also use invoke ExitProcess,0 instead of ret

Hope that helps Smile
Post 09 Jan 2010, 09:48
View user's profile Send private message Reply with quote
Teehee



Joined: 05 Aug 2009
Posts: 568
Location: Brazil
Teehee
also use section .data at bottom. Some antivirus got virus alerts if you let it at top. Smile

_________________
Sorry if bad english.
Post 09 Jan 2010, 09:55
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7782
Location: Kraków, Poland
Tomasz Grysztar
bitshifter wrote:
Also use invoke ExitProcess,0 instead of ret

That's not so good advice. Ending program with RET is perfectly legal in this case.
Post 09 Jan 2010, 12:51
View user's profile Send private message Visit poster's website Reply with quote
Pirata Derek



Joined: 31 Oct 2008
Posts: 259
Location: Italy
Pirata Derek
I'm agree with tomasz:

Automatically at application start, system sets the ESP pointing an offset to a kernel.dll library routine that terminates the thread (and so, the process)

the RET instruction will jump in that routine and the application execution is stopped.
Post 09 Jan 2010, 13:10
View user's profile Send private message Send e-mail Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3170
Location: Denmark
f0dder
Tomasz and Pirata: that is depending on undocumented behavior. While not very likely to ever break, this is a pretty bad idea.

If you were linking against libc and using main/winmain, it'd be perfectly fine & documented... but that's a different story.
Post 09 Jan 2010, 13:29
View user's profile Send private message Visit poster's website Reply with quote
Pirata Derek



Joined: 31 Oct 2008
Posts: 259
Location: Italy
Pirata Derek
Yes, but documented or not it don't care:

why don't you assemble this simple program and, debug it with IDA pro and trace the execution after the RET?

maybe you find the operating system mechanism that close this process/thread, without problems.....

PLEASE: check the NtTerminateProcess and NtClose
(from XP to seven the mechanism is different)
Post 09 Jan 2010, 13:48
View user's profile Send private message Send e-mail Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7782
Location: Kraków, Poland
Tomasz Grysztar
f0dder: when you create a thread, it is called as a function you can return from, and it is perfectly documented. Since there is nowhere stated that the main application thread is somehow different from the other threads in this aspect, I assume this means we can take this behaviour to be documented.
Post 09 Jan 2010, 14:01
View user's profile Send private message Visit poster's website Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3170
Location: Denmark
f0dder
Pirata: I know how the stuff works, thank you - but it's still not documented. Just like some people thought they could get away with PE executable with no imports because "kernel32.dll is always injected"... well, try that on win2k.

Tomasz: documented for usermode thread creation functions, yes. But how your PE entrypoint is reached isn't documented - neither is it documented whether the executable loading is done in kernel or usermode. I think it's fairly safe MS isn't going to change the mechanics of the PE loader anytime soon, but depending on undocumented functionality tends to lead to breakage sooner or later.

And it's not like ExitProcess takes a lot of space in the import table, that the call takes lot of space or incurs measurable overhead compared to "ret", so you might as well play it safe unless you're writing 4kb intros Smile
Post 09 Jan 2010, 16:37
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7782
Location: Kraków, Poland
Tomasz Grysztar
I think that main thread should not be discriminated from the other threads in such a way. No matter what creates it, it should behave the same. My opinion is: since it is not stated that this thread (though created through different mechanism) behaves differently than the ones you create yourself, we can assume it behaves the same, including the RET behaviour.
Well, it seems a little like interpreting the law. Very Happy Anyway, that's my opinion - unless they document clearly that the main thread is different from the other threads in such a way, that it cannot be exited with RET, it's a perfectly valid assumption that it behaves just like any other. I would even argue, that we should be exiting the main thread with "RET 4". Wink
Post 09 Jan 2010, 17:01
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
In Windows Super Sky 9 not calling ExitProcess could left the process in zombie state? Razz (don't remember if this state is implemented on Windows)
Post 09 Jan 2010, 18:40
View user's profile Send private message Reply with quote
Pirata Derek



Joined: 31 Oct 2008
Posts: 259
Location: Italy
Pirata Derek
The only thing i can tell to you is:

If you end a process or thread with RET and follow the execution (with a debugger), you give always the same RESULT:
The Process / Thread EXITS WITHOUT ANY KIND OF ERRORS.

I've done that about 20 times in many PEs.

This pratical consideration should answer at all, until you can prove the opposite case.
Post 09 Jan 2010, 19:45
View user's profile Send private message Send e-mail Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3170
Location: Denmark
f0dder
Tomasz: Windows internals are not documented by MS - you aren't told if the main thread is created with CreateThread, CreateRemoteThread, ZwCreateThread, or something completely different. You're relying on the documentation of user-mode CreateThread. I don't have the DDK documentation handy right now, so I can't look up ZwCreateThread, but you can be pretty sure it doesn't lead to the same KERNEL32.DLL code that CreateThread does Razz

It's the same kind of reasoning that leads to "Windows uses file mappings for the executable - I should be able to UnmapViewOfFile on my BaseAddress, then" - which works on some Windows versions and not others... You know part of the story, and some of it might even be partially documented - but you really shouldn't extrapolate from this.

LocoDelAssembly wrote:
In Windows Super Sky 9 not calling ExitProcess could left the process in zombie state? Razz (don't remember if this state is implemented on Windows)
It's not likely to happen in this example, but you don't have any guarantee it won't. It's mainly the mindset in general I'm against, but considering it costs you next to nothing to do things properly, then why not do it? If you do Windows development you should be following The Old New Thing, and if you do that you really should cringe whenever you see people depending on undocumented behavior Smile

Piara Derek wrote:
This pratical consideration should answer at all, until you can prove the opposite case.
The same logic leads to "I've been struck by lightning 3 times, it's not something that kills you" or "I've done 100 acid trips, it's not dangerous to anyone". See your flaw? For something a bit more "realistic", I point you back to the PE-with-no-imports example... it works on all the Windows versions I tested - except Windows 2000. The precise rule on that OS is "you must end up importing from KERNEL32.DLL" - thus importing your own "null.dll" isn't good enough, but importing GDI32.DLL is since it ends up importing from KERNEL32.DLL (but you really shouldn't depend on that either, because it's not documented as a part of GDI32 Smile). This DLL dependency isn't documented as a requirement, but it still goes to show that there are differences between Windows versions, even for something so fundamental and "that'll never change!".
Post 09 Jan 2010, 20:16
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7782
Location: Kraków, Poland
Tomasz Grysztar
f0dder wrote:
Tomasz: Windows internals are not documented by MS - you aren't told if the main thread is created with CreateThread, CreateRemoteThread, ZwCreateThread, or something completely different. You're relying on the documentation of user-mode CreateThread. I don't have the DDK documentation handy right now, so I can't look up ZwCreateThread, but you can be pretty sure it doesn't lead to the same KERNEL32.DLL code that CreateThread does Razz

There's nowhere said that the main thread is different from the other threads, and for the sake of this argument it doesn't really matter how it is created. If you couldn't rely on it being "thread" just like any other is, you couldn't even use ExitThread and be sure that it would work with it.
It really doesn't matter to me, whether it is CreateThread used to create it, or some custom kernel code - however what matters to me, is that it is still called "thread", and since there is nowhere stated that it is something different from the other ones, I feel obligated to treat it no differently than others. The fact how it was created should be transparent to the programmer.
Post 09 Jan 2010, 20:25
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
Tomasz, but you are using RET from ThreadProc right? So, what is documented is that you can simply RET from it without calling ExitThread. In the entry-point however, where are you told that there was some ThreadProc that called the entry-point or even the entry-point is a ThreadProc so you can just do RET?
Post 09 Jan 2010, 20:38
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7782
Location: Kraków, Poland
Tomasz Grysztar
I am nowhere told that ThreadProc is something applied only to thread created with CreateProcess. I treat it as something more general, that you have to have in mind when using CreateProcess, but should be true for all threads.
Post 09 Jan 2010, 21:06
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
CreateProcess=CreateThread?

Code:
DWORD WINAPI ThreadProc(
  __in  LPVOID lpParameter
);    


What I mean is that you rely on the fact that you can return from ThreadProc, but since the entry point is NOT documented as ThreadProc, how do you conclude that RET will be always safe? (which should be "RET 4" if the "main" thread is even more equal to all other threads)

And another problem, doing just RET will be equivalent to ExitProcess, TerminateProcess or neither of both?

MSDN wrote:
If one of the terminated threads in the process holds a lock and the DLL detach code in one of the loaded DLLs attempts to acquire the same lock, then calling ExitProcess results in a deadlock. In contrast, if a process terminates by calling TerminateProcess, the DLLs that the process is attached to are not notified of the process termination. Therefore, if you do not know the state of all threads in your process, it is better to call TerminateProcess than ExitProcess. Note that returning from the main function of an application results in a call to ExitProcess.
( http://msdn.microsoft.com/en-us/library/ms682658%28VS.85%29.aspx )
Post 09 Jan 2010, 21:42
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7782
Location: Kraków, Poland
Tomasz Grysztar
LocoDelAssembly wrote:
CreateProcess=CreateThread?

Yes, my mistake.

LocoDelAssembly wrote:
What I mean is that you rely on the fact that you can return from ThreadProc, but since the entry point is NOT documented as ThreadProc, how do you conclude that RET will be always safe?

The fact that entry point is not documented to make thread with CreateThread doesn't mean it does not create a thread - it does. And my assumption is, since not told otherwise, that all threads are the same, thus I conclude that all threads have the ThreadProc-like structure, and the fact that you are told to use it with CreateThread is just a natural consequence of this fact. I simply exploit the fact that the documentation is incomplete here, and in my interpretetation (again - this starts to look a bit like interpreting the law by judge, etc.) the only logical conclusion is that every thread should be ThreadProc-like, because otherwise we would have some discrimination that would have no explanation in documentation (and I would consider that a bug).

LocoDelAssembly wrote:
And another problem, doing just RET will be equivalent to ExitProcess, TerminateProcess or neither of both?

Doing just RET should be equivalent to ExitThread only. It's a common behaviour to all threads, and hence also a logical conclusion from my above reasoning.
Post 09 Jan 2010, 22:05
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
Quote:

the only logical conclusion is that every thread should be ThreadProc-like

But then, why it is not "RET 4", as being a stdcall entry you should restore the stack?

Also note that the documentation mentions in some parts "main thread" (in CreateProcess, for example), so it is not clear why all threads should start the same way to me.

On the other hand there is something that could be backing you:
MSDN wrote:
How Processes are Terminated

A process executes until one of the following events occurs:

* Any thread of the process calls the ExitProcess function. Note that some implementation of the C run-time library (CRT) call ExitProcess if the primary thread of the process returns.
* The last thread of the process terminates.
* Any thread calls the TerminateProcess function with a handle to the process.
* For console processes, the default console control handler calls ExitProcess when the console receives a CTRL+C or CTRL+BREAK signal.
* The user shuts down the system or logs off.
However, it could be referring to the case of calling ExitThread/TerminateThread for the "main thread" exclusively and doing "RET 4" or ExitThread/TerminateThread in the others.
Post 09 Jan 2010, 22:36
View user's profile Send private message Reply with quote
yinke



Joined: 07 Jan 2010
Posts: 7
yinke
thank you
Post 10 Jan 2010, 04:10
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2, 3  Next

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.