Showing posts with label octal. Show all posts
Showing posts with label octal. Show all posts

Friday, May 2, 2008

Perl Script To Do Lame Encryption With Octal Dump On Linux Or Unix

Hey There,

A post ago, we took a look at using od on Linux or Unix. Hopefully, it made the use of that cryptic command somewhat more accessible.

Today, I thought we'd take a look at using the "od" command for a less practical purpose. Much like crypt (and a much older post we did on using simple encryption and decryption using Perl's pack and unpack functions), the quick-and-dirty Perl script we're putting out today is a pretty good way to keep people who don't know what they're reading from rifling through your stuff ;)

The script is simple enough, and only takes two arguments. You can either instruct it to convert a file from ASCII to octal, like so:

host # ./octala.pl -o shell.pl

or the opposite ( octal to ASCII conversion ):

host # ./octala.pl -a shell.pl.od <--- Assuming you're just running this script and accepting the default extension we popped on the end (BTW, by default, this line of code will add an ".as" extension to your file. The original is never destroyed. But that can be easily fixed by adding a line of code if you like. ...just don't forget to back up any file you might need!)

Below is a simple demonstration of the script in action, followed by the real deal. Note that we only substitute four characters that aren't "representable" (SPC = a space, HT = a tab, LF = a line feed, CR = a carriage return -- actually the CR and LF are both replaced with a new-line).

Here's to people not knowing what you're up to ;)

Cheers,

Ex:

host # cat shell.pl
<--- This script is one of our old ones with some lines chopped off, so it probably won't run :)

#!/usr/bin/perl

if ( $port =~ /\D/) {
$port = getservbyname($port, $protocol) || die "getservbyname ${port}/$protocol\n";;
}
$inet_address = inet_aton($host) || die "inet_aton: ${host}\n";
$port_address = sockaddr_in($port, $inet_address);
$protocol_num = getprotobyname('$protocol');

while (1) {
$shell_shock=accept(NEWSOCKET, SOCKET)|| die "accept $!\n";
dup2(STDERR,2);
system("/bin/sh -i");
close($shell_shock);
}
exit;


host # ./octala -o shell.pl <--- Here we convert the file to octal, and strip out the offset field.

host # cat shell.pl.od
043 041 057 165 163 162 057 142 151 156 057 160 145 162 154 012
012 151 146 040 050 040 044 160 157 162 164 040 075 176 040 057
134 104 057 051 011 173 012 011 044 160 157 162 164 040 075 040
147 145 164 163 145 162 166 142 171 156 141 155 145 050 044 160
157 162 164 054 040 044 160 162 157 164 157 143 157 154 051 040
174 174 040 144 151 145 040 042 147 145 164 163 145 162 166 142
171 156 141 155 145 040 044 173 160 157 162 164 175 057 044 160
162 157 164 157 143 157 154 134 156 042 073 073 012 175 012 044
151 156 145 164 137 141 144 144 162 145 163 163 040 075 040 151
156 145 164 137 141 164 157 156 050 044 150 157 163 164 051 040
174 174 040 144 151 145 040 042 151 156 145 164 137 141 164 157
156 072 040 044 173 150 157 163 164 175 134 156 042 073 012 044
160 157 162 164 137 141 144 144 162 145 163 163 040 075 040 163
157 143 153 141 144 144 162 137 151 156 050 044 160 157 162 164
054 040 044 151 156 145 164 137 141 144 144 162 145 163 163 051
073 012 044 160 162 157 164 157 143 157 154 137 156 165 155 040
075 040 147 145 164 160 162 157 164 157 142 171 156 141 155 145
050 047 044 160 162 157 164 157 143 157 154 047 051 073 012 012
167 150 151 154 145 040 050 061 051 011 173 012 011 044 163 150
145 154 154 137 163 150 157 143 153 075 141 143 143 145 160 164
050 116 105 127 123 117 103 113 105 124 054 040 123 117 103 113
105 124 051 174 174 040 144 151 145 040 042 141 143 143 145 160
164 040 044 041 134 156 042 073 012 011 144 165 160 062 050 123
124 104 105 122 122 054 062 051 073 012 011 163 171 163 164 145
155 050 042 057 142 151 156 057 163 150 040 055 151 042 051 073
012 011 143 154 157 163 145 050 044 163 150 145 154 154 137 163
150 157 143 153 051 073 012 175 012 145 170 151 164 073 012

host # ./octala -a shell.pl.od
<--- and here we take that octal file and translate it back to ASCII

host # cat shell.pl.od.as
#!/usr/bin/perl

if ( $port =~ /\D/) {
$port = getservbyname($port, $protocol) || die "getservbyname ${port}/$protocol\n";;
}
$inet_address = inet_aton($host) || die "inet_aton: ${host}\n";
$port_address = sockaddr_in($port, $inet_address);
$protocol_num = getprotobyname('$protocol');

