Extracting TLS keys from an unwilling application

栏目: IT技术 · 发布时间: 4年前

内容简介:I want to be able to inspect the traffic of programs running on my computer. I don’t really trust those programs and ideally I’d like to put nearly all of them into a high security jail.One of those programs is Oculus software. There are a few reasons why

I want to be able to inspect the traffic of programs running on my computer. I don’t really trust those programs and ideally I’d like to put nearly all of them into a high security jail.

One of those programs is Oculus software. There are a few reasons why I want to be cautious about Oculus software.

  1. Oculus is owned by Facebook, which means Facebook can dictate what Oculus software does with user’s data.
  2. Oculus servers run on Facebook’s infrastructure, which means that Facebook can have access to any data uploaded to those servers.
  3. Oculus Headset has cameras and software that builds a 3D map of my room, which can be uploaded to the servers.
  4. Oculus Privacy Policy explicitly states that Oculus automatically collects:
    Information about your environment, physical movements, and dimensions when you use an XR device. For example, when you set up the Oculus Guardian System to alert you when you approach a boundary, we receive information about the play area that you have defined;
    

Fortunately, I can use programs such as Wireshark or tcpdump to inspect traffic sent to the servers.

Fortunately, Oculus is using TLS so that a third party cannot snoop on this data in transit.

Unfortunately, I am playing a role of “third party” in this case.

Fortunately, it’s possible to read process memory and extract secret keys and inspect TLS data.

Things that didn’t work

  • Setting SSLKEYLOGFILE variable – Oculus Runtime is using a 1.0.2o version of OpenSSL where this is not supported.
  • Extracting OpenSSL keys using an automated debugger – Oculus Runtime is using statically linked OpenSSL with no debug symbols.
  • Substituting OpenSSL library with one that can log secret keys – it’s statically linked.
  • I didn’t want to add extra root certificates and proxies to inspect all TLS traffic going on the machine.

Doing this the hard way

So the plan forward was to:

  • Figure out a code location where secret keys for the session are available
  • Patch or debug the program so that we can inspect and log those keys

A bit of reverse engineering

To figure out the code location some reverse-engineering was necessary. The first step was to figure out which version does Oculus Runtime use. Looking for strings in OculusAppFramework.dll , there was the following string: Stack part of OpenSSL 1.0.2o-fb10 27 Mar 2018 , which means I have a specific version that I work off.

After reading Introduction to OpenSSL programming on Linux Journal , I deduced that SSL_connect (and later SSL_set_connect_state ) may be a good place to interject OpenSSL for key extraction.

I’ve loaded up Oculus Runtime into Ghidra, opened up source code that contains public interface of OpenSSL ssl_lib.c and attempted to find common ground between those. The things of interest were integer and string constants which could be used as landmarks.

A particularly notable function is SSL_get_version , which contains references to multiple strings. Looking for TLSv1.2 yielded a few locations, particularly this one:

Extracting TLS keys from an unwilling application

It looks like SSL_get_version got inlined. I suspected that this was not the only place where TLS connections were made, so I had to find a different place to work on. The next notable thing was that near one of the SSL version strings I’ve noticed code paths and assertion strings:

Extracting TLS keys from an unwilling application

As it turns out, debug information such as source file names and assetion expressions, which can be used as landmarks too. Now we have more landmarks to navigate OpenSSL binary code.

I’ve continued to label function as I inspected nearby references to .\\ssl\ssl_lib.c strings, and I’ve stumbled onto SSL_set_connect_state function . Using the same code pattern, mov dword ptr [$register + 0x48], 0x5000 , I’ve found SSL_connect as well. SSL_connect had an inlined call to SSL_set_connect_state . I’ve decided to be cautious and interject both of these functions.

Extracting the data

These functions already have pointers to ssl_st struct, so let’s extract the data from there.

There were a few options to do this:

  • Use/write a programmable debugger and breakpoint/inspect values on those functions
  • Binary patch the DLL
  • Use DLL injection and patching in-memory DLL code

Since I’ve had poor experience with controlling debuggers programmatically, I didn’t want to go use the first option. This is a potential thing that I might want to improve. Since I didn’t want to invalidate a signed DLL, I didn’t binary patch it. Last option it is.

DLL injection

To extract all TLS keys, we need to control the running process from the very beginning. One way to do this is to set gflags to use DLL injector program as a debugger for the process. The program we want to debug is called OVRServer_x64.exe , so let’s create HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\OVRServer_x64.exe key in registry and set Debugger string value to command line of our injector.

The injector doesn’t have to do any debugging, but it needs to start a program with DEBUG_ONLY_THIS_PROCESS or DEBUG_PROCESS flag. Otherwise, our debugger will bespawned recursively.

The CreateRemoteThread DLL injection is itself a simple technique on Windows, it’s consicely described in a WikiLeaks article as well in other articles.

The code for injector.exe is here .

Running from inside the process

After the DLL was injected, it can patch the code in-memory and log secret keys.

The architecture for injectee.dll is pretty simple – patch the code, create a channel, create writer thread with the receiving end of the channel, send keys from different threads using the other end.

Patching was done in assembly. It can be approximately described like this:

Extracting TLS keys from an unwilling application

There are several ways to extract the keys ginen a pointer to ssl_st struct.

  • Implementing a C library
  • Walking the pointers manually
  • Porting OpenSSL structs to the used language

Initially I’ve implemented walking the pointers by hand, but that is a very fragile approach. Porting OpenSSL structs to Rust is quite cumbersome, so I’ve implemented a miniature C library to read secret keys given an ssl_st struct pointer.

The rest is plumbing, and we now can inspect TLS traffic in a running application:

Extracting TLS keys from an unwilling application

The code for injectee.dll is here .

If you’re interested, the entire code for the project is here: github.com/m1el/oculus-tls-extractor

Analysis of the data being sent by Oculus Runtime to the mothership is coming up in the follow-up post.


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

C++面向对象程序设计

C++面向对象程序设计

萨维奇 (Walter Savitch) / 周靖 / 清华大学出版社 / 2003-12 / 59.0

《C++面向对象程序设计》具备良好的编排体系,适合打算涉足编程领域的读者阅读,尤其适合大一学生。它最大的特色是Savitch教授最受欢迎的写作风格,这一风格非常适合初学者,能迅速引导他们开始编程实践。《C++面向对象程序设计》包括全面的习题、项目、编程提示、编程示例、编程陷阱以及有用的小结,以帮助初学者更清楚地了解C++。一起来看看 《C++面向对象程序设计》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试