如何使用C/C ++在OS X中获得分区偏移? [英] How do I get the partition offset in OS X with C/C++?

查看:50
本文介绍了如何使用C/C ++在OS X中获得分区偏移?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用驱动器序列号+分区偏移量+分区大小创建自己的卷ID,但是我需要知道如何在OS X上获取分区信息.我(成功地)尝试了以下操作:

I want to create my own volume id using the drive serial + partition offset + partition size, but I need to know how to get the partition information on OS X. I have (unsucceedingly) tried the following:


int fd;
if ((fd = open("/dev/disk0s1", O_RDONLY|O_NONBLOCK)) >= 0) {
    struct hd_geometry geom;
    if (ioctl(fd, 0x0301, &geom) == 0){ //0x0301 is HDIO_GETGEO
        printf("Index = %u\n", geom.start);
    }
    close(fd);
}

但是即使成功了,它也是一个有缺陷的解决方案,因为 this 指出:hd_geometry.start是一个无符号的long,并且对于大小超过219 Gb的磁盘将不包含有意义的值".此外,我相信它需要管理权限,这也是不好的.还有其他方法吗?

But even if that were to succeed, it is a flawed solution since as this noted: hd_geometry.start is an unsigned long and "will not contain a meaningful value for disks over 219 Gb in size." Furthermore, I belive that it requires administrative rights, which is also bad. Is there any other way of doing this?

推荐答案

好的最后一点.因为您正在尝试读取原始磁盘,所以需要管理员权限.例如,您可能潜在地寻找写入私有密钥并以非特权用户身份读取它的区块,然后我们会在哪里?

Okay last point first. Requiring admin rights is necessary because you are trying to read a raw disk; you could for example potentially seek to a block where a private crypto key is written and read it as an unprivileged user and then where would we be?

第二,/dev/disk0s1只是一个分区,也是它的块设备版本.您需要读取磁盘的字符设备版本,该版本为/dev/rdisk0.

Second, /dev/disk0s1 is just a partition and it's also the block-device version of it. You need to read the character device version of the disk, which would be /dev/rdisk0.

第三,HDIO_GETGEO是一个Linux内核ioctl(尤其是考虑它的0x0301值),您不会因此而在Darwin上走得太远.查看有关磁盘IOCTL的< sys/disk.h> .我认为DKIOCGETFEATURES/DKIOCGETPHYSICALBLOCKSIZE等应该会让您前进.

Third, HDIO_GETGEO is a linux kernel ioctl (especially consider the 0x0301 value of it) you are not going to get far on Darwin with this; Have a look at <sys/disk.h> for the related disk IOCTLs. I think DKIOCGETFEATURES / DKIOCGETPHYSICALBLOCKSIZE etc should get you going.

如果您对这些概念有疑问,我强烈建议您在可以破坏的虚拟机中进行此开发,因为您不想意外地使用会损坏磁盘的IOCTL.

If you have trouble with these concepts I HIGHLY recommend doing this development in a virtual machine that you can clobber because you do NOT want to accidentally use an IOCTL which will screw up your disks.

所以你在 Mac OS X/Darwin 上工作;我们假设GUID分区表

So you are working on Mac OS X / Darwin; We'll assume GUID Partition Table

LBA ==逻辑块寻址...;1块= 512字节

LBA == Logical Block Addressing ... ; 1 block = 512 bytes

LBA 0 - Master Boot Record  (also contained old partition table) 
LBA 1 - GUID Partition Table (standard for OS X) 
LBA 2 - first 4 entries 
LBA 3 - 33 - next 124 entries making for a total of 128 entries
LBA 34 - Partition 1

您可以抓住第二个区块并开始跟踪信息

You can grab the second block and start tracing the information

http://en.wikipedia.org/wiki/GUID_Partition_Table 上进行阅读

它的定义很明确.GUID对整数值使用小尾数字节顺序(请参阅Wikipedia页面底部的示例)

It's quite well defined. GUID uses little-endian byte order for integer values (see examples at the bottom of the wikipedia page)

制作副本,以免与实际的磁盘搞混:

Make a copy so that you are not screwing with the actual disks:

dd if =/dev/rdisk0 of = fakedisk count = 33

dd if=/dev/rdisk0 of=fakedisk count=33

这将创建前33个块或磁盘的副本.使用fakedisk来测试您的程序.

this will create a copy of the first 33 blocks or a disk. Use fakedisk to test your program out.

如果您的磁盘使用MBR,请使用与GPT相同的概念

In case your disk uses MBR use the same concepts as GPT

http://en.wikipedia.org/wiki/Master_Boot_Record

对这些部门有很好的描述.

has excellent description of the sectors.

对fdisk转储进行压缩表明fdisk使用了上述方法.

dtrussing fdisk dump shows that fdisk uses the approach described above.

dtruss fdisk -d/dev/rdisk0

dtruss fdisk -d /dev/rdisk0

