End-of-Transmission character as an IFS - sh

I have a Bourne shell script which uses End-of-Transmission character as an IFS:
ASCII_EOT=`echo -e '\004'`
while IFS="$ASCII_EOT" read DEST PASSWORD; do
...
done
How does the EOT behave as an IFS? Or what kind of input might the read expect?

It's an ASCII character just like ,; it just isn't printable.
$ printf 'foo\004bar' > tmp.txt
$ hexdump -C tmp.txt
00000000 66 6f 6f 04 62 61 72 0a |foo.bar.|
00000008
$ IFS=$(printf '\004') read f1 f2 < tmp.txt
$ echo "$f1"
foo
$ echo "$f2"
bar

Related

how to find offset of a pattern from binary file (without grep -b)

I want to get a byte offset of a string pattern from a binary file on embedded linux platform.
If I can use "grep -b" option, It would be best way but It is not supported on my machine.
machine does not support
ADDR=`grep -oba <pattern string> <file path> | cut -d ":" -f1`
Here the manual of grep command on the machine.
root# grep --help
BusyBox v1.29.3 () multi-call binary.
Usage: grep \[-HhnlLoqvsriwFE\] \[-m N\] \[-A/B/C N\] PATTERN/-e PATTERN.../-f FILE \[FILE\]...
Search for PATTERN in FILEs (or stdin)
-H Add 'filename:' prefix
-h Do not add 'filename:' prefix
-n Add 'line_no:' prefix
-l Show only names of files that match
-L Show only names of files that don't match
-c Show only count of matching lines
-o Show only the matching part of line
-q Quiet. Return 0 if PATTERN is found, 1 otherwise
-v Select non-matching lines
-s Suppress open and read errors
-r Recurse
-i Ignore case
-w Match whole words only
-x Match whole lines only
-F PATTERN is a literal (not regexp)
-E PATTERN is an extended regexp
-m N Match up to N times per file
-A N Print N lines of trailing context
-B N Print N lines of leading context
-C N Same as '-A N -B N'
-e PTRN Pattern to match
-f FILE Read pattern from file
Since that option isn't available, I'm looking for an alternative.
the combination of hexdump and grep can be also useful
such as
ADDR=`hexdump <file path> -C | grep <pattern string> | cut -d' ' -f1`
But if pattren spans multiple lines, it will not be found.
Is there a way to find the byte offset of a specific pattern with a Linux command?
Set the pattern as the record separator in awk. The offset of the occurrence is the length of the first record. BusyBox awk treats RS as an extended regular expression, so add backslashes before any of .[]\*+?^$ in the pattern string.
<myfile.bin awk -v RS='pattern' '{print length($0); exit}'
If the pattern contains a null byte, you need a little extra work. Use tr to exchange null bytes with some byte value that doesn't appear in the pattern. For example, if the pattern's hex dump is 00002a61:
<myfile.bin tr '\0!' '!\0' | awk -v RS='!!-A' '{print length($0); exit}'
If the pattern is not found, this prints the length of the whole file. So if you aren't sure whether the pattern is present, you need again some extra work. Append some text that can't be part of a pattern match to the file, so that you know that if there's a match, it won't be at the very end of the file. Then, if the pattern is present, the file will contain at least two records. But if the pattern is not present, the file only contains the first record (without a record separator after it).
{ cat myfile.bin; echo garbage; } |
awk -v RS='pattern' '
NR==1 {n = length($0)}
NR==2 {print n; found = 1; exit}
END {exit !found}
'
Something like this?
hexdump -C "$file" |
awk -v pattern="$pattern" 'residue { matched = ($0 ~ "\\|" residue)
if (matched) print $1; residue = ""; if (matched) next }
$0 ~ pattern { print $1 }
{ for(i=length(pattern)-1; i>0; i--)
if ($0 ~ substr(pattern, 1, i) "\\|$") { residue=substr(pattern, i+1); break } }'
The offset is just the first field from the hexdump output; if you need the precise location of the match, this requires some additional massaging to figure out the offset to add to the address, or subtract if it was wrapped.
Briefly tested in a clean-slate Busybox Docker container where hexdump -C output looks like this:
/ # hexdump -C /etc/resolv.conf
00000000 23 20 44 4e 53 20 72 65 71 75 65 73 74 73 20 61 |# DNS requests a|
00000010 72 65 20 66 6f 72 77 61 72 64 65 64 20 74 6f 20 |re forwarded to |
00000020 74 68 65 20 68 6f 73 74 2e 20 44 48 43 50 20 44 |the host. DHCP D|
00000030 4e 53 20 6f 70 74 69 6f 6e 73 20 61 72 65 20 69 |NS options are i|
00000040 67 6e 6f 72 65 64 2e 0a 6e 61 6d 65 73 65 72 76 |gnored..nameserv|
00000050 65 72 20 31 39 32 2e 31 36 38 2e 36 35 2e 35 0a |er 192.168.65.5.|
00000060 20 | |

