flat assembler
Message board for the users of flat assembler.

Index > Windows > [Solved] Simple Shell. Need Help!

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



Joined: 02 Feb 2015
Posts: 42
Location: A chair
CampTheBoss 07 Feb 2015, 12:39
I made a shell using 64 bit windows, and need some help with making commands into one whole string.
here is the code
Code:
;WinCMD64 Dev Edition By Henry Southall (Permissions now added)
format PE64 console                             ;Win64 portable executable console format
entry loadprog                                  ;loadprog is the program's entry point. It prints a message to the screen before asking the user what to do.
 
include 'win64ax.inc'
include 'winexec.inc'                           ;WinExec Permissions plugin
 
section '.data' data readable writeable         ;data definitions
sysprefix EQU '[WinCMD64] '
console db "WinCMD64 Version 1.0 By Henry Southall" ,0ah, 0dh, prefix, 'Hooked into WinCMD64!',0
constr db 0ah, 0dh, '[',username,'] [INFO]: ',0
stringformat db "%s", 0ah, 0
msg db 0ah, 0dh, sysprefix,"Unknown command. type 'h' for help",0
msg2 db 'Help:', 0ah, 0dh, 'h  Opens this window',0ah, 0dh, 'e  Shuts the application',0ah, 0dh, 'r  Restarts the application',0ah, 0dh, 'd  Gets the directory you are in',0ah, 0dh, 'c  Clears the screen',0ah, 0dh, 'u  Displays user information',0ah, 0dh, 'w  Opens the web browser',0
str1 db 'WinCMD64 Successfully Started',0
caption db 'WinCMD64 Version 1.0',0
badchar db prefix,'Invalid Character! (0-20 are not supported)',0
exitmsg db 'Press any key to exit WinCMD64...',0
creds db 'Username: ',username, 0ah, 0dh, 'OP: ',OP,0ah, 0dh, 'Group: ',ranked,0
opbad db prefix, 'OP Status is invalid!',0
clear db 'cls',0
titlechange db 'title WinCMD64',0
p db 'Pause>nul',0
URL db 'http:\\www.google.co.uk',0

section '.code' code readable executable      ;code (Builds Application up)
loadprog:                                     ;Allocate memory
        push rbp
        mov rbp, rsp
        sub rbp, 128
_start:
        invoke system,titlechange
        invoke printf, stringformat, console   ; call printf, defined in msvcrt.dll
  ;      invoke MessageBox,0,str1,caption,MB_OK
afterstrt:
        call checkOP
        invoke printf, constr
looper:
        invoke getchar,0     ;Starts the loop
checkhelp:
        cmp al, 'h'
        je help
        jne checkother
checkother:
        cmp al, 'r'
        je checkfirst
        jne restartcheck
restartcheck:
        cmp al, 'e'
        je checkexit
        jne directorycheck
directorycheck:
        cmp al, 'd'
        je directoryperms
        jne clearcheck
clearcheck:
        cmp al, 'c'
        je clearperms
        jne usercheck
usercheck:
        cmp al, 'u'
        je usercred
        jne webcheck
webcheck:
        cmp al, 'w'
        je checkweb
        jne charerr?

charerr?:
        cmp al, 0h
        je afterstrt
        jne othererr
othererr:
        cmp al, 20h
        je afterstrt
        jne checkenter
checkenter:
        cmp al, 0ah
        je looper
        jne checkstrpos
checkstrpos:
        cmp al, 0dh
        je looper
        jne checkundr
checkundr:
        cmp al, 20h
        jl invaldchar
        jne okerr

invaldchar:
invoke printf, stringformat, badchar
jmp afterstrt

usercred:
invoke printf, stringformat, creds
jmp closekeylevel

executeweb:
invoke ShellExecute,0,0,URL,0,0,SW_SHOW
jmp closekeylevel

exit:
        invoke printf, stringformat, exitmsg
        invoke system,p
        invoke ExitProcess, 0                ; exit the process

okerr:
        cmp al, 0ah
        je looper
        invoke printf, msg
        jmp afterstrt

executedir:
        invoke printf, stringformat,invoke GetCommandLine
        jmp closekeylevel

