flat assembler
Message board for the users of flat assembler.

Index > Windows > ReadFile input name in execution time

Author
Thread Post new topic Reply to topic
x0r4nd



Joined: 22 Apr 2013
Posts: 14
x0r4nd 30 Apr 2013, 19:43
Hello I am new in this forum, I am Spanish speaking. I translated this message using Google Translator.
Also You can notice that I am almost completely ignorant about FASM, ASSEMBLER and programming.
I ask for patience because I know that my question is elementary and so perhaps the answer also is:
After searching many examples and wasting too much time I managed to build a small console (Windows 7) program that opens and reads a text file and display its contents on the same console.
But the only way to achieve this is to insert in the "data" of the program the name of the file to read (in the example: DB FileTitle "1.txt") meaning that only supports that fact in DESIGN TIME.
I could not get the program to accept input via console the file name to read (Execution Time) so if I want to read one file or other should be built for each file different program (????????? ?!!!!), this would be further complicated if not known at compile the program the text file name to read.
In ALL the examples I've read in this forum, other forums, blogs, tutorials, books, articles, courses, etc. .. always appears that the file name to read is inserted at design time and have not found one that that the name can be introduced at will by the user of the program at runtime. (In the example would be "buf1")
I tried all possible means: keyboard input formatting (wsprintf), concatenating strings (lstrcat) so that at design time enter a variable (the directory) and run-time file name to read to get a single string with the full path.
I emptied the string FileTitle to copy it to buf1 ...
I used "LOPEN" and "lread" instead of "OpenFile" and "ReadFile" ...
I've also changed the format of the variables, DD DB TCHAR, in all possible combinations..
Etc.. etc ...
The only thing that I did not try is shoot me in the head ....
What is the secret? if all languages and programs do this so simple why do not succeed with ASM??????
Thanks in advance.
ANNEX CODE PROGRAM.
Code:
format PE console 4.0
include 'E:\__PROGRAMACION\__ASSEMBLER\FASM\INCLUDE\win32ax.inc'
section "data"  readable writeable
                FileTitle DB "1.txt" 
                hFile dd ?
                nSize dd ?
                lpBytesRead dd ?
                lpBuffer rb 64000
                in_handle DD ?
                out_handle DD ?
                written DD ?
                buf1 DD ?,0
                salto TCHAR 10,13
.code
start:
                 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                 invoke AllocConsole
                 invoke GetStdHandle, STD_INPUT_HANDLE
                 mov [in_handle], eax
                 invoke GetStdHandle, STD_OUTPUT_HANDLE
                 mov [out_handle], eax
                 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proceso:
                 invoke ReadConsole, [in_handle],buf1,512, written, 0
                 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                 push  0                ;ByVal hTemplateFile As Long
                 push  1                ;ByVal dwFlagsAndAttributes As Long   FILE_ATTRIBUTE_READONLY=1
                 push  3                ;ByVal dwCreationDisposition As Long OPEN_EXISTING=3
                 push 0                 ;ByRef lpSecurityAttributes As SECURITY_ATTRIBUTES
                 push 1                 ;ByVal dwShareMode As Long  FILE_SHARE_READ=1
                 push GENERIC_READ      ;ByVal dwDesiredAccess As Long
                 push FileTitle ; (buf1)        ;ByVal lpFileName As String
                 call [CreateFile]
                 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                 mov [hFile], eax
                 invoke GetFileSize,eax, 0;
                 inc eax
                 mov [nSize], eax ;
                 invoke ReadFile,[hFile] , lpBuffer,[nSize], lpBytesRead, 0 ; [nSize]
                 invoke CloseHandle, [hFile] ;
                 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                 invoke WriteConsole, [out_handle],lpBuffer,[lpBytesRead],[lpBytesRead],0
                 invoke WriteConsole, [out_handle],salto,2,2,0
                 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                 xor edx,edx
                 mov [buf1],edx
                 mov [lpBytesRead],edx
                 mov [nSize],edx
                 mov [hFile],edx
                 mov [lpBuffer],NULL
                 call proceso
invoke ExitProcess, 0
.end start    


Description:
Filesize: 136.54 KB
Viewed: 5710 Time(s)

readfile.jpg


Post 30 Apr 2013, 19:43
View user's profile Send private message Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2909
Location: 0x77760000
typedef 30 Apr 2013, 20:27
Hello. When in doubt read the API documentation:

ReadConsole:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms684958(v=vs.85).aspx

