从Qt应用程序获取原始数据包数据

时间:2012-05-27 15:35:12

标签: c++ qt packet

我正在寻找一种方法来访问&篡改Qt应用程序发送和接收的原始数据包数据,但找不到任何内容。有什么方法吗? 或者如果不是应用程序,至少是从QWebView访问分组数据的方法。

有没有方法可以实现上述两种方法中的任何一种?

4 个答案:

答案 0 :(得分:3)

篡改与网络连接中的服务器之间发送/接收的数据的正确方法是QNetworkAccessManager

此类允许您向服务器发送请求(可能带有标题)并获取响应(也包含标题)。

您可以访问相应QNetworkReply对象上收到的数据。响应的标题:

{
  ...
  QNetworkAccessManager *qnam = new QNetworkAccessManager(this);
  connect(qnam, SIGNAL(finished(QNetworkReply*)),
          this, SLOT(replyFinished(QNetworkReply*)));

  QNetworkRequest request;
  request.setUrl(QUrl("http://stackoverflow.com"));
  request.setRawHeader("User-Agent", "Foo browser");
  qnam->get(QNetworkRequest(request));
  ...
}

然后定义插槽:

void MyWidget::replyFinished(QNetworkReply *reply)
{
  QByteArray response = reply->readAll();
  QString mime = reply->header(QNetworkRequest::ContentTypeHeader).toString();
  ...
}

查看文档herehere

实际上,QWebView有一个QNetworkAccessManager对象来执行请求和管理回复。您可以通过QWebPage::networkAccessManager()方法获取该对象。您可以通过QWebPageQWebView获取QWebView::page()


修改

要操纵QWebView显示的网页,您可以通过webView->setHtml(QString html)直接设置新的HTML内容。

您还可以通过QWebFrame类的方法直接访问HTML。

要获得此类对象,您必须执行以下操作:

QWebFrame *wb = webView->page()->currentFrame();

方法是:

  • void QWebFrame::setContent ( const QByteArray & data, const QString & mimeType = QString(), const QUrl & baseUrl = QUrl() )用于在字节数组中设置新文档。

  • void QWebFrame::setHtml ( const QString & html, const QUrl & baseUrl = QUrl() )也会这样做,但会考虑HTML文档的内容。

  • QString QWebFrame::toHtml () const将内容作为HTML文档获取。

  • QString QWebFrame::toPlainText () const与上述相同,为纯文本。

查看这些功能的文档。


编辑2:

最后,如果您想访问或过滤QWebView本身发出的请求,我只能看到一种方法:从QNetworkAccessManager派生一个类并覆盖用于发出请求的方法和收到答案。

然后,将该类的实例设置为QWebView使用的QNetworkAccessManager。

让我用骨架澄清:

class MyNAM : public QNetworkAccessManager
{
  // ...

  MyNAM(QObject *parent = 0) : QNetworkAccessManager(parent) { }

  // ...

  virtual QNetworkReply * createRequest(Operation op, const QNetworkRequest & req, QIODevice * outgoingData = 0) {

    // e.g. logging of the request

    // e.g. decide if the request must be made
    if (some_bool_deciding) {
      QNetworkAccessManager::createRequest(op, req, outgoingData);
    }
    else {
      // or faked...
    }
    // etc.
  }

  // ...
};

在您的主要应用程序中,您必须:

// ...
MyNAM *nam = new MyNAM();
webview->page()->setNetworkAccessManager(nam);
// ...

从现在开始,所有请求都将使用该对象进行。

此方法允许完全控制导航器发出的请求:过滤和访问请求数据(标题,获取和发布值等)。您可以记录请求,分析请求及其POST / GET字段等。

希望终于有所帮助!

答案 1 :(得分:3)

对不起,山姆,我做不到。我一直在尝试我能想象到的一切,但没有任何事情可以实现。

让我们列出一个简短的选项列表,以及可以做什么和不可以做什么:

  • 您可以通过QWebFrame获取webView->page()->currentFrame(),然后访问setContents()setHtml(),{{1}等方法来访问检索到的网页}或toHtml()。您可以通过这些功能动态更改窗口小部件中显示的网页。

  • 您可以通过toPlainText()广告位中的方法reply->readAll()访问为每个请求收到的原始响应(作为字节数组)。

  • 可以通过覆盖您自己的网络访问管理器中的replyFinished()方法来拦截请求。在那里,您可以访问请求中发送的URL和标题,并更改它们或取消请求。

但是......您想要访问每个请求的请求和回复数据。

访问请求很简单,已经通过覆盖自定义QNetworkAccessManager::createRequest()中的createRequest()方法来解释。但是让我们谈谈另一部分:

  • 对于我所看到的,从请求获得的回复是只读 IT无法更改,因为它是硬编码的在QNetworkAccessManager的源代码中。

  • 无法使用 QNetworkReply writeData()的{​​{1}}功能,因为它只是简单地执行QNetworkReply !!!

    < / LI>
  • 您可以尝试继承自己的return -1并将其返回到自定义QNetworkReply的{​​{1}}方法中。您必须覆盖功能createRequest()QNetworkAccessManagerreadAll()。奇怪的是,此方法仅在请求发送到非HTTP目标时才有效。我认为bytesAvailable()的内部调用abort()的不同实现,具体取决于所使用的协议(HTTP,FTP,...)。所以这在某种意义上起作用,但不是我们想要的方式。例如,此方法可用于在特定条件下返回预定义的网页。

  • 考虑到QNetworkAccessManager必须返回QNetworkReply对象这一事实,我看不到任何允许在回复的字节数组中进行篡改的子类组合。它确实受到很好的保护,你必须重新实现这些课程上的所有内容才能实现你的目标。几乎复制粘贴所有QNetworkAccessManager::createRequest()部分的源类并进行自己的实现。

所以我认为答案是:“不,似乎不能完全按照你的要求完成;只是部分”。

对不起。

答案 2 :(得分:0)

看起来你想要Wireshark http://www.wireshark.org/或Fiddler http://www.fiddler2.com/fiddler2/,或者甚至是Charles http://www.charlesproxy.com/

这些工具与Qt无关,可用于检查和拦截各种程序的网络流量。

答案 3 :(得分:0)

......那代理服务器怎么样?一夜好眠让我想到了这种可能性。

您可以在loopback exampletorrent client example之后制作一个。因此,您可以捕获并篡改请求 AND 回复。

您可以使用QWebView在客户端webView->page()->networkAccessManager()->setProxy()上配置代理。

这涉及构建一个侦听所需端口(例如8080)并侦听本地主机上的连接的进程。

您必须通过以下方式实施代理协议:

  1. 分析GET和POST操作,
  2. 以二进制传输方式接收整个请求,
  3. 篡改请求,
  4. 通过连接将获得的请求发送到目标IP
  5. 然后你可以捕捉回复,
  6. 篡改收到的回复,
  7. 将结果响应发送到客户端webView。
  8. 这里我没有经验,但路径似乎很清楚。这将是一个很多编码,但我认为这是一个很好的选择如果不是唯一的选择

    更重要的是:可以做到