flat assembler
Message board for the users of flat assembler.

Index > Windows > Command line differs in Command Prompt & PowerShell?

Author
Thread Post new topic Reply to topic
Flier-Mate



Joined: 26 May 2023
Posts: 88
Flier-Mate 30 May 2023, 20:57
I know I should use better code to get command line argument.
Below is my way of retrieving the input filename.

But from my findings, given "test test.asm", Command prompt gives correct "test.asm", but PowerShell gives "est.asm" (missing the leftmost character).

Does anyone know why?

Code:
        invoke  GetCommandLine
        push    eax
        mov     edi, eax
        or      ecx, -1
        xor     eax, eax
        repnz   scasb           ; Calculate total length of command line arguments
        not     ecx
        pop     eax
        dec     ecx
        mov     dword [_fnlen], ecx
        push    eax
        mov     edi, eax
        or      ecx, -1
        mov     eax, 32
        repnz   scasb           ; Calculate length of first command line argument (APPNAME)
        not     ecx
        pop     eax
        inc     ecx
        sub     dword [_fnlen], ecx     ; Compute the length of second command line argument (_FILENAME)
        cmp     dword [_fnlen], 0
        js      .err0
        add     eax, ecx
        mov     ecx, dword [_fnlen]
        mov     esi, eax
        lea     edx, [_filename]
        mov     edi, edx
        rep     movsb            


[_filename] is the input filename
[_fnlen] is the length of input filename


Description: Command prompt & PowerShell
Filesize: 112.57 KB
Viewed: 2860 Time(s)

Screenshot 2023-05-31 043334.png


Post 30 May 2023, 20:57
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20298
Location: In your JS exploiting you and your system
revolution 30 May 2023, 23:19
I suggest two ways to solve this:

1) Print out the returned string from GetCommandLine in hex and look for differences.

2) Use a debugger and follow the code.
Post 30 May 2023, 23:19
View user's profile Send private message Visit poster's website Reply with quote
Flier-Mate



Joined: 26 May 2023
Posts: 88
Flier-Mate 31 May 2023, 03:20
revolution wrote:
I suggest two ways to solve this:

1) Print out the returned string from GetCommandLine in hex and look for differences.

2) Use a debugger and follow the code.


I use the first method as it is easier, but I don't know how to interpret this result....

I use: "test2 test.asm > cmd.txt" at command prompt and ".\test2 test.asm > ps.txt" at PowerShell.

Command-prompt:
Code:
00000000  74 65 73 74 32 20 20 74 65 73 74 2E 61 73 6D 20   test2  test.asm
00000010  00 00 00 00 00 00 00 00 42 84 7C 12 68 7C 00 10   ........B.|.h|..    


PowerShell:
Code:
00000000  FF FE 22 00 43 00 3A 00 5C 00 55 00 73 00 65 00   ..".C.:.\.U.s.e.
00000010  72 00 73 00 5C 00 42 00 4F 00 4F 00 5C 00 70 00   r.s.\.B.O.O.\.p.
00000020  72 00 6F 00 6A 00 65 00 63 00 74 00 73 00 5C 00   r.o.j.e.c.t.s.\.
00000030  74 00 65 00 73 00 74 00 32 00 2E 00 65 00 78 00   t.e.s.t.2...e.x.
00000040  65 00 22 00 20 00 74 00 65 00 73 00 74 00 2E 00   e.". .t.e.s.t...
00000050  61 00 73 00 6D 00 00 00 00 00 00 00 00 00 00 00   a.s.m...........    


The command line string returned by PowerShell has BOM and is in Wide Char??

That one returned by command prompt has an extra white space (0x20) at the end of command line, and the one returned by PowerShell doesn't have two white space after the program name.

This is how I print the string returned by GetCommandLine:
Code:
section '.data' readable writable

_dummy    dd ?
_stdout   dd ?

section '.code' code readable executable

start:
        invoke  GetCommandLine
        push    eax
        invoke  GetStdHandle, -11
        mov     [_stdout], eax
        pop     eax
        mov     esi, eax
        mov     edx, MAX_PATH
        call    Print
        invoke  ExitProcess,0

Print:
        ;invoke  WriteConsole, dword [_stdout], esi, edx, _dummy, 0
        invoke  WriteFile, dword [_stdout], esi, edx, _dummy, 0
        ret           