while (1) {
$shell_shock=accept(NEWSOCKET, SOCKET)|| die "accept $!\n";
dup2(STDERR,2);
system("/bin/sh -i");
close($shell_shock);
}
exit;


host # diff shell.pl shell.pl.od.as <--- Cool - They're exactly the same :)


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/usr/bin/perl

#
# octala.pl - convert files from octal to ASCII or reverse
# Usage: octala [-o|-a] input_file
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

if ( $#ARGV != 1 ) {
print "Usage: $0 [-o|-a] input_file\n";
exit(1);
}

$oct_or_asc = $ARGV[0];
$input_file = $ARGV[1];

if ( ! -f $ARGV[1] ) {
print "File $input_file can't be found! Over\n";
exit(2);
}

$tmp=$$;

%otoa = qw(000 NUL 001 SOH 002 STX 003 ETX 004 EOT 005 ENQ 006 ACK 007 BEL 010 BS 011 HT 012 LF 013 VT 014 FF 015 CR 016 SO 017 SI 020 DLE 021 DC1 022 DC2 023 DC3 024 DC4 025 NAK 026 SYN 027 ETB 030 CAN 031 EM 032 SUB 033 ESC 034 FS 035 GS 036 RS 037 US 040 SPC 041 ! 042 " 043 # 044 $ 045 % 046 & 047 ' 050 ( 051 ) 052 * 053 + 054 , 055 - 056 . 057 / 060 0 061 1 062 2 063 3 064 4 065 5 066 6 067 7 070 8 071 9 072 : 073 ; 074 < 075 = 076 > 077 ? 100 @ 101 A 102 B 103 C 104 D 105 E 106 F 107 G 110 H 111 I 112 J 113 K 114 L 115 M 116 N 117 O 120 P 121 Q 122 R 123 S 124 T 125 U 126 V 127 W 130 X 131 Y 132 Z 133 [ 134 \ 135 ] 136 ^ 137 _ 140 ` 141 a 142 b 143 c 144 d 145 e 146 f 147 g 150 h 151 i 152 j 153 k 154 l 155 m 156 n 157 o 160 p 161 q 162 r 163 s 164 t 165 u 166 v 167 w 170 x 171 y 172 z 173 { 174 | 175 } 176 ~ 177 DEL);

if ( $oct_or_asc eq "-o" ) {
system("od -b $input_file >odfile.$tmp");
open(TMPODFILE, "<odfile.$tmp");
@TMPODFILE = <TMPODFILE>;
close(TMPODFILE);

open(NEWODFILE, ">$input_file.od");
foreach $odline (@TMPODFILE) {
if ( $odline =~ /^\w+$/ ) {
next;
}
$odline =~ s/^\w+ //;
print NEWODFILE $odline;
}
close(NEWODFILE);
unlink("odfile.$tmp");
} elsif ( $oct_or_asc eq "-a" ) {
open(TMPASFILE, "<$input_file");
@TMPASFILE = <TMPASFILE>;
close(TMPASFILE);
open(NEWASFILE, ">$input_file.as");
foreach $asline (@TMPASFILE) {
@asline = split(" ", $asline);
foreach $aschunk (@asline) {
$fixedaschunk = $otoa{$aschunk};
$fixedaschunk =~ s/SPC/ /;
$fixedaschunk =~ s/HT/\t/;
$fixedaschunk =~ s/LF/\n/;
$fixedaschunk =~ s/CR/\n/;
print NEWASFILE $fixedaschunk;
}
}
close(NEWASFILE);
unlink("odfile.$tmp");
} else {
print "Unrecognized option: $oct_or_asc\n";
exit(3);
}


, Mike

Thursday, May 1, 2008

Using OD To Find Bad Characters In Files On Linux Or Unix

Hey there,

Today we're going to take a look at a command called "od" (short for "octal dump") and the sometimes elusive search for, and destruction of, those "mystery characters" that make your scripts not run correctly. Sure, there are programs out there like dos2unix that pretty much take care of this problem for you, but that's like taking candy from a baby ;) And there's always the possibility that they won't be able to find the bizarre character you're trying to get rid of. What do you do then?

We covered the other side of this issue in an earlier post on adding real control characters to your files. Now, it's time to finally undo that damage ;)

od is a great utility for finding out if there really are bad characters in your file in the first place. "cat -v" works, too, but you can only trust it as much as you trust your terminal settings. I generally assume my tty settings are correct, but they could be up to just about anything ;) For today's purposes, "cat -v" serves as an excellent corollary to od's output and, hopefully, makes it even easier to understand.

For instance, if you're looking for a control character in a file (we'll say ^M, since that one's the most popular), cat -v does a great job of bringing it out in the open, like this:

host # cat file
def
host # cat -v file
abc^Mdef


