MacOS 也是把磁盘当成一个文件,也是可以使用 dd来读取,命行令行如下:
sudo dd if=/dev/disk2 bs=512 count=1 skip=100 of=sector_100.bin
这个就是读取 /dev/disk2这个磁盘每100这个sector, bs表示扇区大小是512.
但是你直接用读,应该是会出错的,如下:
dd: /dev/disk2: Resource busy
你需要把这个磁盘umount下来。
先使用diskutil list找到这磁盘的挂载
$ diskutil list
/dev/disk2 (synthesized):
#: TYPE NAME SIZE IDENTIFIER
0: APFS Container Scheme - +1.0 TB disk2
Physical Store disk1s2
1: APFS Volume p1t2 86.0 KB disk2s1
然后umount它的挂载
$ diskutil umount disk2s1
Volume p1t2 on disk2s1 unmounted
再执行就ok了。
$ sudo dd if=/dev/disk2 bs=512 count=1 skip=100 of=sector_100.bin
1+0 records in
1+0 records out
512 bytes transferred in 0.000225 secs (2274877 bytes/sec)
也可以使用grep命令去查找一个字符串出现的位置。
$ sudo grep -a -o -b 'EFI PART' /dev/nvme0n1
512:EFI PART
41661792:EFI PART
412075976:EFI PART
412207048:EFI PART
587940832:EFI PART
512110190080:EFI PART
按上面的原理,我们可以使用代码来一个一个扇区的查找我们丢失数据。我丢了一个android的签名keystore, 用遍了网上的工具都没有找到。我自己写了一个搜索扇区程序,尝试去恢复这个文件。代码如下:
//
// main.cpp
// recoverssd
#include <unistd.h>
#include <stdio.h>
#include <string>
#include <fcntl.h>
#include <iostream>
//00000000: feed feed 0000 0002 0000 0001 0000 0001 ................
//00000010: 0010 616e 6472 6f69 642e 6b65 7973 746f ..android.keysto
//00000020: 7265 0000 0192 d2fb 4242 0000 0502 3082 re......BB....0.
//00000030: 04fe 300e 060a 2b06 0104 012a 0211 0101 ..0...+....*....
//00000040: 0500 0482 04ea 0170 fa35 f5c6 96d6 3cd9 .......p.5....<.
//00000050: c181 8fb9 129c 64ab bfb2 357f a8db 7b36 ......d...5...{6
//00000060: cab8 d8d2 bd83 74a0 1310 b5f5 0c35 e78d ......t......5..
char keystoreHeader[] = "\xfe\xed\xfe\xed\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\x00\x10\x61\x6e\x64\x72\x6f\x69\x64\x2e\x6b\x65\x79\x73\x74\x6f\x72\x65";
#define needlesize 0x22
void BytesToStringA(char *&pBinStr, const unsigned char * pbin, int len,char seperator)
{
pBinStr = new char[len*3+2];
pBinStr[0]=0;
if(len==0 || pbin == NULL)
{
return;
}
int ncLen = 0;
for(int i=0;i<len;i++)
{
if(seperator!=0)
ncLen += sprintf(pBinStr+ncLen,"%02X%c",pbin[i],seperator);
else
ncLen += sprintf(pBinStr+ncLen,"%02X",pbin[i]);
}
}
const char* strnstr(const char *dst, int dlen, const char * src, int slen)
{
const char *s = NULL;
while (dlen >= slen) {
if (memcmp(src, dst, slen) == 0) {
s = dst;
break;
}
dst++;
dlen--;
}
return s;
}
int main(int argc, const char * argv[]) {
// insert code here...
std::string diskdev="/dev/disk2";
int fdes = open(diskdev.c_str(), O_RDONLY);
if (fdes < 0)
{
std::cout << "open dev failed " << diskdev << "\n";
return -1;
}
#define SECTOR_SIZE 1024*1024
char szSector[SECTOR_SIZE];
size_t numberdone=0;
while(true)
{
ssize_t nr = read(fdes, szSector, SECTOR_SIZE);
if(nr>0)
{
if(strnstr(szSector,SECTOR_SIZE, keystoreHeader,needlesize )!=NULL)
{
char *pBinStr = NULL;
BytesToStringA(pBinStr,(const unsigned char *)szSector,SECTOR_SIZE,' ');
if(pBinStr!=NULL)
{
printf("\n\n%s\n",pBinStr);
delete pBinStr;
}
return 0;
}
printf("\r read %ld",++numberdone);
}
else{
printf("read all \n");
}
}
std::cout << "open ok \n";
close(fdes);
return 0;
}