为什么Powershell和WinAPI在文件中查找时会将巨大的数字识别为负数?
我正在研究NTFS文件系统,当我试图在为什么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开头
\\\.\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
,具体取决于您如何解释它。