od can do the same thing, if only slightly differently:

host # od -c file
0000000 a b c \r d e f \n
0000010


Notice that, with the "-c" flag used, we can make the "^M" show up as an easily identifiable "\r". We also get to see what having that "actual" ^M in our file has done. Notice the second line in the "od" output (00000010). The first column of od's output is the byte-offset of the line. The first line, naturally starts at an offset of 0 and, since od only grabs the amount of bytes per line that you can actually see in the output, the second entry (the offset of the 6 letters and the new-line) should be 7 (This is because the numbering starts at zero - just in case you didn't know. No offense if you did ;). Another clue that something is amiss.

This is what the file would look like normally, using the same example as above, but without the ^M inserted:

host # cat file
abcdef
host # cat -v file
abcdef
host # od -c file
0000000 a b c d e f \n
0000007


Perfect :) The really nice thing about using od with the "-c" flag is that it prints out all regular characters in ASCII, which, studies have shown, most humans prefer reading ;) Only when od runs into a character it doesn't understand, does it do any substitution, as with the ^M. Below is the basic table of conversions the "-c" flag will do automatically:

null \0
backspace \b
form-feed \f
new-line \n
return \r
tab \t


After that, if od doesn't recognize a regular ASCII character, it will finally live up to its name and dump the octal value (of course, we could have forced it to do this all along, but we're trying to make this command seem accessible ;). Here's an example of what we see when od can't translate for us ASCII folks anymore:

host # cat file
bcdef
host # cat -v file
a^?bcdef
host # od -c file
0000000 a 177 b c d e f \n
0000010


Okay. So, in this instance, "cat -v" shows us what looks like a "backspace" or "erase" character (^?). od's output is slightly different. The "what would be the next line" offset is at 10. That's the sum of all 6 ASCII characters, the new-line and the 3-digit octal code, so everything's in order (even though it's not right).

The really sweet thing is that you, armed with the knowledge od has provided, can remove the character from the file with tr (or your fancy file/character manipulation command of choice) using the octal code, which makes it completely unnecessary for you to remember some bizarre symbol ;)

host # cat file
bcdef
host # cat -v file
a^?bcdef
host # od -c file
0000000 a 177 b c d e f \n
0000010
host # tr -d '\177' <file
abcdef
host # tr -d '\177' <file >file2
<--- Where the magic happens...
host # cat file2
abcdef
host # cat -v file2
abcdef
host # od -c file2
0000000 a b c d e f \n
0000007


Hope this makes the crusty old "od" command seem less daunting. You can do a whole lot more with it, of course, but there will be plenty of time for that later :)

Cheers,

, Mike

Wednesday, December 5, 2007

Converting Alpha Permissions To Octal

Today, I thought I'd put together a little script (written in ksh, but easily portable to sh or Perl) to address a common concern amongst users of most Unix/Linux-based systems; how to translate alpha permissions (like -rwxrwxr-x) to octal (like 775). This issue has been addressed, to some degree by all flavors of *nix, in that you can use the chmod command either way. For instance, if you had a file with 775 (or -rwxrwxr-x) permissions, you could add "other" (or "world") write permissions to the file by doing:

chmod 777 FILENAME or chmod o+w FILENAME

Both ways are equally effective and, you might even say that their are some advantages to using one over the other. For instance, with octal permissions, to add "group" write permissions to a 755 file, you would have to remember to retain the original modes when executing chmod. If you just did:

chmod 070

It would cause serious issues (755 becomes 070)! It's much easier to remember:

chmod g+w

Which would add the write permissions for "group" ownership and not affect the other bits (755 becomes 775)!

One example of a situation where you absolutely "must" use alpha notation with chmod is an old bug in Solaris (that exists even today, in Solaris 10 - latest patch release), whereby you "cannot" set the "group ID" bit (more commonly referred to as setgid) on a directory with octal notation. For instance:

xyx.com[/export/home/user] # chmod 2755 bob
xyz.com[/export/home/user] # ls -ld bob
drwxr-xr-x 2 root other 512 Dec 3 16:34 bob
<--- No Good.

xyz.com[/export/home/user] # chmod g+s bob
xyz.com[/export/home/user] # ls -ld bob
drwxr-sr-x 2 root other 512 Dec 3 16:34 bob
<--- Now it's working :)

The only other thing left to explain before we get to the script (assuming you're still reading this and haven't just blown to the bottom already ;) is the common misconception that there are only 3 octal numerics in a file's (or anything's) permissions. This may not be news to most folks, but there are actually 4 octals. The last 3 are the ones that are usually represented; as in 755. The fourth, which is actually the first, is usually an implied 0. For example, 755 is the same as 0755. The first (usually omitted) bit has a potential of 4 different values (0, 1, 2 and 4 or any combination thereof), just like the rest of them do, although they take on a unique significance.

