首页
社区
课程
招聘
[求助]关于HOOK浏览器NtDeviceIoControlFile函数,修改POST数据的问题。
发表于: 2014-2-6 13:59 11315

[求助]关于HOOK浏览器NtDeviceIoControlFile函数,修改POST数据的问题。

2014-2-6 13:59
11315
我HOOK了IE的NtDeviceIoControlFile函数,想修改POST发包的数据,IE做POST数据时,会发送两个包,一个是HTTP头,一个是数据,如果修改的数据长度跟原数据长度相等,则可以直接修改数据,不会有问题,但如果数据长度不相等,则需要先修改HTTP头里的Content-length参数,然后再在第二个数据包发送的时候修改数据Buffer。

我的问题是,在第二种情况下,修改长度不一样的包发送后,服务器可以正确识别修改后的数据,等于是修改成功了,但是浏览器这里却会报一个ERROR_INTERNET_INTERNAL_ERROR错误,导致浏览器认为网络错误,我研究了一整天没有头绪,怀疑是不是HOOK的NtDeviceIoControlFile函数里的返回值或者参数的修改方式不对导致的,请坛子里的各位大牛帮我分析一下。

我的修改方式是这样的:
int PraLenght;
NTSTATUS WINAPI CWininetHook::_NtDeviceIoControlFile( HANDLE FileHandle,HANDLE Event OPTIONAL,PVOID ApcRoutine OPTIONAL,PVOID ApcContext OPTIONAL,PVOID IoStatusBlock,ULONG IoControlCode,PVOID InputBuffer OPTIONAL,ULONG InputBufferLength,PVOID OutputBuffer OPTIONAL,ULONG OutputBufferLength )
{
  LONG stat = -1; 


  if (IoControlCode != AFD_SEND)
  {
    __asm
    {
      push  OutputBufferLength
        push  OutputBuffer
        push  InputBufferLength
        push  InputBuffer 
        push  IoControlCode
        push  IoStatusBlock 
        push  ApcContext
        push  ApcRoutine
        push  Event
        push  FileHandle
        call  s_pfnNtDeviceIoControlFile
        mov    stat ,eax
    }
    return stat ; 
  }

  string text = "";
  PAFD_INFO AfdInfo = NULL;
  char * Buffer = NULL;
  ULONG Len = NULL;
  string domain;
  
  if (IoControlCode == AFD_SEND)
  {
    AfdInfo = (PAFD_INFO)InputBuffer;
    Buffer = AfdInfo->BufferArray->buf;
    Len = AfdInfo->BufferArray->len;

    text = Buffer;
    text = text.substr(0,Len);
    if(text != "!" && text != "" && text.length() > 0)
    {
      if(text.substr(0,4) == "POST")
      {
        //修改HTTP头里的Content-length
        if(text.find("SpeSubmit.aspx") != text.npos)
        {
          domain = GetDomainFromRequest(text.c_str());
          if(Ecode.find(domain) != Ecode.end())
            Ecode_h[FileHandle] = Ecode[domain];
          else
            Ecode_h[FileHandle] = -1;

          PraLenght = MyRelpaceHeaderLength(text);

          TRACE(text.c_str());

          [COLOR="red"]AfdInfo->BufferArray->len = text.size();
          AfdInfo->BufferArray->buf = (char *)text.c_str();[/COLOR]
        }
        else if(Ecode_h.find(FileHandle) != Ecode_h.end())
        {
          Ecode_h.erase(FileHandle);
        }
      }
      else if(text.substr(0,3) == "GET" && Ecode_h.find(FileHandle) != Ecode_h.end())
      {
        Ecode_h.erase(FileHandle);
      }
      else if(Ecode_h.find(FileHandle) != Ecode_h.end())
      {
        //修改POST数据
        if(Ecode_h[FileHandle] == -1)
        {
          if(MyConver::is_utf8_code(text)) Ecode_h[FileHandle] = TRUE;
          else Ecode_h[FileHandle] = FALSE;
        }
        if(Ecode_h[FileHandle]) MyConver::UTF8ToGBK(text,text.c_str());
        BOOL b = MyHttpSendRequest(FileHandle,text);
        if(Ecode_h[FileHandle]) text = MyConver::GBKToUTF8(text);
        
        if(b)
        {
          int span = PraLenght - text.size();
          for (int i = 0; i < span; i++)
          {
            text += " ";
          }

          text = text.substr(0,PraLenght);
          TRACE(text.c_str());

          Ecode_h.erase(FileHandle);
          [COLOR="Red"]AfdInfo->BufferArray->len = PraLenght;
          AfdInfo->BufferArray->buf = (char*)text.c_str();[/COLOR]
        }
      }

      __asm
      {
        push  OutputBufferLength
          push  OutputBuffer
          push  InputBufferLength
          push  InputBuffer 
          push  IoControlCode
          push  IoStatusBlock 
          push  ApcContext
          push  ApcRoutine
          push  Event
          push  FileHandle
          call  s_pfnNtDeviceIoControlFile
          mov    stat ,eax
      }

      AfdInfo->BufferArray->buf = (char*)Buffer;
      AfdInfo->BufferArray->len = Len;
      return stat;
    }
    __asm
    {
      push  OutputBufferLength
        push  OutputBuffer
        push  InputBufferLength
        push  InputBuffer 
        push  IoControlCode
        push  IoStatusBlock
        push  ApcContext
        push  ApcRoutine
        push  Event
        push  FileHandle
        call  s_pfnNtDeviceIoControlFile
        mov    stat ,eax
    }
  }

  return stat ; 
}

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (8)
雪    币: 239
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
说明一下,我是参照qihoocom前辈的文章http://bbs.pediy.com/showthread.php?t=81204实现的,感谢。
2014-2-6 14:12
0
雪    币: 228
活跃值: (115)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
3
你可以把协议头拦截下来 然后等东西修改完 再依次把协议 内容发出去
2014-2-6 18:37
0
雪    币: 239
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
我明白你的意思,我这里不是发送数据的内容不能控制,我已经可以控制发送的数据了,只需要对Content-length增加300,然后新建该长度的缓冲区存放修改后的数据就可以发包了,处理方式在代码里有。但是我这里的现象表明,浏览器的发包机制不可以替换InputBuffer参数里的发包缓冲区,否则即使发送成功了,还是会报错。。

我觉得可能我的hook函数处理得不够完美,即使替换并发包完成后替换回原来的缓冲区和长度,还是报错了,不知道是不是还有别的参数要修改。。
2014-2-6 19:27
0
雪    币: 31
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
有没可能是这样,本来是发300字节数据出去,你加上了几十个字节,但是上层不知道啊,一判断返回的字节数不对,直接报错
2014-2-6 19:45
0
雪    币: 239
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
应该不会,上层只管NtDeviceIoControlFile函数发包是否成功返回吧?我输出过所有访问的返回值,修改参数的调用跟普通调用的返回值都是一样的,都是返回0成功。。。
2014-2-6 20:17
0
雪    币: 31
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
不是吧,就像用send数据是有返回发送的长度的
2014-2-6 20:33
0
雪    币: 239
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
谢谢,经过您的提醒,我查看了其他参数的描述,是IoStatusBlock有返回发送长度,我以前没写过底层网络编程,刚才修改了该参数的长度值,完美解决了修改问题,非常感谢,解决了我最大的难题。
2014-2-6 20:51
0
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
mark
2015-1-13 15:11
0
游客
登录 | 注册 方可回帖
返回
//