Code:
BOOL WINAPI ReadConsole(
  _In_      HANDLE hConsoleInput,
  _Out_     LPVOID lpBuffer,
  _In_      DWORD nNumberOfCharsToRead,
  _Out_     LPDWORD lpNumberOfCharsRead,
  _In_opt_  LPVOID pInputControl
);
    


Your buffer points to an 8-byte memory space (x2 DWORD)
So you only need to read 7 characters (the last one as a null terminator) or change that to RB 100 (100 bytes) or DB 100 DUP (0) (100 bytes fill with nulls)
Post 30 Apr 2013, 20:27
View user's profile Send private message Reply with quote
x0r4nd



Joined: 22 Apr 2013
Posts: 14
x0r4nd 30 Apr 2013, 21:46
Hello TypeDef tanks about your answer but it do'nt solve the problem.
I think it is not about the size of the buffer because when I add this line
Quote:
invoke WriteConsole, [out_handle],buf1,[written],[written],0

after the input, it is reproduced without add an extra character or missing information. This occurs regardless of the size or type buffer DD DB TCHAR etc. ..
And it remains that: although the typed buffer is received by the perfect form, the file whose name introduced is not open.
Code:
format PE console 4.0

include 'win32ax.inc'

section "data"  readable writeable
                ;FileTitle DB "1.txt"
                hFile dd ?
                nSize dd ?
                lpBytesRead dd ?
                lpBuffer rb 64000
                in_handle DD ?
                out_handle DD ?
                written DD ?
                buf1 rb 100
                salto TCHAR 10,13
.code
start:
                 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                 invoke AllocConsole
                 invoke GetStdHandle, STD_INPUT_HANDLE
                 mov [in_handle], eax
                 invoke GetStdHandle, STD_OUTPUT_HANDLE
                 mov [out_handle], eax
                 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proceso:
                 invoke ReadConsole, [in_handle],buf1,6, written, 0
                 invoke WriteConsole, [out_handle],buf1,[written],[written],0
                 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                 push  0                ;ByVal hTemplateFile As Long
                 push  1                ;ByVal dwFlagsAndAttributes As Long   FILE_ATTRIBUTE_READONLY=1
                 push  3                ;ByVal dwCreationDisposition As Long OPEN_EXISTING=3
                 push 0                 ;ByRef lpSecurityAttributes As SECURITY_ATTRIBUTES
                 push 1                 ;ByVal dwShareMode As Long  FILE_SHARE_READ=1
                 push GENERIC_READ      ;ByVal dwDesiredAccess As Long
                 push buf1 ;FileTitle         ;ByVal lpFileName As String
                 call [CreateFile]
                 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                 mov [hFile], eax
                 invoke GetFileSize,eax, 0;
                 inc eax
                 mov [nSize], eax ;
                 invoke ReadFile,[hFile] , lpBuffer,[nSize], lpBytesRead, 0 ; [nSize]
                 invoke CloseHandle, [hFile] ;
                 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                 invoke WriteConsole, [out_handle],lpBuffer,[lpBytesRead],[lpBytesRead],0
                 invoke WriteConsole, [out_handle],salto,2,2,0
                 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                 xor edx,edx
                 mov [buf1],dl
                 mov [lpBytesRead],edx
                 mov [nSize],edx
                 mov [hFile],edx
                 mov [lpBuffer],NULL
                 call proceso
invoke ExitProcess, 0

.end start    
Post 30 Apr 2013, 21:46
View user's profile Send private message Reply with quote
hopcode



Joined: 04 Mar 2008
Posts: 563
Location: Germany
hopcode 30 Apr 2013, 22:43
Hallo x0r4nd, try this direct
Code:
;--- usage readfile.exe < readfile.asm
;--- or readfile.exe  (echo the line you type, break with Ctrl+C)

 format PE CONSOLE 5.0
 entry start
 include 'win32a.inc'

section '.data' data readable writeable
  szBuf db 1024 dup (0)
  szErr db "EOF or error while reading",0

section '.code' code readable executable
start:
 mov edi,szBuf
 mov esi,szErr

.lineN:
 push edi
 call [gets]
 add esp,4
        
 test eax,eax
 cmovz edi,esi

 push edi
 call [strlen]
 add esp,4
 mov dword[edi+eax],0D0Ah

 push edi
 call [printf]
 add esp,4

 cmp edi,esi
 jnz .lineN