From visual inspection (screenshot attached), I think it is because Command Prompt inserts two white space between program name and input filename.....


Description:
Filesize: 11.35 KB
Viewed: 2837 Time(s)

Screenshot 2023-05-31 112639.png


Post 31 May 2023, 03:20
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4017
Location: vpcmpistri
bitRAKE 31 May 2023, 03:33
Reading the code we can see something peculiar:

First the length of the string is calculated with:
Code:
        or      ecx, -1
        xor     eax, eax
        repnz   scasb           ; Calculate total length of command line arguments
        not     ecx
        dec     ecx    
... note how the value of ECX is reduced by one.

Then the distance of first argument with:
Code:
        or      ecx, -1
        mov     eax, 32
        repnz   scasb           ; Calculate length of first command line argument (APPNAME)
        not     ecx
        inc     ecx    
... the value of ECX in increased by one.

So, these techniques have a difference of two. Why? If we wanted to skip the space character they should only differ by one. Although Powershell is a different command processor, I think the error is in your code - the INC ECX is probably not what you intend.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 31 May 2023, 03:33
View user's profile Send private message Visit poster's website Reply with quote
Flier-Mate



Joined: 26 May 2023
Posts: 88
Flier-Mate 31 May 2023, 03:43
Thanks bitRAKE for your analysis, it is indeed true to skip the space character they should only differ by one.

If I comment the "inc ecx", the output in PowerShell is correct ("test.asm") but in command prompt is in error (" test.asm").

From my quick check, "dec ecx" is to remove the trailing space, and the "inc ecx" is to take command prompt special case into consideration (there are two white spaces between program name and input filename, not just one like in PowerShell).

And thanks for your code (that one you quoted), I modified it to use in my program to extract command line string. Smile
Post 31 May 2023, 03:43
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20298
Location: In your JS exploiting you and your system
revolution 31 May 2023, 04:01
It should be indifferent to the number of spaces.

A user could type
Code:
C:\>         test.exe           arg0                   arg1                     "2 3" 4 "5 6 7"     
Five arguments, some enclosed in quotes.
Post 31 May 2023, 04:01
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4017
Location: vpcmpistri
bitRAKE 31 May 2023, 04:16
Your redirected output also confirms the double-space. Seems like more complex processing is needed. Could just use CommandLineToArgvW() and be done with it. (Of course, that has it's own caveats.)

Might be of interest: The wild west of Windows command line parsing.
Post 31 May 2023, 04:16
View user's profile Send private message Visit poster's website Reply with quote
Flier-Mate



Joined: 26 May 2023
Posts: 88
Flier-Mate 31 May 2023, 05:03
Thank you revolution and bitRAKE for the feedback.

The "wild west of Windows command lien parsing" article has interesting point about undocumented offset in fs register to get the command line string. Wouldn't know that if I didn't read this article.

Yes, more complex processing is needed, I will use CommandLineToArgvW() as last resort. Or use "Command line parameters" example found in FASM website.

But.... I have an idea on how to solve the arbitrary white spaces, I will insert another routine to scan for white spaces until not found. Will start implement this in my future program.

Thank you all once again!
Post 31 May 2023, 05:03
View user's profile Send private message Reply with quote
Flier-Mate



Joined: 26 May 2023
Posts: 88
Flier-Mate 07 Aug 2023, 06:56
I fixed the code, the following work in Command Prompt and PowerShell:

Code:
        call    [GetCommandLine]
        push    eax
        cld
        mov     edi, eax
        or      ecx, -1
        xor     eax, eax
        repnz   scasb           ; Calculate total length of command line arguments
        not     ecx
        pop     eax
        push    eax
        mov     dword [_fnlen], ecx
        mov     edi, eax
        or      ecx, -1
        mov     eax, 32
        repnz   scasb           ; Find the first white space after first argument
        repz    scasb           ; Scan for extra white spacing between first argument and second argument
        not     ecx
        mov     dword [_dummy], ecx
        sub     dword [_fnlen], ecx
        cmp     dword [_fnlen], 0    ; Check if no argument is supplied
        js      .err0
        mov     ecx, dword [_fnlen]
        pop     eax
        add     eax, dword [_dummy]
        dec     eax
        mov     esi, eax
        lea     edi, [_filename]
        rep     movsb                


First argument here refers to APPNAME, second argument is user's specified FILENAME.
Post 07 Aug 2023, 06:56
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-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.