Perl hex replacement (s///g) has no effect when used on an ISO file

267 Views Asked by At

I am trying to install a Live Kali Linux on a USB without the two beeps at booting. I found the fifth post in this thread that says:

This can also depend on UEFI vs BIOS

For BIOS you can use the following PERL script on the ISO file itself and it will take care of any place ^G exists in the iso:

perl -p -i -e 's;\x6d\x65\x6e\x75\x07;\x6d\x65\x6e\x75\x20;g' your-kali.iso

The beep was added for accessibility to the UEFI boot menu as well so you may still get the beep. To remove that you must edit grub.cfg and comment out or remove the following two lines:

insmode play
play 960 440 1 0 4 440 1

I used live build to make the changes to grub.cfg, generated the iso, and then ran the perl script prior to flashing to the usb.

I managed to delete the (x07) byte for BIOS with the given Perl script, so I tried the same thing with "insmode play play 60 440 1 0 4 440 1" (I opened grub.cfg in a hex editor, copied the hex of this string, 696E736D6F6420706C61790A706C61792039363020343430203120302034203434302031, and put 20 in the place of every byte).

I ran this script perl -p -i -e 's;\x69\x6e\x73\x6d\x6f\x64\x20\x70\x6c\x61\x79\x0a\x70\x6c\x61\x79\x20\x39\x36\x30\x20\x34\x34\x30\x20\x31\x20\x30\x20\x34\x20\x34\x34\x30\x20\x31;\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20;g' your-kali.iso.

But the string is still in the iso.

Why does it not get replaced?

2

There are 2 best solutions below

0
On BEST ANSWER

You are reading a line at a time, which is defined as a sequence of byte up until the line feed (inclusive). So $_ is never going to have a line feed anywhere but at the end.

perl -i -pe'
   s/^i(?=nsmode play$)/#/;
   s/^p(?=lay 960 440 1 0 4 440 1$)/#/;
' your-kali.iso

That comments out the lines independently. If you want to replace them as a set, you'll need a buffer.

perl -i -pe'
   if (/^insmode play$/) {
      $buf = $_;
      $_ = "";
      next;
   }

   $_ = $buf . $_;
   $buf = "";
   s/^insmode play\nplay 960 440 1 0 4 440 1\n/#nsmode play\n#lay 960 440 1 0 4 440 1\n/;

   END { print $buf }
' your-kali.iso
2
On

perl -p -e CODE generally runs the specified CODE on each line of the input, where lines (on POSIX-y systems) are separated by newline (\x0a) characters, so this code will not allow you to make substitutions where the search pattern contains \x0a.

My approach (and this is Perl, so there are many ways to do this) would be more like

perl -p -i -e '$_="" if $_ eq "insmod play\n" || 
               $_ eq "play 960 440 1 0 4 440 1\n"' your-kali.iso

This replaces the input line with the empty string when the line matches one of two target patterns (that is, removes them from the output, not replaces them with strings of spaces).