58489

Get raw packet data from Qt application

Question:

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?

Answer1:

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:

<ul><li>

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.

</li> <li>

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.

</li> <li>

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.

</li> </ul>

But... you want to access to the request and replied data for <strong>each</strong> 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:

<ul><li>

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

</li> <li>

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

</li> <li>

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, <strong>this method works only if the request is made to a non-HTTP destination</strong>. 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.

</li> <li>

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.

</li> </ul>

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

Sorry.

Answer2:

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 <a href="http://qt-project.org/doc/qt-4.8/QNetworkAccessManager.html" rel="nofollow">here</a> and <a href="http://qt-project.org/doc/qt-4.8/qnetworkreply.html" rel="nofollow">here</a>.

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().

<hr />

<strong>EDIT</strong>

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:

<ul><li>

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

</li> <li>

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

</li> <li>

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

</li> <li>

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

</li> </ul>

Look at the documentation for those functions.

<hr />

<strong>EDIT 2:</strong>

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!

Answer3:

It looks like you want Wireshark <a href="http://www.wireshark.org/" rel="nofollow">http://www.wireshark.org/</a> or Fiddler <a href="http://www.fiddler2.com/fiddler2/" rel="nofollow">http://www.fiddler2.com/fiddler2/</a>, or maybe even Charles <a href="http://www.charlesproxy.com/" rel="nofollow">http://www.charlesproxy.com/</a>.

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.

Answer4:

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

You can make one following the <a href="http://doc.qt.nokia.com/4.7-snapshot/network-loopback.html" rel="nofollow">loopback example</a> and the <a href="http://doc.qt.nokia.com/4.7-snapshot/network-torrent.html" rel="nofollow">torrent client example</a> among others. So you can capture and tamper the requests <strong>AND</strong> 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:

<ol><li> Analyzing the GET and POST operations,</li> <li> Receive the whole request as a binary transfer,</li> <li> Tamper with the request,</li> <li> Send the obtained request in the connection to the destination IP,</li> <li> Then you can capture the reply,</li> <li> Tamper the received reply, and</li> <li> Send the resulting response to the client webView.</li> </ol>

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

And more importantly: <strong>it can be done</strong>!

Recommend

  • Android capture video and upload it to server using single button
  • How to declare method globally in Class
  • Parsing large text files with Adobe AIR
  • progressdialog bar get freeze
  • Why generic T is inferred as a literal type only when it has a constraint?
  • Galaxy Tablet browser sniff / detection
  • Do I always need to use a cell array to assign multiple values to a struct array?
  • What is the Difference between system initialization and update in hybris?
  • Indentation standards when writing django Application
  • Kill unload function in JS?
  • Program doesn't stop after exception
  • Canceling async httpwebrequests
  • Is it OK to write code after [super dealloc]?
  • C++ std::set comparator
  • setContentView() is not enough to switch between layouts?
  • Freeing interfaced object that descends from a TRectangle
  • Classic ASP URL Rewriting
  • Using same constraints in multiple classes
  • LiveData is abstract android
  • Google Maps api v3 get start and end coordinates of a street
  • Laravel 4 routing not working due to .htaccess file?
  • Implicit joins and Where in Doctrine - how?
  • Button text different than value submitted in query string
  • Inline R code in YAML for rmarkdown doesn't run
  • Should I or shouldn't I use the CachingConnectionFactory with hornetq 2.4.1
  • Caching attributes in superclass
  • Swift: Switch statement fallthrough behavior
  • How to test if a URL from an Eclipse bundle is a directory?
  • JavaScriptCore crash on iOS9
  • How to recover from a Spring Social ExpiredAuthorizationException
  • ILMerge & Keep Assembly Name
  • Large data - storage and query
  • WOWZA + RTMP + HTML5 Playback?
  • Calling of Constructors in a Java
  • bootstrap to use multiple ng-app
  • How to get icons for entities from eclipse?
  • log4net write single file for each call to log.info
  • Exception on Android 4.0 `android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode)`
  • Turn off referential integrity in Derby? is it possible?
  • JaxB to read class hierarchy