Extra computation steps on adding brackets?

Ok, so just a question popped up in my mind while writing some code.
Does the CPU compute this
gap = (gap*3) + 1;
with the same efficiency as the below expression without the brackets?
gap = gap*3 + 1;
Update to be more clarifying:
Often while writing arithmetic expressions, we tend to add brackets to make the code easier to read, even if the brackets do not change what the expression evaluates to. So the question is, does adding such brackets have any affect on the performance?
As mentioned above in the comments:
file test1.c:
int main(void)
{
int gap = 1;
gap = (gap*3) + 1;
return gap;
}
file test2.c:
int main(void)
{
int gap = 1;
gap = gap*3 + 1;
return gap;
}
Using gcc and its -S option ("Compile only; do not assemble or link"): gcc -S test1.c && gcc -S test2.c. Comparing those two files:
$ diff test1.s test2.s
1c1
< .file "test1.c"
---
> .file "test2.c"
(i.e. only the file names differ in the first line)
When you still don't believe me (for this particular example), then you can further compile & assemble: gcc test1.c -o test1 && gcc test2.c -o test2. Comparing those binary files (or rather ELF executables) will give you one byte difference, i.e. the file name again:
$ hexdump -C test1 > hex1.txt && hexdump -C test2 > hex2.txt
$ diff hex1.txt hex2.txt
387c387
< 00001fc0 79 5f 65 6e 74 72 79 00 74 65 73 74 31 2e 63 00 |y_entry.test1.c.|
---
> 00001fc0 79 5f 65 6e 74 72 79 00 74 65 73 74 32 2e 63 00 |y_entry.test2.c.|

Modifying an input string using sed

Using sed, how can I change an input string like 9872 to 39 38 37 32 i.e. insert digit 3 before and a space after each digit of entered string 9872.
Input string:
9872
Required output:
39 38 37 32
echo 9872 | sed 's/./3&\ /g'
And just for completeness, a more general way using regex references.
echo 9872 | sed -r 's/([[:digit:]])/3\1 /g'
$ echo "9872" | sed 's/[0-9]/3& /g'
39 38 37 32

64 Bit "network" (big-endian) order Integer in Perl

Similar to how you can use pack's:
N An unsigned long (32-bit) in "network" (big-endian) order.
Is there any method for packing a 64-bit integer in "network" (big-endian) order in Perl?
If your system supports the Q pack format, you can use Q> to get big-endian (since Perl 5.9.2):
% perl -e 'print pack("Q>", 1)' | hexdump -C
00000000 00 00 00 00 00 00 00 01 |........|

Insert shell code

I got a small question.
Say I have the following code inside a console application :
printf("Enter name: ");
scanf("%s", &name);
I would like to exploit this vulnerability and enter the following shell code (MessageboxA):
6A 00 68 04 21 2F 01 68 0C 21 2F 01 6A 00 FF 15 B0 20 2F 01
How can I enter my shell code (Hex values) through the console ?
If I enter the input as is, it treats the numbers as chars and not as hex values.
Thanks a lot.
You could use as stdin a file with the desired content or use the echo command.
Suppose your shell code is AA BB CC DD (obviously this is not a valid shellcode):
echo -e "\xAA\xBB\xCC\xDD" | prog