Delphi XE4 编写64位DLL ASM的问题

chuangxinwork 2014-12-29 11:53:50
目前了解到编写64位的情况下内嵌ASM已经不支持了,需要独立写个方法,对ASM不懂,帮忙懂得解决下,非常感谢!
程序整体源代码:http://pan.baidu.com/s/1bnm2paR
32的情况可以编译,64位就不行

代码如下:
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;
...全文
601 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
chuangxinwork 2014-12-31
  • 打赏
  • 举报
回复
引用 6 楼 kiboisme 的回复:
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}
编译通过,非常感谢!
蓝色光芒 2014-12-30
  • 打赏
  • 举报
回复
  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强转类型到函数类型,即可调用
lyhoo163 2014-12-30
  • 打赏
  • 举报
回复
64位和32位汇编不兼容。
武稀松 2014-12-30
  • 打赏
  • 举报
回复
另外你这个Hook其实不需要内嵌汇编. http://www.raysoftware.cn/?p=493 支持X86,X64的各种Hook,.而且使用很简单
武稀松 2014-12-30
  • 打赏
  • 举报
回复
X64中VC是不支持内嵌汇编的. 但是Delphi还是支持的,但是和之前有点区别.就是如果内嵌汇编就要整个函数都用会编写.比如: procedure test; asm ....... end;
蓝色光芒 2014-12-30
  • 打赏
  • 举报
回复
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}
chuangxinwork 2014-12-30
  • 打赏
  • 举报
回复
引用 4 楼 kiboisme 的回复:
  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强转类型到函数类型,即可调用
能否帮我改下能编译,太感谢了。。

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