executeclr:
        invoke system,clear
        jmp closekeylevel

help:
        invoke printf, stringformat, msg2
        mov al, 0
        jmp closekeylevel

closekeylevel:
        invoke getchar,0
cmp al, 0ah
        je afterstrt
        jne checkkey2
checkkey2:
        cmp al, 0h
je afterstrt
jne afterstrt

section '.idata' import data readable      ; data imports
 
library kernel, 'kernel32.dll',\             ; link to kernel32.dll, msvcrt.dll, user32.dll, shell32.dll
        msvcrt, 'msvcrt.dll',\
        user32, 'user32.dll',\
        shell32,'shell32.dll'
 
import kernel, \                             ; import from kernel32
       ExitProcess, 'ExitProcess',\
       GetCommandLine,'GetCommandLineA'
 
import msvcrt, \                             ; Import from msvcrt
       printf, 'printf',\
       getchar, '_fgetchar',\
       system, 'system'

import user32, \
       MessageBox,'MessageBoxA'

import shell32,\
       ShellExecute,'ShellExecuteA'    


The include file i used:


Code:
;WinExec Permissions plugin for WinCMD64 (Not compatible with WinCMD32)
;All permissions defined with a '1' or a '0'
;Data
prefix EQU '[WinExec] '
noperm db prefix, 'You do not have permission to do this!',0
apperrmsg db prefix, 'Error Reading permission!',0
;User details
username EQU 'Henry'
ranked EQU 'Administrator'
;Permissions Start here
winexec.cmd.dir DB 0h
winexec.cmd.rld DB 0h
winexec.cmd.clr DB 0h
winexec.cmd.ext DB 0h
winexec.cmd.web DB 0h
OP EQU 'TRUE'
;Code

checkOP:
IF OP='TRUE'
        ranked EQU 'Administrator'
        mov BYTE[winexec.cmd.dir], 1h
        mov BYTE[winexec.cmd.rld], 1h
        mov BYTE[winexec.cmd.clr], 1h
        mov BYTE[winexec.cmd.ext], 1h
        mov BYTE[winexec.cmd.web], 1h
        ret
ELSE
        jmp opbad?
END IF
ret

checkweb:
.if BYTE[winexec.cmd.web]=1h
        jmp executeweb
.else
        jmp webbad
.endif

checkexit:
.if BYTE[winexec.cmd.ext]=1h
        jmp exit
.else
        jmp extbad
.endif

checkfirst:
.if BYTE[winexec.cmd.rld]=1h
        jmp _start
.else
        jmp rldbad
.endif

directoryperms:
.if BYTE[winexec.cmd.dir]=1h
        jmp executedir
.else
        jmp dirbad
.endif

clearperms:
.if BYTE[winexec.cmd.clr]=1h
        jmp executeclr
.else
        jmp clrbad
.endif

webbad:
.if BYTE[winexec.cmd.web]=0h
        jmp badperm
.else
        jmp apperr
.endif
rldbad:
.if BYTE[winexec.cmd.rld]=0h
        jmp badperm
.else
        jmp apperr
.endif
extbad:
.if BYTE[winexec.cmd.ext]=0h
        jmp badperm
.else
        jmp apperr
.endif
dirbad:
.if BYTE[winexec.cmd.dir]=0h
        jmp badperm
.else
        jmp apperr
.endif
clrbad:
.if BYTE[winexec.cmd.clr]=0h
        jmp badperm
.else
        jmp apperr
.endif

badperm:
fastcall [printf], stringformat,noperm
jmp afterstrt

apperr:
fastcall [printf], stringformat,apperrmsg
jmp afterstrt

opbad?:
IF OP='FALSE'
        ranked EQU 'Default'
        ret
ELSE
        fastcall [printf], stringformat,opbad
        ret
END IF    


I have successfully managed to make it so one key can be pressed with enter, but i want a whole string. Smile