SYSCALL(args)            = return
open("/dev/dtracehelper\0", 0x2, 0x7FFF5CFDD5C0)                 = 3 0
__sysctl(0x7FFF5CFDD084, 0x2, 0x7FFF5CFDD070)            = 0 0
bsdthread_register(0x7FFF8BCA41D4, 0x7FFF8BCA41C4, 0x2000)               = 0 0
[[ .... content edited  ... ]]
open("/dev/rdisk0\0", 0x0, 0x7FFF5CFDDD7A)               = 3 0
fstat64(0x3, 0x7FFF5CFDDA10, 0x0)                = 0 0
fstat64(0x3, 0x7FFF5CFDDAC8, 0x0)                = 0 0
ioctl(0x3, 0x40086419, 0x7FFF5CFDDB60)           = 0 0
ioctl(0x3, 0x40046418, 0x7FFF5CFDDB5C)           = 0 0
close(0x3)               = 0 0
open("/dev/rdisk0\0", 0x0, 0x0)          = 3 0
fstat64(0x3, 0x7FFF5CFDDAD0, 0x0)                = 0 0
open("/dev/rdisk0\0", 0x0, 0x0)          = 4 0
fstat64(0x4, 0x7FFF5CFDDA80, 0x0)                = 0 0
lseek(0x4, 0x0, 0x0)             = 0 0
issetugid(0x102C22000, 0x3, 0x7FFF5CFDDC00)              = 0 0
geteuid(0x102C22000, 0x3, 0x0)           = 0 0
[[ tracing data suppressed ]]
read(0x4, "\0", 0x200)           = 512 0
close(0x4)               = 0 0
getrlimit(0x1008, 0x7FFF5CFDCFA8, 0x7FFF8BD0D470)                = 0 0
fstat64(0x1, 0x7FFF5CFDCEF8, 0x7FFF5CFDCFBC)             = 0 0
ioctl(0x1, 0x4004667A, 0x7FFF5CFDCF94)           = 0 0
write_nocancel(0x1, "1,625142447,0xEE,-,1023,254,63,1023,254,63\n\0", 0x2B)              = 43 0
write_nocancel(0x1, "0,0,0x00,-,0,0,0,0,0,0\n\0", 0x17)          = 23 0
write_nocancel(0x1, "0,0,0x00,-,0,0,0,0,0,0\n\0", 0x17)          = 23 0
write_nocancel(0x1, "0,0,0x00,-,0,0,0,0,0,0\n\0", 0x17)          = 23 0
close(0x3)               = 0 0

破译ioctl

我如何确定使用的是这些ioctl.

deciphering ioctls

How did I figure out that it was these ioctls that are used.

dtruss转储为:

dtruss dump is:

ioctl(0x3,0x40086419,0x7FFF5CFDDB60)= 0 0ioctl(0x3,0x40046418,0x7FFF5CFDDB5C)= 0 0

ioctl(0x3, 0x40086419, 0x7FFF5CFDDB60) = 0 0 ioctl(0x3, 0x40046418, 0x7FFF5CFDDB5C) = 0 0

和0x40086518对应于DKIOCGETBLOCKSIZE通过回溯disk.h(并注意_IOR在ioccom.h中扩展为_IOC)来收集此信息,并且后8位对应于IOCTL常量定义中的第二个数字.

and 0x40086518 corresponds to DKIOCGETBLOCKSIZE This is gleaned by tracing back disk.h (and noting that _IOR expands to _IOC in ioccom.h) and that the last 8 bits correspond to the second number in the IOCTL constant define.

#define DKIOCGETBLOCKSIZE _IOR('d',24,uint32_t)

在0x40086418中,尾随的18(十六进制)== 24(十进制)

in 0x40086418 the trailing 18(hex) == 24(dec)

所以现在我们注意到fdisk执行DKIOCGETBLOCKCOUNT和DKIOCGETBLOCKSIZE来获取物理范围,因为从技术上讲,您应该使用该结果来计算LBA偏移量(请参阅下面的解密ioctl)

So now that we note that fdisk performs DKIOCGETBLOCKCOUNT and DKIOCGETBLOCKSIZE  to get the physical extents because technically you should use the RESULT of that to figure out LBA offsets (see deciphering ioctls below)

这是fdisk的工作方式:

This is how fdisk is doing it:

open("/dev/rdisk0 \ 0&",0x0,0x0)= 4 0读取(0x4,"\ 0&",0x200)= 512 0关闭(0x4)= 0 0

open("/dev/rdisk0\0", 0x0, 0x0) = 4 0 read(0x4, "\0", 0x200) = 512 0 close(0x4) = 0 0

您可以效仿,确保将 0x200 替换为实际块大小.

You can follow suit make sure you replace the 0x200 with the actual block size.

此外,如果您要使用上面的dd命令进行复制,请使用此处显示的块大小.

Also, if you're going to use the dd command above to make a copy use the block size as it comes out here.

这篇关于如何使用C/C ++在OS X中获得分区偏移?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