Get raw packet data from Qt application

◇◆丶佛笑我妖孽 提交于 2019-12-23 16:41:02

问题


I was searching for a method to access & tamper the raw packet data sent and received by a Qt application but could not find anything. Is there any method? Or if not the application at least a method to access the packet data from a QWebView.

Is there any method to achieve any of the above two?


回答1:


I'm sorry, Sam, I cannot make it work. I've been trying everything I can imagine, but nothing goes as it would have been desired.

Let's make a short list of options and what can and cannot be done:

  • You can access the retrieved web page by means of obtaining the QWebFrame with webView->page()->currentFrame() and then accessing to methods like setContents(), setHtml(), toHtml() or toPlainText(). You can, by those functions, change dynamically the web page shown in the widget.

  • You can access the raw response (as an array of bytes) received for each request, by means of the method reply->readAll() in the replyFinished() slot.

  • It's possible to intercept the requests, by overriding the QNetworkAccessManager::createRequest() method in a network access manager of your own. There you can access the URL and the headers sent in the request and change them or cancel the request.

But... you want to access to the request and replied data for each request.

Access to the request is easy, it's already been explained by the override to the createRequest() method in a custom QNetworkAccessManager. But let's talk about the other part:

  • For what I've seen, the reply obtained from the request is read-only and IT CAN'T BE CHANGED, as it's hard-coded in the source code for QNetworkReply.

  • You cannot use the writeData() function of QNetworkReply, as it is hardcoded to simply do return -1!!!

  • You can try to subclass a QNetworkReply of your own and return it in the createRequest() method of a custom QNetworkAccessManager. You must override the functions readAll(), bytesAvailable(), and abort(). Curiously, this method works only if the request is made to a non-HTTP destination. I think the internals of QNetworkAccessManager invokes different implementations of the QNetworkReply depending of the protocol used (HTTP, FTP, ...). So this worked in a sense, but not in the way we want. This method can be used to return a predefined web page under certain conditions, for example.

  • Considering the fact that QNetworkAccessManager::createRequest() must return a QNetworkReply object, I cannot see any combination of subclassing that permits tampering in the replied byte array. It's really well protected and you must reimplement everything on those classes to be able to achieve your goal. Almost copy-paste the source classes of all the QtNetwork part and make your own implementation.

So I think that the answer would be: "No, it seems that it cannot be done exactly as you ask; only partially".

Sorry.




回答2:


The proper method to tamper with data sent / received to and from a server in a network connection is by the means of QNetworkAccessManager.

This class lets you send a request to a server (probably with headers) and get the response (also with headers).

You can access to the data received on the corresponding QNetworkReply object. Also the headers of the response:

{
  ...
  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));
  ...
}

Then define the slot:

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

Take a look at the documentation here and here.

In fact, a QWebView has a QNetworkAccessManager object to execute the requests and manage the replies. You can obtain that object by means of the QWebPage::networkAccessManager() method. You can obtain the QWebPage from a QWebView by means of QWebView::page().


EDIT

To manipulate the webpage displayed by the QWebView, you can directly set a new HTML contents by means of webView->setHtml(QString html).

You can also access the HTML directly by methods of the QWebFrame class.

To obtain such object, you must do:

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

The methods are:

  • void QWebFrame::setContent ( const QByteArray & data, const QString & mimeType = QString(), const QUrl & baseUrl = QUrl() ) for setting a new document in byte array.

  • void QWebFrame::setHtml ( const QString & html, const QUrl & baseUrl = QUrl() ) does the same, but considering the content an HTML document.

  • QString QWebFrame::toHtml () const to get the contents as an HTML document.

  • QString QWebFrame::toPlainText () const the same as above, as plain text.

Look at the documentation for those functions.


EDIT 2:

Finally, if you want to access or filter the requests made by the QWebView itself, I can see only one way: derive a class from QNetworkAccessManager and override the methods used to make the requests and receive the answers.

Then, make an instance of that class an set it as the QNetworkAccessManager used by the QWebView.

Let me clarify with an skeleton:

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.
  }

  // ...
};

In your main application, you must made:

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

From now on, all the requests will be made using that object.

This method allows a full control over the requests made by the navigator: filter and access to the request data (headers, get and post values, etc.). You could log the requests, analyze the requests and their POST/GET fields, etc.

Hope that finally helped!




回答3:


It looks like you want Wireshark http://www.wireshark.org/ or Fiddler http://www.fiddler2.com/fiddler2/, or maybe even Charles http://www.charlesproxy.com/.

These tools don't have anything to do with Qt and can be used to inspect and intercept web traffic for all sorts of programs.




回答4:


...and what about a proxy server? A good night sleep has made me think of this possibility.

You can make one following the loopback example and the torrent client example among others. So you can capture and tamper the requests AND the replies. 

You can configure the proxy on the client QWebView with webView->page()->networkAccessManager()->setProxy()

This involves the construction of a process that listens to the desired port (e.g. 8080) and listen to connections on the localhost. 

You must implement the protocol of a proxy by:

  1.  Analyzing the GET and POST operations,
  2.  Receive the whole request as a binary transfer,
  3.  Tamper with the request,
  4.  Send the obtained request in the connection to the destination IP,
  5.  Then you can capture the reply,
  6.  Tamper the received reply, and
  7.  Send the resulting response to the client webView.

Here I have no experience, but the path seems clear. It would be a lot of  coding, but I think this is really a good option if not the only option

And more importantly: it can be done!



来源:https://stackoverflow.com/questions/10775154/get-raw-packet-data-from-qt-application

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!