ret 0

 section '.idata' import data readable writeable
        
 library \
  msvcrt,"MSVCRT",\
  import msvcrt,\
   printf,"printf",\
   gets,"gets",\
   strlen,"strlen"
    

example/tuts for c-calling convention without cinvoke ?
Cheers,
Very Happy

_________________
⠓⠕⠏⠉⠕⠙⠑
Post 30 Apr 2013, 22:43
View user's profile Send private message Visit poster's website Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 30 Apr 2013, 22:43
x0r4nd,

Console process gets its own console by default; unless you use FreeConsole() to release it, AllocConsole() will fail.

ReadConsole() fills your buffer with available input literally, i.e. <Enter> key will be represented with CR/LF pair.

Fourth parameter for WriteConsole() (LPDWORD lpNumberOfCharsWritten) should be address of dword that receives number of characters written; you've passed contents of that dword ([written] instead of written).

CreateFile() expects zero-terminated string as contents of memory pointed by LPCTSTR lpFileName parameter. ReadConsole() won't supply that terminator for you.

Arbitrary usage of Hungarian prefix notation can be misleading.

How your program is supposed to terminate? Apart from GPF or stack overflow, naturally. Wink
Post 30 Apr 2013, 22:43
View user's profile Send private message Reply with quote
x0r4nd



Joined: 22 Apr 2013
Posts: 14
x0r4nd 30 Apr 2013, 23:40
Hello HopCode, Thank's.
Your code is a very good example of how to enter and read strings in console. But my problem is another: How do I get that string introduced to serve as a file name that wants to open and read in console?
I will continue researching, now I do not feel alone.
Post 30 Apr 2013, 23:40
View user's profile Send private message Reply with quote
x0r4nd



