1,183
社区成员
发帖
与我相关
我的任务
分享
function NewNtDeviceIoControlFile(
FileHandle: THANDLE;
Event: THANDLE;
ApcRoutine: PIO_APC_ROUTINE;
ApcContext: PVOID;
IoStatusBlock: PIO_STATUS_BLOCK;
IoControlCode: ULONG;
InputBuffer: PVOID;
InputBufferLength: ULONG;
OutputBuffer: PVOID;
OutputBufferLength: ULONG
): NTSTATUS; stdcall;
var
AfdInfo: PAFD_INFO;
Buffer: PAnsiChar;
Len: DWORD;
tmpStr: string;
Index: Integer;
begin
// 先调用原始函数
asm
push OutputBufferLength //XE4 64位编译这里报错,需要另外写一个方法,不知道怎么写
push OutputBuffer
push InputBufferLength
push InputBuffer
push IoControlCode
push IoStatusBlock
push ApcContext
push ApcRoutine
push Event
push FileHandle
call OldNtDeviceIoControl
mov Result, eax
end;
// 如果原始函数失败了(例如RECV无数据)
if (not NT_SUCCESS(Result)) then
begin
Exit;
end;
// 检查是否为TCP收发指令
if (IoControlCode <> AFD_SEND)
and (IoControlCode <> AFD_RECV) then
begin
Exit;
end;
// 访问AFD INFO结构,获得SEND或RECV的BUFFER信息
// 这里可能是有问题的BUFFER,因此我们要加TRY EXCEPT
try
// 从 InputBuffer 得到 Buffer 和 Len
AfdInfo := PAFD_INFO(InputBuffer);
Buffer := AfdInfo.BufferArray.buf;
Len := AfdInfo.BufferArray.len;
case IoControlCode of
AFD_SEND:
if (LookupSendPacket(Buffer, Len)) then
begin
// 输出包内容
OutputDebugString(PChar(Format('[HTTP Send] Handle = %0.8X, Length = %d', [FileHandle, Len])));
OutputDebugString(PChar(Format('%s', [StrPas(Buffer)])));
tmpStr := LowerCase(string(StrPas(Buffer)));
{ 网址过滤实现 }
if (Pos(Block_Filter, tmpStr) > 0) then
begin
OutputDebugString(PChar(Format('>>> "%s" was blocked.', [Block_Filter])));
Result := $C0000001; // 返回失败让系统丢掉这个包
end;
{ 重定向实现 }
// 查找发送的数据中是否包含 URL_Filter 中的字符串
if (Pos(URL_Filter, tmpStr) > 0) then
begin
// 匹配到 URL_Filter,将Handle加入 SessionList
tmpStr := IntToHex(FileHandle, 8);
if (SessionList.IndexOf(tmpStr) = -1) then // 如果没有这个Handle
SessionList.Add(tmpStr);
end;
end;
AFD_RECV:
if (LookupRecvPacket(Buffer, Len)) then
begin
// 输出包内容
OutputDebugString(PChar(Format('[HTTP Recv] Handle = %0.8X, Length = %d', [FileHandle, Len])));
OutputDebugString(PChar(Format('%s', [StrPas(Buffer)])));
{ 重定向实现 }
// 在SessionList查找Handle,找到则进行重定向
tmpStr := IntToHex(FileHandle, 8);
Index := SessionList.IndexOf(tmpStr);
if (Index >= 0) then
begin
SessionList.Delete(Index);
// 修改缓冲区内容为重定向字符串,
CopyMemory(Buffer, @Redirect_String[1], Length(Redirect_String));
OutputDebugString(PChar(Format('>>> Redirect "%s" to a new page.', [URL_Filter])));
end;
end;
end;
except
end;
end;
asm
push OutputBufferLength //XE4 64位编译这里报错,需要另外写一个方法,不知道怎么写
push OutputBuffer
push InputBufferLength
push InputBuffer
push IoControlCode
push IoStatusBlock
push ApcContext
push ApcRoutine
push Event
push FileHandle
call OldNtDeviceIoControl
mov Result, eax
end;
这就是一个标准的API调用,可以不使用汇编的,先定义这个函数的格式,把OldNtDeviceIoControl强转类型到函数类型,即可调用type
TNtDeviceIoControlFileFun = function(
FileHandle: THANDLE;
Event: THANDLE;
ApcRoutine: PIO_APC_ROUTINE;
ApcContext: PVOID;
IoStatusBlock: PIO_STATUS_BLOCK;
IoControlCode: ULONG;
InputBuffer: PVOID;
InputBufferLength: ULONG;
OutputBuffer: PVOID;
OutputBufferLength: ULONG
): NTSTATUS; stdcall;
function NewNtDeviceIoControlFile(
FileHandle: THANDLE;
Event: THANDLE;
ApcRoutine: PIO_APC_ROUTINE;
ApcContext: PVOID;
IoStatusBlock: PIO_STATUS_BLOCK;
IoControlCode: ULONG;
InputBuffer: PVOID;
InputBufferLength: ULONG;
OutputBuffer: PVOID;
OutputBufferLength: ULONG
): NTSTATUS; stdcall;
var
AfdInfo: PAFD_INFO;
Buffer: PAnsiChar;
Len: DWORD;
tmpStr: string;
Index: Integer;
begin
// 先调用原始函数
Result := TNtDeviceIoControlFileFun(OldNtDeviceIoControl)(
FileHandle,
Event,
ApcRoutine,
ApcContext,
IoStatusBlock,
IoControlCode,
InputBuffer,
InputBufferLength,
OutputBuffer,
OutputBufferLength);
// 如果原始函数失败了(例如RECV无数据)
if (not NT_SUCCESS(Result)) then
begin
Exit;
end;
....
另:别被3楼的话吓到了,32位和64位可以用编译关键字区分的
如:
function Test : Boolean;
{$IFDEF CPUARM}
begin
//Android,iOS等ARM编码写于此
Result := False;
end;
{$ELSE}
asm
{$IFDEF CPUX64}
XOR RAX , RAX
{$ELSE} //CPUX86
XOR EAX , EAX
{$ENDIF}
end;
{$ENDIF}