【问题标题】:Get raw packet data from Qt application从 Qt 应用程序获取原始数据包数据
【发布时间】:2012-06-02 06:14:53
【问题描述】:

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

有什么方法可以实现以上两个吗?

【问题讨论】:

  • 我不明白你的意思。您是否正在编写 Qt 应用程序并需要访问“原始数据包”? “原始数据”是什么意思?
  • 我的意思是,我用QWebView做了一个浏览器。现在,每当 QWebView 从 Internet 下载/上传数据时,我都想访问已发送和接收的 http 数据包数据,并对其进行篡改。有可能吗?
  • ...代理服务器呢?我在新答案中解释得更好......

标签: c++ qt packet


【解决方案1】:

...那么代理服务器呢?睡个好觉让我想到了这种可能性。

您可以在loopback exampletorrent client example 等后面创建一个。因此,您可以捕获和篡改请求AND回复。

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

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

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

  1. 分析 GET 和 POST 操作,
  2.  以二进制传输的形式接收整个请求,
  3. 篡改请求,
  4.  将获取到的请求在连接中发送到目的IP,
  5.  然后您可以捕获回复,
  6. 篡改收到的回复,并且
  7. 将结果响应发送到客户端 webView。

这里我没有经验,但路径似乎很清晰。这将是很多编码,但我认为这确实是一个不错的选择,如果不是唯一的选择

更重要的是:可以做到

【讨论】:

  • 是的,当然可以使用代理服务器来完成。我之前曾想过,但我也认为它可以在 QT 应用程序本身内完成。但事实并非如此,所以我别无选择,只能使用代理服务器。谢谢!
【解决方案2】:

对不起,山姆,我不能让它工作。我一直在尝试我能想象到的一切,但一切都没有如我所愿。

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

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

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

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

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

访问请求很容易,在自定义QNetworkAccessManager 中覆盖createRequest() 方法已经解释了这一点。但是让我们谈谈另一部分:

  • 就我所见,从请求中获得的回复是只读的并且无法更改,因为它是硬编码的在QNetworkReply的源代码中。

  • 不能使用QNetworkReplywriteData() 函数,因为它被硬编码为简单地执行return -1!!!

  • 您可以尝试子类化您自己的QNetworkReply,并在自定义QNetworkAccessManagercreateRequest() 方法中返回它。您必须覆盖函数readAll()bytesAvailable()abort()。奇怪的是,此方法仅在向非 HTTP 目标发出请求时才有效。我认为QNetworkAccessManager 的内部调用QNetworkReply 的不同实现取决于所使用的协议(HTTP、FTP、...)。所以这在某种意义上是有效的,但不是我们想要的方式。例如,此方法可用于在某些条件下返回预定义的网页。

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

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

对不起。

【讨论】:

  • 起初我以为这是一个简单的任务。我收回我的话!!无论如何,非常感谢 Felix 提供了如此出色的支持并花费了您宝贵的时间来帮助我(至少它帮助我清楚地了解了 QNetworkAccessManager 的工作原理)!非常感谢您的帮助。
【解决方案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() 方法获取该对象。您可以通过QWebView::page()QWebView 获取QWebPage


编辑

要操作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 字段等。

希望最终有所帮助!

【讨论】:

  • 这就是我所做的QNetworkAccessManager *manager = ui->webView->page()->networkAccessManager(); connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(finished(QNetworkReply*))); void MainWindow::finished(QNetworkReply *reply) { qDebug()<<reply->isWritable(); } 从上面的代码中,isWritable() 返回 false,所以我无法编辑/附加收到的数据。那么在从 QNetworkReply 接收到的数据上编辑/附加的正确方法是什么?
  • 数据由槽函数内部的reply->readAll()返回。看看我的槽函数。 QByteArray 是原始响应(字节数组)。您可以随意操作收到的QByteArray
  • 是的,我可以,但我想操纵 QWebView 显示的内容。即使我在您的插槽函数中操作回复,它也不会反映在 QWebView 中。
  • 我已经通过编辑更新了答案,因为这将是一个非常大的评论!
  • 非常感谢您迄今为止的帮助 Felix,但不幸的是,这也无济于事。您向我展示的是单独获取页面,然后将其设置为 QWebView 的 html。但我想要的不仅是访问/篡改 HTML,还包括 QWebView 本身发出的每个 HTTP 请求,包括所有图像、css、javascript、pdf、docs、txt 等。 QWebView 请求的任何东西都必须由我操作,然后由它显示。那么这样的事情可能吗?谢谢。
【解决方案4】:

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

这些工具与 Qt 没有任何关系,可用于检查和拦截各种程序的 Web 流量。

【讨论】:

    猜你喜欢
    • 2018-10-13
    • 2014-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-26
    • 2016-11-09
    • 1970-01-01
    相关资源
    最近更新 更多