Joined: 22 Apr 2013
Posts: 14
x0r4nd 30 Apr 2013, 23:49
Hello Baldr, thank's
I understand and apply your advices, but this did not solve the problem:
How do I manually typed the name of a text file that I want to read in the console?
I have added the final zero with lstrcat , also with the macro Astrocat (jumpex http://board.flatassembler.net/topic.php?t=11734), but the result is still the same DOES NOT OPEN NOR READ THE FILE.
The program is just a sketch, I finish it with ctrl + c, but in the future can enter a key word "exit", "quit", "fin","end", "salir","going out," out "to call ExitProcess.
I'm not a hacker, neither a shellcoder ,do not wish to exploit buffers.
Post 30 Apr 2013, 23:49
View user's profile Send private message Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2909
Location: 0x77760000
typedef 01 May 2013, 00:43
Study this sir

Code:
;
;   (c) 2013. typedef
;
include 'win32ax.inc'

.data
    fileNameAsInput  db 100 dup(0),0
    stdIn            dd ?
    stdOut           dd ?

    _oops            db 'AllocConsole failed',0
    bytesRead        dd ?

    pBuff            db 'Hullo Wurld',0
    buff_len         =  $ - pBuff

    pszText          db 'Enter a file name: ',0
    txtLength        =  $ - pszText
    bytesWritten     dd ?
.code

start:
        call    [AllocConsole]
        test    eax,    eax
        je      .oops

        ; Get input handle
        push    STD_INPUT_HANDLE
        call    [GetStdHandle]
        mov     [stdIn],     eax

        ; Get output handle
        push    STD_OUTPUT_HANDLE
        call    [GetStdHandle]
        mov     [stdOut],     eax

        ; write somet text
        push    NULL
        push    bytesWritten
        push    txtLength
        push    pszText
        push    [stdOut]
        call    [WriteConsole]

        ; Read 100 bytes from handle
        push    NULL
        push    bytesRead
        push    100
        push    fileNameAsInput
        push    [stdIn]
        call    [ReadConsole]

        ; trim  CRLF
        mov     eax,    [bytesRead]
        add     eax,    -2
        mov     [fileNameAsInput+eax], NULL


        ; Create the file here
        push     NULL
        push     FILE_ATTRIBUTE_NORMAL
        push     CREATE_ALWAYS
        push     NULL
        push     NULL             ; exclusive mode
        push     GENERIC_WRITE
        push     fileNameAsInput
        call     [CreateFile]

        mov     ebx,    eax      ; save file handle

        ; Write to the file
        push    NULL
        push    bytesRead        ; Not needed anymore(bytes written)
        push    buff_len         ; number of bytes to write
        push    pBuff
        push    ebx
        call    [WriteFile]

        ; close the file
        push    ebx
        call    [CloseHandle]

        ; free the console
        call   [FreeConsole]
        jmp    .finish
.oops:
       push     0
       push     _oops
       push     _oops
       push     0
       call     [MessageBox]

.finish:
       push     0
       call     [ExitProcess]

.end start
    
Post 01 May 2013, 00:43
View user's profile Send private message Reply with quote
hopcode



Joined: 04 Mar 2008
Posts: 563
Location: Germany
hopcode 01 May 2013, 00:55
or the same with tomatoes but commented Wink
Code:
;--- fasm readfileA.asm
;--- usage readfileA.exe

 format PE CONSOLE 5.0
 entry start
 include 'win32a.inc'

section '.data' data readable writeable
  bytesRead dd 0
  szBuf db 1024 dup (0)
  szErr db "Error while reading",0
  szMsg db "Please enter a valid filename : ",0
  szSize db "Filesize is : %d bytes",13,10,0
  szOk  db "Ok",13,10,0

section '.code' code readable executable
start:
 xor ebx,ebx

 push szMsg  ;--- print useful message
 call [printf]
 add esp,4         ;--- adjust stack here for push once

 push szBuf   ;--- ready to accept a single line containing filename
 call [gets]
 add esp,4
 test eax,eax
 jz     .err

 push 0             ;--- template not required
 push FILE_ATTRIBUTE_NORMAL ;--- normal file
 push OPEN_EXISTING     ;--- how to create  
 push 0             ;--- pointer to security attributes not strictly required

 push FILE_SHARE_READ   \
        or FILE_SHARE_WRITE    ;--- can be shared

 push GENERIC_READ ;--- access it for reading 
 push szBuf              ;--- filename
 call [CreateFile] 
 test eax,eax
 jle .err
 mov ebx,eax

 push 0         ;--- file must be < 4Gb
 push ebx      ;--- handle of file to get size of
 call [GetFileSize]
 test eax,eax ;--- zero or > 7FFFFFFFh not accepted as size here
 jle .err

 push eax
 push szSize
 call [printf]
 add esp,8      ;--- c-calling covention adjust stack for 2 push dword

.readN:
 push 0      ;---address of structure for data 
 push bytesRead ;---address of number of bytes read 
 push 1024           ;---number of bytes to read 
 push szBuf     ;---address of buffer that receives data  
 push ebx            ;---handle of file to read 
 call [ReadFile] ;--- after a successful read the filepointer is automagically after bytesRead

 xor ecx,ecx
 test eax,eax
 jz .err

 cmp ecx,[bytesRead]  ;--- if bytesRead is 0 we are at EOF
 jnz .readP

 push szOk
 jmp .ok

.readP:
 push szBuf     ;--- print content
 call [printf]
 add esp,4
 jmp .readN

.err:
 push szErr            ;--- print error message

.ok:
 call [printf]
 add esp,4

 test ebx,ebx   ;--- check if filehandle is ok
 jz .exit

 push ebx       
 call [CloseHandle] 

.exit:
 ret 0

 section '.idata' import data readable writeable
  library \
    kernel32,'KERNEL32',\
    msvcrt,"MSVCRT",\
    user32,'USER32'

     include 'api\kernel32.inc'
     include 'api\user32.inc'
        
  import msvcrt,\
   printf,"printf",\
   gets,"gets",\
   strlen,"strlen" 
    

after the 3rd post it deserves example/tuts ehh !! Very Happy

_________________
⠓⠕⠏⠉⠕⠙⠑
Post 01 May 2013, 00:55
View user's profile Send private message Visit poster's website Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 01 May 2013, 01:16
x0r4nd,

Probably you've added final zero to already invalid file name (because it contains CR/LF or is too short. Here is slightly modified version of your source (mods are indicated by ;;;):
Code:
format PE console 4.0

include 'win32ax.inc'

section "data"  readable writeable
                ;FileTitle DB "1.txt"
                hFile dd ?
                nSize dd ?
                lpBytesRead dd ?
                lpBuffer rb 64000
                in_handle DD ?
                out_handle DD ?
                written DD ?
                buf1 rb 100
                salto TCHAR 10,13
.code
start:
                 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                 invoke AllocConsole
                 invoke GetStdHandle, STD_INPUT_HANDLE
                 mov [in_handle], eax
                 invoke GetStdHandle, STD_OUTPUT_HANDLE
                 mov [out_handle], eax
                 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
proceso:
                 invoke ReadConsole, [in_handle],buf1,6, written, 0
;;;                 invoke WriteConsole, [out_handle],buf1,[written],[written],0
                 invoke WriteConsole, [out_handle],buf1,[written],written,0
                 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                 push  0                ;ByVal hTemplateFile As Long
                 push  1                ;ByVal dwFlagsAndAttributes As Long   FILE_ATTRIBUTE_READONLY=1
                 push  3                ;ByVal dwCreationDisposition As Long OPEN_EXISTING=3
                 push 0                 ;ByRef lpSecurityAttributes As SECURITY_ATTRIBUTES
                 push 1                 ;ByVal dwShareMode As Long  FILE_SHARE_READ=1
                 push GENERIC_READ      ;ByVal dwDesiredAccess As Long
                 push buf1 ;FileTitle         ;ByVal lpFileName As String
                 call [CreateFile]
                 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                 mov [hFile], eax
                 invoke GetFileSize,eax, 0;
                 inc eax
                 mov [nSize], eax ;
                 invoke ReadFile,[hFile] , lpBuffer,[nSize], lpBytesRead, 0 ; [nSize]
                 invoke CloseHandle, [hFile] ;
                 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                 invoke WriteConsole, [out_handle],lpBuffer,[lpBytesRead],[lpBytesRead],0
                 invoke WriteConsole, [out_handle],lpBuffer,[lpBytesRead],lpBytesRead,0
;;;                 invoke WriteConsole, [out_handle],salto,2,2,0
                 invoke WriteConsole, [out_handle],salto,2,0,0
                 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                 xor edx,edx
                 mov [buf1],dl
                 mov [lpBytesRead],edx
                 mov [nSize],edx
                 mov [hFile],edx
                 mov [lpBuffer],NULL
                 call proceso
invoke ExitProcess, 0

.end start    
Try it with file name of exactly six characters.

Here is another example, it properly terminates entered file name (you may try include "Win32WX.Inc" too, just make sure that your file using UTF-16LE encoding).
Code:
        format  PE console
        include "Win32AX.Inc"

        .code
TypeFile:
        invoke  GetStdHandle, STD_OUTPUT_HANDLE
        mov     [hStdOut], eax
        invoke  WriteConsole, eax, prompt, lengthof.prompt, NULL, NULL
        invoke  GetStdHandle, STD_INPUT_HANDLE
        mov     [hStdIn], eax
        invoke  ReadConsole, eax, filename, lengthof.filename, CharsRead, NULL
        mov     ecx, [CharsRead]
        mov     edi, filename
        mov     eax, 13
if sizeof.TCHAR = 1
        repne scas byte [es:edi]
        mov     byte [edi-sizeof.TCHAR], 0
else if sizeof.TCHAR = 2
        repne scas word [es:edi]
        mov     word [edi-sizeof.TCHAR], 0
else
  err "Unknown character size"
end if
        invoke  CreateFile, filename, GENERIC_READ, FILE_SHARE_READ, NULL,\
                            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL+FILE_FLAG_SEQUENTIAL_SCAN, NULL
        mov     [hFile], eax
        invoke  ReadFile, eax, buffer, sizeof.buffer, BytesRead, NULL
        invoke  CloseHandle, [hFile]
        mov     eax, [BytesRead]
if sizeof.TCHAR = 2
        shr     eax, 1
end if
        invoke  WriteConsole, [hStdOut], buffer, eax, NULL, NULL
        invoke  ExitProcess, 0

        .data
prompt  TCHAR   "Enter file name: "
lengthof.prompt = ($ - prompt)/sizeof.TCHAR
hStdIn  dd      ?
hStdOut dd      ?
CharsRead dd    ?
filename TCHAR  MAX_PATH dup ?
lengthof.filename = ($ - filename)/sizeof.TCHAR
hFile   dd      ?
BytesRead dd    ?
buffer  TCHAR   1000 dup ?
sizeof.buffer = $ - buffer
        .end    TypeFile    
Post 01 May 2013, 01:16
View user's profile Send private message Reply with quote
x0r4nd



Joined: 22 Apr 2013
Posts: 14
x0r4nd 01 May 2013, 01:47
Thank you all.
I will study the examples; for now, the Hopcode's code works perfectly. The others has not yet managed to work.
I will do the home work.
As I said earlier, the problem was elementary and only product of my ignorance.
Thanks a lot again.
Post 01 May 2013, 01:47
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< 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-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.