Why return-to-libc shell using system() exits immediately? - exploit

I'm experimenting control-flow hijacking attacks on programs written in C on Linux. I'm trying to perform a simple ret-2-libc attack on a program with the No-eXecutable-stack countermeasure enabled. For this purpose I'm returning to system() function with argument /bin/sh.
But I have a problem: Although my attack works and a shell is spawned successfully, the shell exits immediately after entering the first character! That is, the shell closes after I press any key!
This behavior is also observable in this simple C code:
int main() { system("/bin/sh"); return 0; }
I compile it using: gcc code.c -o system
Why is this? And how can I fix it?
I'm experimenting on Ubuntu-9.04 with kernel 2.6.28 and glibc-2.9-1
Update: The shell becomes interactive if and only if the first key that I press is Enter. That is, if the first character that I enter is a new-line (\n) then the shell remains open and become interactive.
So can anyone explain what's going on here?

Okay I believe that system is successfully calling /bin/sh but it is calling it with the -c flag.
Try:
/bin/bash -c junk
That should behave similarly to what you are seeing. You need to play around with the registers to setup the system call so that /bin/sh is called without the -c flag.

Related

Emacsclient crashes when evaluating window functions

To not bore anyone here with specifics, whenever I evaluate an expression similar to this one:
emacsclient -t -e '(set-buffer *scratch*)'
the client will flash up on the terminal and crash.
This seems to be happening with all window-changing functions. Is the client not supposed to work like that? Running this in a normal emacs session does not cause this problem.
You're also using -t, but I'm not exactly sure why.
Is your emacs running in another tty session?
Or is your emacs running in windowing mode (e.g. on X Windows)?
If I have emacs running in windowing mode and I run the following command from another xterm window, then everything works exactly as I would expect it to:
emacsclient -c -e '(set-buffer "*scratch*")
Note in particular the -c option, and the fact that the buffer name is a string and so must be enclosed in double-quotes.

Can I automate Windbg to attach to a process and set breakpoints?

I am debugging a windows process that crashes if the execution stops for even a few milliseconds. (I don't know how many exactly, but it is definitely less than the time taken by my reflexes to resume the process.)
I know I can launch a windbg session via the command prompt by typing in windbg -p PID which brings up the GUI. But can I then further pass it windbg commands via the command prompt, such as bm *foo!bar* ".frame;gc";g".
Because If I can pass it these commands I can write these down in a .bat file and just run it. There would at least be no delay due to entering (or even copy-pasting) the commands.
Use the -c parameter to pass them:
windbg -p PID -c "bm *foo!bar* .frame;gc;g"
According to the help (found by running windbg /?):
-c "command"
Specifies the initial debugger command to run at start-up. This command must be enclosed in quotation marks. Multiple commands can be separated with semicolons. (If you have a long command list, it may be easier to put them in a script and then use the -c option with the $<, $><, $><, $$>< (Run Script File) command.)
If you are starting a debugging client, this command must be intended for the debugging server. Client-specific commands, such as .lsrcpath, are not allowed.
You may need to play around with the quotes...
Edit: Based on this answer, you might be better off putting the commands into a script file to deal with the quotes:
script.txt (I think this is what you want):
bm *foo!bar* ".frame;gc"
g
Then in your batch file:
windbg -p PID -c "$<full_path_to_script_txt"

Waitfor doesn't recognize the expression in Perl

I've a waitfor command, but its not recognizing the pattern. What may be wrong?
while(#wait = $t->waitfor('/bash-3.2\$ $/i'))
Thanks,
Sharath
You need to set the waitfor to match your PS1 prompt.
On my machine if I:
export PS1=export PS1="\s-\v\$"
my prompt becomes:
bash-3.2$
So I think your code should be looking for
while(#wait = $t->waitfor('/bash\-3\.2\$/i'))
Which hopefully matches
I have to wonder though if your regex is the problem.
If you run an interactive command such as bash it will never return control to the program as it has no user input. Also, the while loop scares me a bit. I'm not sure why you need that.
If you really need bash try running your commands with bash -c <some command>
That way bash will run your single command and return the result.

How do I get Perl to run an alias I've defined in BASH?

I have a script that opens up different files at the same time.
My problem here is that when I run system() on the alias I've defined in bash which points to /home/user1/Software/nc, perl tells me that it can't execute the alias because there is no file/directory at the current location.
I know that the alias works because when I invoke it directly in a shell, it opens fine.
Funny enough, I can do system("firefox") within my script fine, but not the alias. How do I use this alias in this script without it breaking?
Perl won't run bash, it will execute the command directly. You can call
bash -c your_command
instead of calling the command itself in Perl.
As it is, this doesn't load your aliases. You need to open an interactive shell, as in #MortezaLSC's answer. There supposedly is a way of loading aliases correctly in a non-interactive shell, but I can't figure it out.
But why don't you just use the command you have aliased to directly in perl? The only reason I could see not to do this, is if your alias is going to change in the future, but you will still want to run whatever command it points to. This seems weird and dangerous to say the least.
Aliases are designed to reduce the typing you do if you invoke commands with the same options etc all the time. They're not all-purpose macros for bash. Bash has functions for doing more complicated stuff, but why would you want to call non-trivial bash code from a perl script? It doesn't seem like you really need this here. Keep the complexity, and the potential for modification and failure, in one place (the perl script).
See a couple of answers to similar questions:
https://unix.stackexchange.com/a/1499/41977
https://superuser.com/a/183980/187150
If you're smart, you made it so your alias is only defined for interactive shells, so you'll have to launch bash and specify that you want an interactive shell using -i.
system('bash', '-i', '-c', 'shell command');
Is it working?
system 'bash -i -c "your alias parameter"';

Odd behavior with Perl system() command

Note that I'm aware that this is probably not the best or most optimal way to do this but I've run into this somewhere before and I'm curious as to the answer.
I have a perl script that is called from an init that runs and occasionally dies. To quickly debug this, I put together a quick wrapper perl script that basically consists of
#$path set from library call.
while(1){
system("$path/command.pl " . join(" ",#ARGV) . " >>/var/log/outlog 2>&1");
sleep 30; #Added this one later. See below...
}
Fire this up from the command line and it runs fine and as expected. command.pl is called and the script basically halts there until the child process dies then goes around again.
However, when called from a start script (actually via start-stop-daemon), the system command returns immediately, leaving command.pl running. Then it goes around for another go. And again and again. (This was not fun without the sleep command.). ps reveals the parent of (the many) command.pl to be 1 rather than the id of the wrapper script (which it is when I run from the command line).
Anyone know what's occurring?
Maybe the command.pl is not being run successfully. Maybe the file doesn't have execute permission (do you need to say perl command.pl?). Maybe you are running the command from a different directory than you thought, and the command.pl file isn't found.
There are at least three things you can check:
standard error output of your command. For now you are swallowing it by saying 2>&1. Remove that part and observe what errors the system command produces.
the return value of system. The command may run and system may still return an exit code, but if system returns 0, you know the command was successful.
Perl's error variable $!. If there was a problem, Perl will set $!, which may or may not be helpful.
To summarize, try:
my $ec = system("command.pl >> /var/log/outlog");
if ($ec != 0) {
warn "exit code was $ec, \$! is $!";
}
Update: if multiple instance of the command keep showing up in your ps output, then it sounds like the program is forking and running itself in the background. If that is indeed what the command is supposed to do, then what you do NOT want to do is run this command in an endless loop.
Perhaps when run from a deamon the "system" command is using a different shell than the one used when you are running as yourself. Maybe the shell used by the daemon does not recognize the >& construct.
Instead of system("..."), try exec("...") function if that works for you.