内核模式:如何逐行读取 txt 文件?
Kernel Mode: How read a txt file line by line?
我需要读取 txt 文件的每一行并将这一行作为参数传递给方法。
我找到了这个例子:
LARGE_INTEGER byteOffset;
ntstatus = ZwCreateFile(&handle,
GENERIC_READ,
&objAttr, &ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL, 0);
if(NT_SUCCESS(ntstatus)) {
byteOffset.LowPart = byteOffset.HighPart = 0;
ntstatus = ZwReadFile(handle, NULL, NULL, NULL, &ioStatusBlock,
buffer, BUFFER_SIZE, &byteOffset, NULL);
if(NT_SUCCESS(ntstatus)) {
buffer[BUFFER_SIZE-1] = '[=10=]';
DbgPrint("%s\n", buffer);
}
ZwClose(handle);
}
但这会读取文件的所有内容,而不是逐行读取。
关于如何做到这一点的一些想法?
读取所有文件以缓冲或将其映射为部分。比执行下一个代码:
extern "C" PCSTR __fastcall findRN(SIZE_T cb, PCSTR sz);
void processLine(SIZE_T len, PCSTR line)
{
DbgPrint("%.*s\n", len, line);
}
NTSTATUS process(PCSTR buf, SIZE_T cb)
{
PCSTR end = buf + cb, line = buf;
while (buf = findRN(end - line, line))
{
processLine(buf - line, line);
line = buf + 2;
}
if (line != end)
{
processLine(end - line, line);
}
return 0;
}
在 c/c++
上实施 findRN
PCSTR __fastcall findRN(SIZE_T cb, PCSTR sz)
{
if (cb < 2)
{
return 0;
}
cb--;
do
{
if (*sz++ == '\r')
{
if (*sz == '\n')
{
return sz - 1;
}
}
} while (--cb);
return 0;
}
如果你need/want 超快速最有效的实现,在 asm 中执行此操作。例如 x64:
findRN proc
cmp rcx,1
ja @@0
xor rax,rax
ret
@@0:
mov ax,0a0dh
xchg rdi,rdx
dec rcx
@@1:
repne scasb
jne @@2
cmp [rdi],ah
jne @@1
@@2:
sete al
dec rdi
movzx rax,al
neg rax
and rax,rdi
xchg rdi,rdx
ret
findRN endp
在 x86 上的代码相同,只是在寄存器名称
中将 r 更改为 e
地图文件:
NTSTATUS process(POBJECT_ATTRIBUTES poa)
{
HANDLE hFile, hSection = 0;
IO_STATUS_BLOCK iosb;
NTSTATUS status = NtOpenFile(&hFile, FILE_GENERIC_READ, poa, &iosb,
FILE_SHARE_VALID_FLAGS, FILE_SYNCHRONOUS_IO_NONALERT);
if (0 <= status)
{
FILE_STANDARD_INFORMATION fsi;
if (0 <= (status = NtQueryInformationFile(hFile, &iosb, &fsi, sizeof(fsi), FileStandardInformation)))
{
if (fsi.EndOfFile.HighPart)
{
status = STATUS_FILE_TOO_LARGE;
}
else if (!fsi.EndOfFile.LowPart)
{
status = STATUS_MAPPED_FILE_SIZE_ZERO;
}
else
{
status = NtCreateSection(&hSection, SECTION_MAP_READ, 0, 0, PAGE_READONLY, SEC_COMMIT, hFile);
}
}
NtClose(hFile);
if (0 <= status)
{
PVOID BaseAddress = 0;
SIZE_T ViewSize = 0;
status = ZwMapViewOfSection(hSection, NtCurrentProcess(), &BaseAddress, 0,
0, 0, &ViewSize, ViewUnmap, 0, PAGE_READONLY);
NtClose(hSection);
if (0 <= status)
{
status = process((PCSTR)BaseAddress, fsi.EndOfFile.LowPart);
ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
}
}
}
return status;
}
我需要读取 txt 文件的每一行并将这一行作为参数传递给方法。
我找到了这个例子:
LARGE_INTEGER byteOffset;
ntstatus = ZwCreateFile(&handle,
GENERIC_READ,
&objAttr, &ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL, 0);
if(NT_SUCCESS(ntstatus)) {
byteOffset.LowPart = byteOffset.HighPart = 0;
ntstatus = ZwReadFile(handle, NULL, NULL, NULL, &ioStatusBlock,
buffer, BUFFER_SIZE, &byteOffset, NULL);
if(NT_SUCCESS(ntstatus)) {
buffer[BUFFER_SIZE-1] = '[=10=]';
DbgPrint("%s\n", buffer);
}
ZwClose(handle);
}
但这会读取文件的所有内容,而不是逐行读取。
关于如何做到这一点的一些想法?
读取所有文件以缓冲或将其映射为部分。比执行下一个代码:
extern "C" PCSTR __fastcall findRN(SIZE_T cb, PCSTR sz);
void processLine(SIZE_T len, PCSTR line)
{
DbgPrint("%.*s\n", len, line);
}
NTSTATUS process(PCSTR buf, SIZE_T cb)
{
PCSTR end = buf + cb, line = buf;
while (buf = findRN(end - line, line))
{
processLine(buf - line, line);
line = buf + 2;
}
if (line != end)
{
processLine(end - line, line);
}
return 0;
}
在 c/c++
上实施findRN
PCSTR __fastcall findRN(SIZE_T cb, PCSTR sz)
{
if (cb < 2)
{
return 0;
}
cb--;
do
{
if (*sz++ == '\r')
{
if (*sz == '\n')
{
return sz - 1;
}
}
} while (--cb);
return 0;
}
如果你need/want 超快速最有效的实现,在 asm 中执行此操作。例如 x64:
findRN proc
cmp rcx,1
ja @@0
xor rax,rax
ret
@@0:
mov ax,0a0dh
xchg rdi,rdx
dec rcx
@@1:
repne scasb
jne @@2
cmp [rdi],ah
jne @@1
@@2:
sete al
dec rdi
movzx rax,al
neg rax
and rax,rdi
xchg rdi,rdx
ret
findRN endp
在 x86 上的代码相同,只是在寄存器名称
中将 r 更改为 e地图文件:
NTSTATUS process(POBJECT_ATTRIBUTES poa)
{
HANDLE hFile, hSection = 0;
IO_STATUS_BLOCK iosb;
NTSTATUS status = NtOpenFile(&hFile, FILE_GENERIC_READ, poa, &iosb,
FILE_SHARE_VALID_FLAGS, FILE_SYNCHRONOUS_IO_NONALERT);
if (0 <= status)
{
FILE_STANDARD_INFORMATION fsi;
if (0 <= (status = NtQueryInformationFile(hFile, &iosb, &fsi, sizeof(fsi), FileStandardInformation)))
{
if (fsi.EndOfFile.HighPart)
{
status = STATUS_FILE_TOO_LARGE;
}
else if (!fsi.EndOfFile.LowPart)
{
status = STATUS_MAPPED_FILE_SIZE_ZERO;
}
else
{
status = NtCreateSection(&hSection, SECTION_MAP_READ, 0, 0, PAGE_READONLY, SEC_COMMIT, hFile);
}
}
NtClose(hFile);
if (0 <= status)
{
PVOID BaseAddress = 0;
SIZE_T ViewSize = 0;
status = ZwMapViewOfSection(hSection, NtCurrentProcess(), &BaseAddress, 0,
0, 0, &ViewSize, ViewUnmap, 0, PAGE_READONLY);
NtClose(hSection);
if (0 <= status)
{
status = process((PCSTR)BaseAddress, fsi.EndOfFile.LowPart);
ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
}
}
}
return status;
}