Last edited by CampTheBoss on 13 Mar 2015, 17:10; edited 1 time in total
Post 07 Feb 2015, 12:39
View user's profile Send private message Send e-mail Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20443
Location: In your JS exploiting you and your system
revolution 07 Feb 2015, 12:42
Perhaps you can define a buffer that stores incoming keystrokes and when Enter is pressed you search your command table for a matching string.
Post 07 Feb 2015, 12:42
View user's profile Send private message Visit poster's website Reply with quote
CampTheBoss



Joined: 02 Feb 2015
Posts: 42
Location: A chair
CampTheBoss 07 Feb 2015, 12:58
do you mean like using an if statement? (.if BYTE[buffer]=variableofkeyword)
I also don't know how to set a buffer up for the msvcrt function: _fgetchar, so I might need help with that. (i am new to win64/32 assembly, I came off DOS as an expert)
Post 07 Feb 2015, 12:58
View user's profile Send private message Send e-mail Reply with quote
CampTheBoss



Joined: 02 Feb 2015
Posts: 42
Location: A chair
CampTheBoss 07 Feb 2015, 13:04
do you mean like using an if statement? (.if BYTE[buffer]=variableofkeyword)
I also don't know how to set a buffer up for the msvcrt function: _fgetchar, so I might need help with that. (i am new to win64/32 assembly, I came off DOS as an expert)
Post 07 Feb 2015, 13:04
View user's profile Send private message Send e-mail Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20443
Location: In your JS exploiting you and your system
revolution 07 Feb 2015, 13:35
I mean to keep loading key presses one-by-one into a multi-byte buffer until either Enter is detected or the buffer overflows. Then in a different part of the code, after Enter has been detected, compare the contents of the buffer to a list of valid commands and act accordingly.
Post 07 Feb 2015, 13:35
View user's profile Send private message Visit poster's website Reply with quote
catafest



Joined: 05 Aug 2010
Posts: 129
catafest 07 Feb 2015, 14:35
I saw you put your username , I think you need to get the default user under your OS. also you can change and update your code with some specials commands like: ls , grep or awk or maybe make some default shells to your applications , like : python 2.7, 3.0 , gimp ...
This can be great.
Post 07 Feb 2015, 14:35
View user's profile Send private message Visit poster's website Yahoo Messenger Reply with quote
CampTheBoss



Joined: 02 Feb 2015
Posts: 42
Location: A chair
CampTheBoss 07 Feb 2015, 17:51
I am adding some stuff to it using ShellExecute, so it can load web pages etc.
The only thing i want to change is the WinExec permissions file. i want to make it a configuration file (in assembly format) and the program reads it without another compile
Post 07 Feb 2015, 17:51
View user's profile Send private message Send e-mail Reply with quote
CampTheBoss



Joined: 02 Feb 2015
Posts: 42
Location: A chair
CampTheBoss 07 Feb 2015, 18:35
I tried making a buffer:

Code:
buff db 0,0,0,0
helpstr db 'help'
looper:
invoke getchar
jmp makeabuff

makeabuff:
cmp al, 0ah
je cmpstrings
mov BYTE[buff],al
jmp looper

cmpstrings:
cmp BYTE[buff], BYTE[helpstr]
je good
jne exit
    


but it never compiles.
why?
Post 07 Feb 2015, 18:35
View user's profile Send private message Send e-mail Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20443
Location: In your JS exploiting you and your system
revolution 07 Feb 2015, 18:52
Your buffer is four bytes in size so your maximum command length is 4 characters.

But you need to add each keypress to the next position in the buffer. Currently you keep overwriting the first position with each incoming keypress.

Also, perhaps you can review the docs for the cmps instruction (and the prefix repz) to do comparisons with memory to memory directly. You'll need the RSI, RDI and RCX registers to be properly set for that to work.
Post 07 Feb 2015, 18:52
View user's profile Send private message Visit poster's website Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2909
Location: 0x77760000
typedef 08 Feb 2015, 02:24
Why not just make the shell load 'cmdlets' from a folder instead of hard coding your commands?

This will give you lots of advantages because your shell will not need to load a network library when all you want to do is find a local file.

Load your cmdlets when your shell loads and also have a command to reload the cmdlets on demand. Add integrity checks as well.
Post 08 Feb 2015, 02:24
View user's profile Send private message Reply with quote
CampTheBoss