For the last 3 bits (user, group and other permissions) the translation is the same. They can have values of 0-7 for each. 000 would equal ---------, while 777 would equal rwxrwxrwx The permissions are compounded by adding the value of the bits. So 0 results in a "---", 1 results in "--x", 2 results in "-w-" and 4 results in "r--". Compounding them is just a matter of addition. So if the value of the user bit was 6, you could only acheive that result (from your selection of 0, 1, 2 and 4) by adding 4 and 2. By merging the above descriptions, 6 would have a value of "rw-" (4 "r--" plus 2 "-w-").

The first (usually hidden) bit is reserved for activating the setuid bit (value of 4), setgid bit (value of 2) and sticky bit (value of 1). As always, 0 equals nothing. These bits are special because, although they'll appear as numerals in your 4 bit octal notation, they appear in different places when using alpha notation. The setuid bit (Value of 4) shows up in the "user" permissions as an "s" where the "x" would normally be (like rws instead of rwx). The same is true of the setgid bit (Value of 2), although it shows up in the "group" permissions. The sticky bit (Value of 1) shows up in the "other" permissions as a "t" (like rwt instead of rwx). In a future post, we'll explore how the bit permissions "actually" modify the files and/or directories they are applied to (This differs for all 4 bits, and is another post in itself).

Below is the initial script to convert all of the alpha permissions you'd see (using "ls -l") on any file(s), to their corresponding octal notation. This can more easily be applied in reverse (which is probably why I wrote it this way first). Note that this was also created using what I call "brute force scripting"; the fastest means to an acceptable end. Feel free to doll it up and make it work better for you. As it is, it will accept any option that the standard "ls" would. So, if you called it "lso," you could execute "./lso /export/home/user" or "./lso -R /export/home/user" or just plain "./lso" -- I'll be using this script (since it has a number of different scripting constructs in it) to demonstrate how to port shell scripts to Perl in a future post, also.

Best wishes :)


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/bin/ksh

#
# 2007 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

arg=$@

ls -l $arg|awk '{ if ($0 !~ /^$/) print $1 " " $NF}'|grep -v "^total"|while read perms filename
do
if [ $filename = $perms ]
then
print "$filename = Directory"
continue
fi
bit_counter=10
oct_counter=0
user_bits=0
group_bits=0
other_bits=0
s_bits=0
set -A oct_array
oct_split=`print -- $perms|sed 's/\([-bcdDlprstwx]\)/\1 /g'`
for x in `print -- $oct_split`
do
oct_array[$oct_counter]=$x
let oct_counter=$oct_counter+1
done
while [ $bit_counter -gt 0 ]
do
case $bit_counter in
'9' ) if [ "${oct_array[$bit_counter]}" = "x" ]
then
let other_bits=$other_bits+1
elif [ "${oct_array[$bit_counter]}" = "t" ]
then
let s_bits=$s_bits+1
let other_bits=$other_bits+1
fi
let bit_counter=$bit_counter-1;;
'8' ) if [ "${oct_array[$bit_counter]}" = "w" ]
then
let other_bits=$other_bits+2
fi
let bit_counter=$bit_counter-1;;
'7' ) if [ "${oct_array[$bit_counter]}" = "r" ]
then
let other_bits=$other_bits+4
fi
let bit_counter=$bit_counter-1;;
'6' ) if [ "${oct_array[$bit_counter]}" = "x" ]
then
let group_bits=$group_bits+1
elif [ "${oct_array[$bit_counter]}" = "s" ]
then
let s_bits=$s_bits+2
let group_bits=$group_bits+1
fi
let bit_counter=$bit_counter-1;;
'5' ) if [ "${oct_array[$bit_counter]}" = "w" ]
then
let group_bits=$group_bits+2
fi
let bit_counter=$bit_counter-1;;
'4' ) if [ "${oct_array[$bit_counter]}" = "r" ]
then
let group_bits=$group_bits+4
fi
let bit_counter=$bit_counter-1;;
'3' ) if [ "${oct_array[$bit_counter]}" = "x" ]
then
let user_bits=$user_bits+1
elif [ "${oct_array[$bit_counter]}" = "s" ]
then
let s_bits=$s_bits+4
let user_bits=$user_bits+1
fi
let bit_counter=$bit_counter-1;;
'2' ) if [ "${oct_array[$bit_counter]}" = "w" ]
then
let user_bits=$user_bits+2
fi
let bit_counter=$bit_counter-1;;
'1' ) if [ "${oct_array[$bit_counter]}" = "r" ]
then
let user_bits=$user_bits+4
fi
let bit_counter=$bit_counter-1;;
0 ) let bit_counter=$bit_counter-1;;
* ) let bit_counter=$bit_counter-1;;
esac
done
octal=${s_bits}${user_bits}${group_bits}${other_bits}
print -- "$octal $filename"
done


, Mike