I'm beginning with win32asm, and having trouble using fputs and fgets from win32 asm code.

In *nix, I believe I can just do:
push 1 ; stdout
push msg
call fputs

But when I try similar code in Windows (using call _fputs), nothing happens.
I believe this is because Windows doesn't initialize 0,1, and 2 to stin, stdout, and stderr :-(
I've seen complicated code that initializes these with GetStdHandle, but it's beyond my comprehension now...

So, my question, is: Is there a simpler way to initialize these, or use STDIN, from win32asm console apps?
Can I do these in C, and then call the code from win32asm?
Can Cygwin do this for me, somehow?
Failing that, is there a simple way I can just include some asm which will set these up for me?

Thanks.
Posted on 2009-05-08 12:56:56 by srobertjames
- You need your .exe to be a console executable
- Push your string, call the puts function in MSVCRT.DLL
- It works.

Which assembler are you using?
Posted on 2009-05-08 14:11:39 by ChaperonNoir
you can simply use AllocConsole() and GetStdHandle(STD_OUTPUT_HANDLE), then use WriteFile() with the returned file-handle. This is when you didn't link your app as a console-app.
Funcs for reading and writing strings will need to be coded by you, they're simple.
Posted on 2009-05-08 14:54:12 by Ultrano
I'm using NASM.  Console mode app.

I'd like to use the standard C functions like fputs, since I'm a lot more familar with those than with MS-specific ones like WriteFile().
Posted on 2009-05-08 18:11:20 by srobertjames
It's worth knowing that Windows uses a common subsystem for all kinds of IO.
You can effectively use the same api to write to file handles, socket handles, pipes, etc.
For example, WriteFile will work with any/all of these IO handles.
Posted on 2009-05-08 20:35:54 by Homer
There is function you can call in MSVCRT that returns a pointer to FILE* stdin / STDOUT / STDERR. I have the code around somewhere, it's something like _iob_func or something like that.

It's really easy to use the C runtime functions from Assembly. Really really easy. fgets, fopen, puts, printf, fprintf, remove, everything works and it's easy to use.

If you want to work with the STDIN stream, why don't you just use gets() and functions like that where you don't need to specify the stream.
http://www.cplusplus.com/reference/clibrary/cstdio/scanf/
Posted on 2009-05-08 21:14:50 by ChaperonNoir
Hi srobertjames,

Here is an example for you :


.386
.model flat, stdcall
option casemap:none

include    \masm32\include\windows.inc
include    \masm32\include\kernel32.inc

includelib  \masm32\lib\kernel32.lib
includelib  \masm32\lib\msvcrt.lib

fputs      PROTO C :DWORD,:DWORD
__p__iob    PROTO C

_iobuf STRUCT
    _ptr        DWORD ?
    _cnt        DWORD ?
    _base      DWORD ?
    _flag      DWORD ?
    _file      DWORD ?
    _charbuf    DWORD ?
    _bufsiz    DWORD ?
    _tmpfname  DWORD ?
_iobuf ENDS

FILE TYPEDEF _iobuf

.data

msg        db 'This is a test.',0

.data?

stdout      dd ?
stdin      dd ?
stderr      dd ?

.code

start:

    call    __p__iob
   
    mov    stdin,eax          ; #define stdin  (&__iob_func()[0])
    add    eax,SIZEOF(FILE)
    mov    stdout,eax          ; #define stdout (&__iob_func()[1])
    add    eax,SIZEOF(FILE)
    mov    stderr,eax          ; #define stderr (&__iob_func()[2])
   
    invoke  fputs,ADDR msg,stdout       
    invoke  ExitProcess,0

END start
Attachments:
Posted on 2009-05-09 06:01:34 by Vortex

If you want to work with the STDIN stream, why don't you just use gets() and functions like that where you don't need to specify the stream.

Because gets() is a *major* security vulnerability.  Any code using gets() is vulnerable.  Never use gets().  Erase it's definition from your include files.

fgets(), on the other hand, lets you specify a count.  But you also need to specify STDIN or the stream handle, which is suprisingly not obvious how to do in Windows.
Posted on 2009-05-09 23:10:07 by srobertjames

Hi srobertjames,

Here is an example for you :


    mov     stdin,eax           ; #define stdin  (&__iob_func()[0])
    add     eax,SIZEOF(FILE)
    mov     stdout,eax          ; #define stdout (&__iob_func()[1])
    add     eax,SIZEOF(FILE)
    mov     stderr,eax          ; #define stderr (&__iob_func()[2])



Neat! Any similar version that will work with NASM + gcc? (That's what I'm using to assemble / link).
Posted on 2009-05-09 23:18:31 by srobertjames
Use GetStdHandle to retrieve std io handles.
I know it seems a little obtuse.
Posted on 2009-05-09 23:23:01 by Homer
Hi srobertjames,

You can translate the Masm code to Nasm. It should work for you.
Posted on 2009-05-10 04:22:27 by Vortex
This code should link with crtdll.lib
extern __imp__iob

main:
push esi
mov  esi,[__imp__iob]
%define stdin 
%define stdout
%define stderr

lea eax,stdout
cinvoke fputs, "hello", eax
invoke _getch
pop esi
ret
Posted on 2009-05-10 05:57:08 by sapero


If you want to work with the STDIN stream, why don't you just use gets() and functions like that where you don't need to specify the stream.

Because gets() is a *major* security vulnerability.  Any code using gets() is vulnerable.  Never use gets().  Erase it's definition from your include files.

fgets(), on the other hand, lets you specify a count.  But you also need to specify STDIN or the stream handle, which is suprisingly not obvious how to do in Windows.


Vulnerable is a big word.  How exactly do you think you can take control of the target program using a buffer overflow. You can make the app crash or malfunction but that's all.
You could just use the safe versions of the CRT apis :
http://msdn.microsoft.com/en-us/library/5b5x9wc7(VS.80).aspx
gets_s for example let's you specify a size for the console input. But by now I'm sure you've found your solution.


Posted on 2009-05-10 09:57:37 by ChaperonNoir
Try NASMX ;)
Posted on 2009-05-11 10:17:05 by SpooK
Hi srobertjames,

Here is an example for reading and writing to console in NASM

Klod
Attachments:
Posted on 2010-01-04 21:32:12 by Klod
Vulnerable is a big word.  How exactly do you think you can take control of the target program using a buffer overflow. You can make the app crash or malfunction but that's all.
...which is bad enough. Haven't looked into gets, but often buffer overflows will let you take control of applications.

Miiiight not be a security issue for most apps using gets, but it's stil lsomething to consider in the big scheme of things.
Posted on 2010-01-06 09:16:04 by f0dder
ChaperonNoir, it's true that with eXecutionDisable bit (and Windows DEP) and Vista's/7's ASLR much of the exploitation problem has been resolved. But not everyone has still enabled these functionalities in their machines and -as f0dder mentioned- even a simple crash is something you can't afford to have if you want to call yourself a decent programmer. Many CRT functions are wll-known for their security risks, which pretty much means "do not use them", except maybe in some small tool-apps you write for yourself only.
Posted on 2010-01-06 14:36:49 by ti_mo_n