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

Get raw packet data from Qt application

本文关键字:原始数据 数据包 数据 原始 获取 Qt 应用程序      更新时间:2023-10-16

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

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

对不起,山姆,我无法让它工作。我一直在尝试我能想象的一切,但没有像它想要的那样进行。

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

  • 您可以通过获取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的内部结构会根据所使用的协议(HTTP,FTP等)调用QNetworkReply的不同实现。所以这在某种意义上是有效的,但不是以我们想要的方式。例如,此方法可用于在特定条件下返回预定义的网页。

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

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

不好意思。

篡改网络连接

中服务器发送/接收的数据的正确方法是通过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();
  ...
}

查看此处和此处的文档。

实际上,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);
// ...

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

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

希望最终有所帮助!

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

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

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

您可以按照环回示例和 torrent 客户端示例等制作一个。因此,您可以捕获和篡改请求回复。

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

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

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

  1. 分析 GET 和 POST 操作,
  2. 以二进制传输的形式接收整个请求,
  3. 篡改请求,
  4. 将连接中获取的请求发送到目标 IP,
  5. 然后你可以捕获回复,
  6. 篡改收到的回复,以及
  7. 将生成的响应发送到客户端 Web 视图。

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

更重要的是:这是可以做到的!