将dd的输出读入shell脚本变量

时间:2017-10-27 11:30:38

标签: linux bash shell dd

作为shell脚本的新手,我拼凑了以下内容来逐行搜索/dev/sdd1来查找字符串。如何将扇区数据导入$HAYSTACK变量?

#!/bin/bash

HAYSTACK=""
START_SEARCH=$1
NEEDLE=$2
START_SECTOR=2048
END_SECTOR=226512895+1
SECTOR_NUMBER=$((START_SEARCH + START_SECTOR))
while [  $SECTOR_NUMBER -lt $END_SECTOR ]; do
    $HAYSTACK=`dd if=/dev/sdd1 skip=$SECTOR_NUMBER count=1 bs=512`
    if [[ "$HAYSTACK" =~ "$NEEDLE" ]]; then
        echo "Match found at sector $SECTOR_NUMBER"
        break
    fi
    let SECTOR_NUMBER=SECTOR_NUMBER+1 
done

更新

目的不是制作一个完美的脚本来处理碎片化的文件场景(我怀疑这是可能的)。

在我的情况下,无法区分带有空值的stings也不是问题。

如果您可以将管道建议扩展为答案,那就足够了。谢谢!

背景

我设法擦除了我的www文件夹,并且一直在努力恢复尽可能多的源文件。我用Scalpel来恢复我的php和html文件。但我可以在我的Ubuntu 16.04上运行的版本是Version 1.60,它不支持页眉/页脚中的正则表达式,因此我无法为css,js和json文件制作好的模式。

我记得搜索和查找我的文件的相当罕见的字符串,但不知道字符串可能在块中的哪个位置。我想出的解决方案是这个shell脚本从分区中读取块并查找子字符串,如果找到匹配则打印出LSB编号并退出。

2 个答案:

答案 0 :(得分:2)

  1. 如果搜索的项目是文本字符串,请考虑使用-t strings命令的选项打印偏移量的位置 找到字符串。由于strings并不关心数据的位置 from,它适用于dd的文件,块设备和管道输入。

    硬盘启动示例:

    sudo strings -t d /dev/sda | head -5
    

    输出:

        165 ZRr=
        286 `|f 
        295 \|f1
        392 GRUB 
        398 Geom
    

    而不是head可以通过管道传输到grep -m 1 GRUB,而不是sudo strings -t d /dev/sda | grep -m 1 GRUB 只会输出第一行“ GRUB ”:

        392 GRUB 
    

    输出:

    bash

    从那里,s=GRUB ; sudo strings -t d /dev/sda7 | grep "$s" | while read a b ; do n=${b%%${s}*} printf "String %-10.10s found %3i bytes into sector %i\n" \ "\"${b#${n}}\"" $(( (a % 512) + ${#n} )) $((a/512 + 1)) done | head -5 可以做很多事情。此代码找到前5个 我的启动分区 / dev / sda7 上的“GRUB”实例:

    String "GRUB Boot found   7 bytes into sector 17074
    String "GRUB."    found 548 bytes into sector 25702
    String "GRUB."    found 317 bytes into sector 25873
    String "GRUBLAYO" found 269 bytes into sector 25972
    String "GRUB"     found 392 bytes into sector 26457
    

    输出(这里的扇区号是相对于开头的 分区):

    dd

    需要注意的事项:

    • 不要使用strings进行基于strings的单块搜索,因为如果字符串跨越两个块,它将会失败。使用strings -t d获取 偏移首先,然后将该偏移转换为块,(或 扇区)。

    • grep可以返回大字符串,“needle”可能是字符串中的几个字节,在这种情况下,偏移量将是 大字符串的开头,而不是bash字符串(或 “针”)。上述$n代码允许使用sudo rafind2 -Xs GRUB /dev/sda7 | head -7 0x856207 - offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF 0x00856207 4752 5542 2042 6f6f 7420 4d65 6e75 006e GRUB Boot Menu.n 0x00856217 6f20 666f 6e74 206c 6f61 6465 6400 6963 o font loaded.ic 0x00856227 6f6e 732f 0069 636f 6e64 6972 0025 733a ons/.icondir.%s: 0x00856237 2564 3a25 6420 6578 7072 6573 7369 6f6e %d:%d expression 0x00856247 2065 7870 6563 7465 6420 696e 2074 expected in t 计算修正后的偏移量。

  2. Lazy all-in-one util rafind2方法。例如,搜索 像以前一样在 / dev / sda7 上的第一个“ GRUB ”实例:

    bash

    输出:

    sed

    对于某些stringss=GRUB ; sudo rafind2 -Xs "$s" /dev/sda7 | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" | sed -r -n 'h;n;n;s/.{52}//;H;n;n;n;n;g;s/\n//p' | while read a b ; do printf "String %-10.10s\" found %3i bytes into sector %i\n" \ "\"${b}" $((a%512)) $((a/512 + 1)) done | head -5 ,可以将输出重新编写为相同的内容 格式为sed输出:

    rafind2

    第一个String "GRUB Boot" found 7 bytes into sector 17074 String "GRUB....L" found 36 bytes into sector 25703 String "GRUB...LI" found 317 bytes into sector 25873 String "GRUBLAYO." found 269 bytes into sector 25972 String "GRUB .Geo" found 392 bytes into sector 26457 实例是从jfs' answer to "Program that passes STDIN to STDOUT with color codes stripped?"借来的 from django.db import models from django.contrib.auth.models import AbstractUser from apps.Tags.models import Tags class Puesto(models.Model): nombre_puesto = models.CharField(max_length=50) etiquetas = models.ManyToManyField(Tags, blank = True) def __str__(self): return '{}'.format(self.nombre_puesto) class Perfil(AbstractUser): nom_puesto = models.ForeignKey(Puesto, blank = True) def __str__(self): return '{}'.format(self.username) 输出非文本颜色代码。

    输出:

    class Tags(models.Model):
        nombre = models.CharField(max_length=20)
    
        def __str__(self):
            return '{}'.format(self.nombre)
    

答案 1 :(得分:1)

你有没有想过这样的

cat /dev/sdd1 | od -cv | sed s'/[0-9]* \(.*\)/\1/' | tr -d '\n' | sed s'/  F   l/  F   l/'g  > v1
cat /dev/sdd1 | od -cv | sed s'/[0-9]* \(.*\)/\1/' | tr -d '\n' | sed s'/  F   l/x F   l/'g  > v2
cmp -lb v1 v2

例如将其应用于.pdf文件

od -cv phase-2-guidance.pdf  | sed s'/[0-9]* \(.*\)/\1/' | tr -d '\n' | sed s'/  F   l/  F   l/'g  > v1
od -cv phase-2-guidance.pdf  | sed s'/[0-9]* \(.*\)/\1/' | tr -d '\n' | sed s'/  F   l/  x   l/'g  > v2
cmp -l v1 v2

给出输出

   228 106 F    170 x
 23525 106 F    170 x
 37737 106 F    170 x
 48787 106 F    170 x
 52577 106 F    170 x
 56833 106 F    170 x
 57869 106 F    170 x
118322 106 F    170 x
119342 106 F    170 x

其中第一列中的数字将是要搜索的模式开始的字节偏移量。这些字节偏移量乘以4,因为od对每个字节使用4个字节。

单行表单(在bash shell中),不写大型临时文件,将是

od -cv phase-2-guidance.pdf  | sed s'/[0-9]* \(.*\)/\1/' | tr -d '\n' | sed s'/  F   l/  x   l/'g | cmp -lb - <(od -cv phase-2-guidance.pdf  | sed s'/[0-9]* \(.*\)/\1/' | tr -d '\n' | sed s'/  F   l/  F   l/'g )

这避免了需要将/ dev / sdd1的内容写入某处的临时文件。

以下示例在USB驱动器设备上查找 PDF 并除以4和512以获取块编号

dd if=/dev/disk5s1 bs=512 count=100000 | od -cv | sed s'/[0-9]* \(.*\)/\1/' | tr -d '\n'  | cmp -lb - <(dd if=/dev/disk5s1 bs=512 count=100000 | od -cv | sed s'/[0-9]* \(.*\)/\1/' | tr -d '\n' | sed s'/P   D   F/x   D   F/'g ) | awk '{print int($1/512/4)}' | head -10

测试这个给出了

100000+0 records in
100000+0 records out
51200000 bytes transferred in 18.784280 secs (2725683 bytes/sec)
100000+0 records in
100000+0 records out
51200000 bytes transferred in 40.915697 secs (1251353 bytes/sec)
cmp: EOF on -
28913
32370
32425
33885
35097
35224
37177
38522
39981
41570

其中数字是512字节块编号。检查给出了

dd if=/dev/disk5s1 bs=512 skip=35224 count=1 | od -vc | grep P

0000340   \0  \0  \0 001   P   D   F       C   A   R   O  \0  \0  \0  \0

以下是一个实际的完整示例与磁盘相似并查找字符序列 live ,其中字符由NUL分隔

   dd if=/dev/disk5s1 bs=512 count=100000 | od -cv | sed s'/[0-9]* \(.*\)/\1/' | tr -d '\n' | sed s'/l  \\0   i  \\0   v  \\0   e/x  \\0   i  \\0   v  \\0   e/'g | cmp -lb - <(dd if=/dev/disk5s1 bs=512 count=100000 | od -cv | sed s'/[0-9]* \(.*\)/\1/' | tr -d '\n' | sed s'/l  \\0   i  \\0   v  \\0   e/l  \\0   i  \\0   v  \\0   e/'g )

请注意

  • 这不会处理分裂模式的非连续块的碎片。执行模式和替换的第二个sed可以替换为执行某些部分模式匹配的自定义程序,并在匹配字符数超过某个级别时进行替换。这可能会导致误报,但可能是处理碎片的唯一方法。