Joined: 02 Feb 2015
Posts: 42
Location: A chair
CampTheBoss 08 Feb 2015, 09:50
Do you mean like loads of includes?
And at execution time, it calls them?
Post 08 Feb 2015, 09:50
View user's profile Send private message Send e-mail Reply with quote
CampTheBoss



Joined: 02 Feb 2015
Posts: 42
Location: A chair
CampTheBoss 08 Feb 2015, 13:38
How do i do it? I don't know how to load cmdlets at execution time.
Post 08 Feb 2015, 13:38
View user's profile Send private message Send e-mail Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2909
Location: 0x77760000
typedef 10 Feb 2015, 04:52
No. I mean like, take a look at CMD.EXE. It calls other console EXEs but also has few built in commands.


Now imagine if all those other system console EXEs were packaged into CMD.EXE. Wink
Post 10 Feb 2015, 04:52
View user's profile Send private message Reply with quote
CampTheBoss



Joined: 02 Feb 2015
Posts: 42
Location: A chair
CampTheBoss 10 Feb 2015, 07:24
typedef wrote:
No. I mean like, take a look at CMD.EXE. It calls other console EXEs but also has few built in commands.


Now imagine if all those other system console EXEs were packaged into CMD.EXE. Wink


Do you mean I should use ShellExecute to load other files?
Post 10 Feb 2015, 07:24
View user's profile Send private message Send e-mail Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2909
Location: 0x77760000
typedef 11 Feb 2015, 13:31
I'd recommend CreateProcess so you can redirect their IO handles to the console's STDIN/OUT and wait for the processes to get their exit code and other info.

However you load them, you just gotta make sure they receive and return data to and from the console. After all, they will be console apps.
Post 11 Feb 2015, 13:31
View user's profile Send private message Reply with quote
CampTheBoss



Joined: 02 Feb 2015
Posts: 42
Location: A chair
CampTheBoss 14 Feb 2015, 17:38
so, I should make macros and implement them into the program to test if they direct to an executable in a working directory?
Post 14 Feb 2015, 17:38
View user's profile Send private message Send e-mail Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2909
Location: 0x77760000
typedef 16 Feb 2015, 06:22
No. My point is to avoid hard coding.

Here, I just whipped up an example for you. I'd advise you to focus more on the methodology and not so much on the code.

List of internal commands (hard coded): clear, time, help, exit

List of external commands (EXEs in cmdlets folder): input, delete, whoami

You can type all those in the shell and it will try to resolve them.

You'll get the idea.


Description:
Download
Filename: GROOT-shell.rar
Filesize: 8.13 KB
Downloaded: 296 Time(s)

Post 16 Feb 2015, 06:22
View user's profile Send private message Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2909
Location: 0x77760000
typedef 16 Feb 2015, 06:51
Update
Function is_cmdlet can be optimized to this:

Code:
proc is_cmdlet
     ; if parameters, get the name part only and check if an EXE by that name exists in the 'cmdlets' folder
     call       has_Params
     cmp      eax, TRUE
     jne       .no_params
     push     szCmdletName
     jmp        .findCmdlet
.no_params:
     push     szInput
.findCmdlet:     
     push     szCmdletPathFmt
     push     szCmdletPath
     call      [wsprintfA]
     add      esp, 4 * 3

     ; check if cmdlet by this name exists
     call      cmdlet_Exists
.finish:
     ret
endp 
    
Post 16 Feb 2015, 06:51
View user's profile Send private message Reply with quote
CampTheBoss



Joined: 02 Feb 2015
Posts: 42
Location: A chair
CampTheBoss 16 Feb 2015, 11:07
Hey, I am kind of stuck because I usually like to do all of my work in high-level code, so could I use the code you have used and optimise it?
Post 16 Feb 2015, 11:07
View user's profile Send private message Send e-mail Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2909
Location: 0x77760000
typedef 16 Feb 2015, 12:16
CampTheBoss wrote:
Hey, I am kind of stuck because I usually like to do all of my work in high-level code, so could I use the code you have used and optimise it?

Sure go ahead.
Post 16 Feb 2015, 12:16
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  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-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.