Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Powershell和WinAPI在文件中查找时会将巨大的数字识别为负数?_Winapi_Rust_Numbers_Hex - Fatal编程技术网

为什么Powershell和WinAPI在文件中查找时会将巨大的数字识别为负数?

为什么Powershell和WinAPI在文件中查找时会将巨大的数字识别为负数?,winapi,rust,numbers,hex,Winapi,Rust,Numbers,Hex,我正在研究NTFS文件系统,当我试图在\\\.\PhysicalDrive0中查找像0xb2ec0000(3001810944)这样的大数字时,遇到了一个奇怪的问题。我的Windows分区的$MFT应该位于该偏移量处(就是这种情况) 当我从那个数字(甚至从十进制形式:3001810944)中查找时,SetFilePointer返回了ERROR\u NEGATIVE\u SEEK,所以我决定学习负数在十六进制中是如何工作的 从主题中,我理解了为什么0xb2ec0000被认为是负面的,因为它以b开头

我正在研究NTFS文件系统,当我试图在
\\\.\PhysicalDrive0
中查找像
0xb2ec0000
3001810944
)这样的大数字时,遇到了一个奇怪的问题。我的Windows分区的
$MFT
应该位于该偏移量处(就是这种情况)

当我从那个数字(甚至从十进制形式:
3001810944
)中查找时,
SetFilePointer
返回了
ERROR\u NEGATIVE\u SEEK
,所以我决定学习负数在十六进制中是如何工作的

从主题中,我理解了为什么
0xb2ec0000
被认为是负面的,因为它以
b
开头。Powershell还将其识别为负值:

PS A:\core>0xb2ec0000
-1293156352
它不仅可以是负数,如果我们排除十六进制中负数的存在,从一些转换器中我们意识到它也等于
3001810944

为了在偏移量
0xb2ec0000
处成功搜索,我决定搜索两次
3001810944/2
字节(
1500905472
),效果很好,但如果某些自然数不在给定上下文中被视为负数,这就成了问题,看起来根本不正常

关于划分,如果我决定执行
0xb2ec0000/2
,它将输出:

PS A:\core>0xb2ec0000/2
-646578176
但是

PS A:\core>3001810944/2
1500905472
以下是程序的防锈代码:

您可以通过打开
\\.\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
定义为当它是
i32
时使用
i64

如果您花时间仔细阅读这些文档,您将看到:

lDistanceToMove

有符号值的低位32位,用于指定 字节来移动文件指针

如果
lpDistanceToMoveHigh
不是
NULL
lpDistanceToMoveHigh
lDistanceToMove
形成一个64位有符号值,用于指定 移动距离

如果
lpDistanceToMoveHigh
NULL
lDistanceToMove
为32位带符号 价值
lDistanceToMove
的正值将移动文件指针 在文件中向前移动,负值将文件指针向后移动

lpDistanceToMoveHigh

指向到的有符号64位距离的高阶32位的指针 移动

如果不需要高阶32位,则必须将此指针设置为
NULL

您需要将
i64
分成两部分,并分别传递每个部分,高位作为指向值的指针

您应该而不是自己尝试编写FFI定义(因为您会弄错它们)。理想情况下,使用具有正确定义的


更好的是,只需使用常规的锈蚀类型,如和。

您需要向我们展示一些相关代码行。@Jabberwocky我添加了代码,它位于锈蚀中,为了理解实际问题,我跳过了不重要的部分。您只需打开
\\.\PhysicalDrive0
并在偏移量
0xb2ec0000
处执行寻道操作,就可以自己复制它。这是因为您将lpDistanceToMoveHigh(指向要移动的有符号64位距离的高位32位的指针)设置为0。lDistanceToMove(有符号值的低位32位)是有符号扩展。。我要告诉你一个可怕的秘密-使用
SetFilePointer[Ex]
根本没有任何意义,
null\u mut()
必须是指向0 dword的指针。但根本不需要调用
SetFilePointer
。为什么?!您还应该对位、字节以及它们的解释方式进行更多的研究。“十六进制”未签名或未签名。例如,
0xff
可以表示
255
-1
,具体取决于您如何解释它。