我正在研究NTFS文件系统,当尝试在具有大量数字的\\.\PhysicalDrive0
(0xb2ec0000
)中搜索3001810944
时遇到一个奇怪的问题。我的Windows分区的$MFT
应该位于该偏移量处(是这种情况)。
[当我从该数字(甚至从十进制形式:3001810944
开始搜索时,SetFilePointer
返回ERROR_NEGATIVE_SEEK
,所以我决定学习负数如何以十六进制工作。
从that主题开始,我理解了为什么0xb2ec0000
被认为是负数,因为它以b
开头。 Powershell还认为它是负面的:
PS A:\core> 0xb2ec0000
-1293156352
它不仅是一个负数,如果我们排除十六进制中存在负数,则从某些hexadecimal to decimal转换器中,我们意识到它也等于3001810944
。
为了成功找到偏移量0xb2ec0000
,我决定寻找两倍的3001810944 / 2
字节(1500905472
),它可以正常工作,但是如果某些自然数不在整数中则被认为是负数,这是一个问题。在给定的上下文中,这似乎根本不正常。
关于除法,如果我决定执行0xb2ec0000 / 2
,它将输出:
PS A:\core> 0xb2ec0000 / 2
-646578176
但是
PS A:\core> 3001810944 / 2
1500905472
这是程序的Rust代码:
您可以通过打开\\.\PhysicalDrive0
并在偏移量0xb2ec0000
处查找来复制示例:
extern "system"{
// [...]
fn CreateFileA(a: *const u8, b: u32, c: u32, d: *mut c_void, e: u32, f: u32, g: *mut c_void) -> *mut c_void;
fn SetFilePointer(a: *mut c_void, b: i64, c: *mut i32, d: u32) -> i32;
}
// [...]
let boot = CreateFileA(
"\\\\.\\PhysicalDrive0\0".as_ptr(),
25,
0x00000002 | 0x00000001,
null_mut(),
3,
128,
null_mut()
);
// [...] Calculating $MFT offset
let mft_offset: i64 = mft_logical_cluster * (bpb.wBytesPerSec * bpb.uchSecPerClust as u16) as i64 + (dsk_info.dwRelativeSector * 512) as i64;
println!("{:x}", mft_offset); // outputs 0xb2ec0000
if(SetFilePointer(boot,mft_offset,null_mut(),0) == -1){
println!("Error: {}", GetLastError()); // outputs 131
}
您错误地将SetFilePointer
定义为i64
时采用i32
。
如果您花时间彻底阅读SetFilePointer
的文档,则会看到:
SetFilePointer
带符号值的低阶32位,用于指定字节来移动文件指针。
如果
lDistanceToMove
不是lpDistanceToMoveHigh
,NULL
和lpDistanceToMoveHigh
形成单个64位有符号值,该值指定移动距离。如果
lDistanceToMove
为lpDistanceToMoveHigh
,则NULL
是32位有符号值。lDistanceToMove
的正值将移动文件指针在文件中向前移动,并且负值将文件指针移回。
lDistanceToMove
指向有符号64位距离的高阶32位的指针移动。
如果您不需要高阶32位,则必须将此指针设置为
lpDistanceToMoveHigh
。
您将需要将NULL
分为两部分,并分别通过每个部分,高位作为指向值的指针。
您应该不是尝试自己编写FFI定义(因为您会弄错它们)。理想情况下,请使用i64
,它具有winapi crate的正确定义。
甚至更好,只需使用常规的Rust类型,例如SetFilePointer
和SetFilePointer
。