I'm writing an format string exploit script for a vulnerable program.
I'm able to exploit the vulnerability by executing the program with the following input:
./vulnerable `perl -e 'print "\x11\x11\x11\x40\x99\x04\x08"'`'AAAAx%11$n'
Here \x40\x99\x04\x08 is the address of a variable in vulnerable.
I want to write a script that generates this input without a hard-coded address.
In my script I retrieve the address of the variable and store it in address.txt.
Then I try to call vulnerable from my script as I did before, but with the content of address.txt:
./vulnerable $(perl -e 'print "\x11\x11\x11$(<address.txt)"')'AAAAx%11$n’
The content of address.txt is \x40\x99\x04\x08 so there is something wrong with the way I provide the content of address.txt to the perl print statement.
I've also tried leave out the $() around perl:
./vulnerable `perl -e 'print "\x11\x11\x11$(<address.txt)"'`'AAAAx%11$n'
But this renders the same result.
What am I doing wrong?
Single quotes don't expand $(...).
./vulnerable $(perl -e 'print "\x11\x11\x11'$(<address.txt)'"')'AAAAx%11$n'
# <------------->
# <-------------------> <->
# <------------------------------------------------><---------->
Related
This question already has answers here:
Send string to stdin
(6 answers)
Command not found error in Bash variable assignment
(5 answers)
How do I set a variable to the output of a command in Bash?
(15 answers)
Closed 3 years ago.
I am trying to assign a variable to the result of a regex substitution in bash. For instance, when I run
echo $initialvar | perl -pe 's/.+(Some_Dir\/)(.+)/\2/'
I get the desired output from the echo. How would I assign a newvar to the resulting output?
I've tried:
newvar= "$($initialvar | perl -pe 's/.+(Some_Dir\/)(.+)/\2/')"
newvar= echo $initialvar | perl -pe 's/.+(Some_Dir\/)(.+)/\2/'
but none of them work
As for your question, it seems to consist of two challenges: One being assigning the output of running a command to a BASH variable, and the other being piping the content of a variable to the standard input of a Perl program.
One
foo=$(bar)
runs bar and saves its output to the BASH variable $foo.
The other
Any of
echo "$foo" | bar
bar <(echo "$foo")
bar <<< "$foo"
runs bar with the content of $foo piped to its standard input
Combining the two
baz=$(bar <<< "$foo")
sets $baz to the value produced by bar having the content of $foo sent to its standard input.
Secondly, a few Perl-related suggestions peripherally related to your question:
I might instead use perl -nE:
-n will loop through each line like -p, but won't print by default.
-E will evaluate like -e, but with experimental features like say enabled.
You can avoid escaping the slash in Some_Dir/ by using another separator, e.g. s!...!...! or m!...!. Instead of replacing with s//, since you're just printing "Some_Dir/" if it matches, you might as well go and do that directly:
perl -nE 'say (m!Some_Dir/! ? "Some_Dir/" : $_)'
So:
newvar=$(perl -nE 'say (m!Some_Dir/! ? "Some_Dir/" : $_)' <<< "$initialvar")
You can use either of the following:
newvar=$(echo "$initialvar" | perl -pe 's/.+(Some_Dir\/)(.+)/\2/')
newvar=`echo "$initialvar" | perl -pe 's/.+(Some_Dir\/)(.+)/\2/'`
I have a file with below commands
cat /some/dir/with/files/file1_name.tsv|awk -F "\\t" '{print $21$19$23$15}'
cat /some/dir/with/files/file2_name.tsv|awk -F "\\t" '{print $2$13$3$15}'
cat /some/dir/with/files/file3_name.tsv|awk -F "\\t" '{print $22$19$3$15}'
When i loop through the file to run the command, i get below error
cat file | while read line; do $line; done
cat: invalid option -- 'F'
Try `cat --help' for more information.
You are not executing the command properly as you intended it. Since you are reading line by line on the file (for unknown reason) you could call the interpreter directly as below
#!/bin/bash
# ^^^^ for running under 'bash' shell
while IFS= read -r line
do
printf "%s" "$line" | bash
done <file
But this has an overhead of creating a forking a new process for each line of the file. If your commands present under file are harmless and is safe to be run in one shot, you can just as
bash file
and be done with it.
Also for using awk, just do as below for each of the lines to avoid useless cat
awk -F "\\t" '{print $21$19$23$15}' file1_name.tsv
You are expecting the pipe (|) symbol to act as you are accustomed to, but it doesn't. To help you understand, try this :
A="ls / | grep e" # Loads a variable with a command with pipe
$A # Does not work
eval "$A" # Works
When expanding a variable without using eval, expansion and word splitting occurs after the shell interprets redirections and pipes, so your pipe symbol is seen just as a literal character.
Some options you have :
A) Avoid piping, by passing the file name as an argument
awk -F "\\t" '{print $21$19$23$15}' /some/dir/with/files/file1_name.tsv
B) Use eval as shown below, the potential security implications of which I would suggest you to research.
C) Put arguments in file and parse it, avoiding the use of eval, something like :
# Assumes arguments separated by spaces
IFS=" " read -r -a arguments;
awk "${arguments[#]-}"
D) Implement the parsing of your data files in Bash instead of awk, and use your configuration file to specify output without the need for expanding anything (e.g. by specifying fields to print separated by spaces).
The first three approaches involve some form of interpretation of outside data as code, and that comes with risks if the file used as input cannot be guaranteed safe. Approach C might be considered a bit better in that regard, but since the command you are calling is awk, an actual program is passed to awk, so whatever awk can do, an attacker (or careless user) with write access to your file can cause your script to do anything awk can do.
I can do math like
perl -e 'print 5253413/39151' -l
But I don't quite get how to take advantage of Perl's ability to do math with my own predefined bash variables. I've tried
var1=$(some wc command that yields a number); var1=$(some wc that yields another number)
perl -e 'print var1/var2' -l
But it doesn't work
There are two main ways to do this.
Within the Perl code you can use the %ENV built-in hash to access environment variables that are exported from the shell
$ export var1=5253413
$ export var2=39151
$ perl -E 'say $ENV{var1}/$ENV{var2}'
134.183366963807
You can use the shell interpolation facility to insert the value of a shell variable into a command
This is best done as parameters to the perl one-liner rather than introducing the values directly into the code
$ var1=5253413
$ var2=39151
$ perl -E '($v1, $v2) = #ARGV; say $v1/$v2' $var1 $var2
134.183366963807
Two less common ways to do this make use of long-standing perl features.
The first is the core module Env, which ties process environment variables to perl variables:
sh$ export VAR1=1000
sh$ export VAR2=33
sh$ perl -MEnv -E 'say $VAR1/$VAR2' # imports all environ vars
333.333333333333
sh$ perl -MEnv=VAR1,VAR2 -E 'say $VAR1/$VAR2' # imports only VAR1, VAR2
333.333333333333
Note that the variables need to be present in the environment inherited by the perl process, for example with export VAR as above, or explicitly for a single command (as by FOO=hello perl -MEnv -E 'say $FOO').
The second and rather more obscure way is to use use perl's -s switch to set arbitrary variables from the command line:
sh$ VAR1=1000
sh$ VAR2=33
sh$ perl -s -E 'say $dividend/$divisor' -- -dividend=$VAR1 -divisor=$VAR2
333.333333333333
awk does something similar with its -v switch.
I believe the spirit of the question is to pass variables without exported ENV vars.
Beside using perl -s -e expression -perlvar=val, below is code that uses two other mechanisms to pass the variable to perl.
a=x; b=N; c=z;
b=y perl -e '$pa='$a';' -e "\$pc=$c;" -e 'print "$pa$ENV{b}$pc\n";'
echo $a$b$c
Passing a and c is same, only the quoting is different. When passing using chained expressions, like this, it is important to end the expression with semi-colon; because, they flow into one expression at the end.
Passing b is done by ENV, but instead of using the exported value, it is passed directly into perl's ENV by giving the assignment before the command on the same command-line.
Last the echo command is to emphasize how the shell's definition of $b is unchanged.
Using the mechanism of b's passing, we arrive at a more secure solution, because the process's ENV data cannot be checked for the value, and it will not be seen in the command-line argument list.
I have one liner mails that I wish to send from procmail into a bash script. I only want the body to be sent, nothing else.
Currently my .procmailrc looks like this:
:0
*^ Subject.*Xecute Command$
{
:0 bf
| /bin/bash /path/to/script
}
And my Bash script is simple:
#!/bin/bash
echo -e "\rLT 4>$0\r\r" > /dev/ttyS1
I don't get any input or output from anywhere.
Any pointers?
If the intention is to add some decorations to the email message and print it to a serial port (?), try a recipe like
:0b
*^ Subject.*Xecute Command$
| ( printf '\rLT 4>'; cat -; printf '\r\r' ) > /dev/ttyS1
The b flag applies to the action line if the condition matches, so you don't need the braces and a new conditionless recipe; the f flag makes no sense at all in this context. (Though if you want to keep the message for further processing, you'll want to add a c flag.)
Also, for the record, $0 in Bash is the name of the currently running script (or bash itself, if not running a script), and $# is the list of command-line arguments. But Procmail doesn't use either of these when it pipes a message to a script; it is simply being made available on standard input.
If you want the action in an external script, that's fine, too, of course; but a simple action like this is probably better written inline. You don't want or need to specify bash explicitly if the script file is executable and has a proper shebang; the reason to have a shebang is to make the script self-contained.
In response to comments, here is a simple Perl script to extract the first line of the first body part, and perform substitutions.
perl -nle 'next if 1../^$/;
s/\<foo\>/bar/g;
print "\rLT 4>$_\r\r"; exit(0)'
This would not be hard to do in sed either, provided your sed understands \r.
Write your script like that:
{
echo -e "\rLT 4>"
cat
echo -e "\r\r"
} > /dev/ttyS1
formail is your friend!
Pipe the message into:
:0
*^ Subject.*Xecute Command$
| formail -I "" | your-bash-script
I wrote a simple shell script to get the version of Perl modules installed
on a server and I keep receiving the following error:
Can't find string terminator "'" anywhere before EOF at -e line 1.
Here is my script:
#!/bin/sh
#
mod_name="Sub::Uplevel"
tmp1="perl -M$mod_name -e 'print \"\$$mod_name::VERSION\"'"
echo $tmp1
$tmp1
If I just directly run the echo'd line (perl -MSub::Uplevel -e 'print "$Sub::Uplevel::VERSION"'), it works. Why doesn't the line work when its run from the variable $tmp1?
In place of just $tmp1, eval works:
eval "$tmp1"
That's because splitting a variable into words (for arguments) is done strictly by splitting on $IFS, not the normal input-parsing. eval forces the normal input parsing.
How did I figure this out?
Change your tmp1= line to put an echo in front, and you get:
perl -MSub::Uplevel -e 'print "$Sub::Uplevel::VERSION"'
Note that the ' are still there, which you wouldn't expect. If you write a quick script:
#!/bin/sh
for a in "$#"; do
echo "arg: $a"
done
and put a call to that in place of echo, you find how the arguments are really split:
arg: perl
arg: -MSub::Uplevel
arg: -e
arg: 'print
arg: "$Sub::Uplevel::VERSION"'
So, you can see that's splitting on spaces, so IFS.
It's always better to construct commands using bash arrays. That will keep arguments with whitespace properly grouped:
#!/bin/bash
mod_name="Sub::Uplevel"
perl_script=$(printf 'print "$%s::VERSION"' $mod_name)
tmp1=(perl -M$mod_name -e "$perl_script")
echo "${tmp1[#]}"
output=$( "${tmp1[#]}" )
Arrays are a bash feature, so the shebang line must reference bash not sh.
I'd usually write what you are doing with backticks, to run the command inside the shell:
#!/bin/sh
#
mod_name="Sub::Uplevel"
tmp1=`perl -M$mod_name -e 'print \"\$$mod_name::VERSION\"'`
echo $tmp1
Then you can work on $tmp1 as needed. It also avoids dealing with escaping.
Try to execute the script the below way(debugging the script):
sh -vx your_script.sh
Then you would be able to see where exactly the problem is.
I donot have the shell to execute it right now.