Finding TeamViewer 0days. Part 1: The story begins
正在查找 TeamViewer 0 天。第 1 部分:故事开始
This series of blog posts are about some findings related to TeamViewer (TV) IPC communication with its SYSTEM service. I was trying to find some vulnerabilities in TeamViewer client and ended up researching how the communication with its helper service works. After being able to spoof (just some simple authentication as we will see) a valid TeamViewer client when connecting to the SYSTEM service IPC, it was possible to trigger an arbitrary driver installation. TeamViewer was not verifying the signature of the driver being installed. They passed the arbitrary inf to UpdateDriverForPlugAndPlayDevices.
本系列博客文章是关于 TeamViewer (TV) IPC 与其 SYSTEM 服务通信相关的一些发现。我试图在 TeamViewer 客户端中查找一些漏洞,并最终研究了与其帮助服务的通信是如何工作的。在连接到 SYSTEM 服务 IPC 时能够欺骗(正如我们将看到的只是一些简单的身份验证)有效的 TeamViewer 客户端后,可以触发任意驱动程序安装。TeamViewer 未验证正在安装的驱动程序的签名。他们将任意 inf 传递给 UpdateDriverForPlugAndPlayDevices。
Thus a privilege escalation USER to KERNEL was possible thanks to TeamViewer.
因此,多亏了 TeamViewer,可以将 USER 权限提升到 KERNEL。
As we will see, one of the best approaches is to use the well-known technique BYOD, Bring Your Own Vulnerable Driver to load a valid signed driver into Windows Kernel and then exploit it in order to perform privileged actions from user level, like changing the token of an arbitrary process with a privileged one.
正如我们将看到的,最好的方法之一是使用众所周知的技术 BYOD,即自带易受攻击的驱动程序,将有效的签名驱动程序加载到 Windows 内核中,然后利用它来从用户级别执行特权操作,例如将任意进程的令牌更改为特权进程。
Background 背景
First of all, some background in order to understand some later things. This vulnerability is not exploitable when TeamViewer is just run on the system, it is necessary to install TeamViewer.
首先,了解一些背景知识,以便了解后面的一些事情。当 TeamViewer 仅在系统运行时,此漏洞无法利用,需要安装 TeamViewer。
When TeamViewer is installed on the system, it creates a service that runs as SYSTEM, TeamViewer_service.exe
当 TeamViewer 安装在系统上时,它会创建一个以 SYSTEM TeamViewer_service.exe
This service is a helper for the client to some tasks. Thus, the client does not run with elevated privileges and some tasks are delegated to the service.
此服务是客户端完成某些任务的帮助程序。因此,客户端不会使用提升的权限运行,并且某些任务会委派给服务。
The communication with the service (IPC) is implemented through sockets (using Overlapped I/O and IoCompletionPort). By default, TeamViewer SYSTEM services listens on 5939/tcp at localhost.
与服务 (IPC) 的通信是通过套接字 (使用重叠 I/O 和 IoCompletionPort) 实现的。默认情况下,TeamViewer SYSTEM 服务侦听 localhost 上的 5939/tcp。
C:\Windows\system32>netstat -ano | findstr /i 15792 TCP 127.0.0.1:5939 0.0.0.0:0 LISTENING 15792 TCP 127.0.0.1:5939 127.0.0.1:64668 ESTABLISHED 15792 [...] |
I tested and the exploit worked on the following TV versions:
我测试了该漏洞,该漏洞适用于以下 TV 版本:
- 15.53.7
- 15.54.6
While testing with TeamViewer some functionality attracted my attention. The ability to install its VPN and Printer Driver just by click. I tested with an unprivileged users and it worked too.
在使用 TeamViewer 进行测试时,一些功能引起了我的注意。只需单击即可安装其 VPN 和打印机驱动程序。我与非特权用户进行了测试,它也有效。
Curiosity killed the cat.
好奇害死猫。
So, the question is, how is that implemented :)? And the journey researching started.
那么,问题是,:)如何实现呢?研究之旅开始了。
First Steps 第一步
At my first try, I was running TV with an administrator user, although with Medium Integrity Level.
在我第一次尝试时,我正在使用管理员用户运行 TV,尽管具有中等完整性级别。
So I tried launching the Driver Install with an unprivileged user and that worked too.
所以我尝试使用非特权用户启动驱动程序安装,这也有效。
TeamViewer logged the installation process. Fourth columns indicates which entity logged. S0 is for SYSTEM process logs. The symbol after S0 indicates the type of log, + appears to indicate level of verbosity. More +, move verbose. When a error occurs, ! are used.
TeamViewer 记录了安装过程。第四列表示记录的实体。S0 用于 SYSTEM 进程日志。S0 后面的符号表示日志的类型,+ 表示详细程度。更多 +,移动冗长。发生错误时,使用 !。
2024/05/26 20:36:39.130 2036 10604 S0+ GetSimpleDisplayCertNameFromFile: Found cert name: 'TeamViewer Germany GmbH'. 2024/05/26 20:36:39.130 2036 10604 S0+ VerifyTeamViewerCertificate: File for loading certificate is C:\Program Files\TeamViewer\tv_x64.exe 2024/05/26 20:36:39.130 2036 10604 S0+ VerifyTeamViewerCertificate: SHA256 code path. 2024/05/26 20:36:39.130 2036 10604 S0+ SHA256 certificate check. 2024/05/26 20:36:39.130 2036 10604 S0+ VerifyCertHash(): Certificate check succeded. 2024/05/26 20:36:39.130 2036 10604 S0+ tvnetwork::IpcLoaderProcessHandlerWin::Received_StartLoaderProcess: Starting Loader Process C:\Program Files\TeamViewer\tv_x64.exe (type 2) for ID 1500170772 in session 2 with args --action install --verbose --log C:\Program Files\TeamViewer\TeamViewer15_Logfile.log --event Local\DriverInstallFinishEvent_VPN --inf C:\Program Files\TeamViewer\x64\TeamViewerVPN.inf --id TEAMVIEWERVPN 2024/05/26 20:36:39.130 2036 10604 S0 CToken::GetSystemToken() set session 2 2024/05/26 20:36:39.130 2036 10604 S0+ ProcessWin::CreateProcessInternal: CreateProcess C:\Program Files\TeamViewer\tv_x64.exe AsUser 2024/05/26 20:36:39.130 2036 10604 S0 tvnetwork::IpcLoaderProcessHandlerWin::Received_StartLoaderProcess: Loader process started, pid = 13920 2024/05/26 20:36:39.146 13920 14904 L64 Loader started with: "C:\Program Files\TeamViewer\tv_x64.exe" --action install --verbose --log C:\Program Files\TeamViewer\TeamViewer15_Logfile.log --event Local\DriverInstallFinishEvent_VPN --inf C:\Program Files\TeamViewer\x64\TeamViewerVPN.inf --id TEAMVIEWERVPN |
Notice last line, where it is possible to observer that a helper binary is being launched as SYSTEM.
请注意最后一行,在这里可以观察到帮助程序二进制文件作为 SYSTEM 启动。
2024/05/26 20:36:39.146 13920 14904 L64 Loader started with: "C:\Program Files\TeamViewer\tv_x64.exe" --action install --verbose --log C:\Program Files\TeamViewer\TeamViewer15_Logfile.log --event Local\DriverInstallFinishEvent_VPN --inf C:\Program Files\TeamViewer\x64\TeamViewerVPN.inf --id TEAMVIEWERVPN |
Interesting, a SYSTEM process is being created that installs the driver given an INF file. This process ends calling UpdateDriverForPlugAndPlayDevicesA
without verification of the signature (Catalog File).
有趣的是,正在创建一个 SYSTEM 进程,该进程在给定 INF 文件的情况下安装驱动程序。此过程结束调用 UpdateDriverForPlugAndPlayDevicesA
,而不验证签名 (目录文件)。
Where that parameters come from?
这些参数从何而来?
I started then investigating the IPC communication. After some API Monitor (what a f*cking such great tool) hours. I will not bore you with the trial and error of different filters and time studying IPC communication. We now know that is using 5939/tcp, so lets analyze Networking APIs.
然后我开始调查 IPC 通信。经过一些 API 监控器(多么这么棒的工具)几个小时后。我不会让您厌烦不同过滤器的试错和时间学习 IPC 通信。我们现在知道它使用的是 5939/tcp,因此让我们分析一下 Networking API。
When launching TV it is possible to see that it is using a proprietary protocol. One can think at first that it is encrypted or something like that. But not, TV is not using encryption on its communication.
启动 TV 时,可以看到它正在使用专有协议。起初人们可能会认为它是加密的或类似的东西。但事实并非如此,TV 并未对其通信使用加密。
The interesting part is, what happens when the button of Install VPN Driver is clicked?
有趣的是,当单击“安装 VPN 驱动程序”按钮时会发生什么?
Oh, oh, Houston… 哦,哦,休斯顿……
The client is sending the INF parameter to the SYSTEM service and the SYSTEM service calling the tv_x64.exe with that parameter.
客户端将 INF 参数发送到 SYSTEM 服务,而 SYSTEM 服务使用该参数调用 tv_x64.exe。
So the idea was clear, if we send an IPC message to the SYSTEM service indicating an arbitrary INF parameter, will we install an arbitrary driver?
所以想法很明确,如果我们向 SYSTEM 服务发送一条 IPC 消息,指示任意 INF 参数,我们是否会安装任意驱动程序?
Here is another view from Wireshark.
这是来自 Wireshark 的另一个视图。
(Not just the INF parameter is send, but I am skipping the other part as the most relevant one is the INF parameter. Notice the Event message Local\DriverInstallFinishEvent).
(不仅 INF 参数是 send,而且我跳过了另一部分,因为最相关的部分是 INF 参数。请注意事件消息 Local\DriverInstallFinishEvent)。
IPC Communication Protocol
IPC 通信协议
This part is the consequence of all the reversing and research of the TV adventure. Chronologically it should be placed the last one, but I think the next sections will be understood better if we first study the IPC communication protocol.
这部分是电视冒险的所有反转和研究的结果。按时间顺序,它应该放在最后一个,但我认为如果我们先研究 IPC 通信协议,接下来的部分会更好地理解。
TV IPC messages are simple. The all have the following structure.
电视 IPC 消息很简单。它们都具有以下结构。
HEADER BODY TAIL |
页眉 身体 尾巴 |
We have a Header that contains some metadata for the message itself, like the length, the type of message, the length of itself, etc.
我们有一个 Header,其中包含消息本身的一些元数据,比如长度、消息类型、自身长度等。
We then have the body with the data of the message at issue.
然后,我们得到了包含有问题的消息数据的正文。
Finally we have a tail that contains always the same signature plus some identifier.
最后,我们有一个尾部,它总是包含相同的签名和一些标识符。
HEADER 页眉
The header is 8-bytes long, but I will consider it as 16-bytes long because after that comes another sub header of another 8 bytes before the body. So, to our understanding, we have 16-byte header before the body. It contains the following fields, where IDK means I don’t kwon.
标头长 8 字节,但我会将其视为 16 字节长,因为在此之后是正文之前另一个 8 字节的 sub 标头。因此,据我们理解,我们在正文之前有 16 字节的标头。它包含以下字段,其中 IDK 表示 I don’t kwon。
| 0 || 1 || 2 || 3 || 4 || 5 || 6 || 7 || 8 || 9 || 10 || 11 || 12 || 13 || 14 || 15 || 16 | | Length of Header || IDK || IDK || IDK || 4-byte Msg Length || 3-byte Msg Length || 2-byte Msg Length || 1-byte Msg Length || IDK || Type of Message || IDK || Direction (Client or Server MSG) || IDK || IDK || IDK || IDK | |
I have always see the header having 8-bytes, so the first byte of the message is always 0x08.
我总是看到标头有 8 个字节,因此消息的第一个字节始终是 0x08。
BODY 身体
What to say? This part contains the non-encrypted data. Like the INF parameter :).
该说什么呢?此部分包含未加密的数据。与 INF 参数:)类似。
TAIL 尾巴
I have found that the last part of the IPC message may vary, but it always start with 0xfe 0x01 0x00 0x00
我发现 IPC 消息的最后一部分可能会有所不同,但它总是以 0xfe 0x01 0x00 0x00 开头
I have not investigate in depth this part, I have always maintain the same bytes copied from capture messages.
我没有深入研究这部分,我始终维护从捕获消息中复制的相同字节。
The last 4-bytes appears to be an identifier.
最后 4 个字节似乎是一个标识符。
Here are the exact messages most relevant for this research.
以下是与本研究最相关的确切信息。
Authentication Messages 身份验证消息
I will get into more detail about the authentication process in the dedicated part about it (Part 2). This subsection will describe the message itself.
我将在有关身份验证过程的专门部分(第 2 部分)中详细介绍该验证过程。此小节将描述消息本身。
The authentication process has two types of messages. One type of messages that is used by the client and the other type of message that is used by the server. The difference between this two is that Client -> Server message contains 8-byte in the body, while the server contains 16-byte in the body. We will see it later why.
身份验证过程有两种类型的消息。一种类型的消息由客户端使用,另一种类型的消息由服务器使用。这两者的区别在于 Client -> Server 消息的正文中包含 8 字节,而服务器在正文中包含 16 字节。我们稍后会看到为什么。
Messages from client to server
从客户端到服务器的消息
Here it is possible to see a message from client to server that we will thresh.
在这里,可以看到从客户端到服务器的消息,我们将要 thresh。
0000 08 00 01 00 1d 00 00 00 2d 02 09 10 00 00 00 b7 ........-....... 0010 48 77 26 8a 72 b8 f0 fe 57 04 03 fc 64 2e b0 fe Hw&.r...W...d... 0020 01 00 00 00 01 ..... |
- First of all we have the header
首先,我们有标题08 00 01 00 1d 00 00 00
08 00 01 00 1d 00 00 00 00
- As we can see it is 8-bytes long (as indicated by the first byte). The next three bytes appear to be always the same and I do not known exactly their task.
正如我们所看到的,它的长度为 8 字节(如第一个字节所示)。接下来的三个字节似乎总是相同的,我不知道他们的任务。 - Then we have the next 4-bytes, indicating the length of the message.
然后我们有接下来的 4 个字节,表示消息的长度。
- The we have the sub header
我们有 sub 标头2d 02 09 10 00 00 00
2天 02 09 10 00 00 00 00
- This sub header is indicating the type of message.
2d 02 09
is for Authentication Message client to server, while, as we will see,2d 03 09
is for Authentication Message Server to client
此 sub 报头指示消息的类型。2d 02 09
用于身份验证消息客户端到服务器,而正如我们将看到的,2d 03 09
用于身份验证消息服务器到客户端 - I do not know what
10 00 00 00
represent, it is the same sequence in both direction of the message.
我不知道10 00 00 00
代表什么,它在消息的两个方向上都是相同的序列。
- Then we have the 16-byte challenge sent by the client to the server.
然后我们有客户端发送到服务器的 16 字节质询。b7 48 77 26 8a 72 b8 f0 fe 57 04 03 fc 64 2e b0
- At the end we have the tail. I dot not know exactly what indicates this bytes, but it is always the same.
最后我们有尾巴。我不知道这个字节的确切含义,但它总是相同的。fe 01 00 00 00 01
费 01 00 00 00 01
Message from Server to Client
从 Server 到 Client 的消息
Here it is possible to see a message from server to the client that we will thresh too.
在这里,可以看到从服务器到客户端的消息,我们也将 thresh。
0000 08 00 01 00 32 00 00 00 2d 03 09 10 00 00 00 29 ....2...-......) 0010 7e d4 88 48 ed 9e 18 5c 3a 4a 12 ce 6e ab 22 0a ~..H...\:J..n.". 0020 10 00 00 00 4b 85 07 8b 3f 21 76 0d a5 fa 62 9b ....K...?!v...b. 0030 a7 5e d1 4a fe 01 00 00 00 01 .^.J...... |
In this case, we have mostly the same, but in this case the message is larger because we have two 16-byte message in this body. The first 16-byte is the challenge sent by the server and the next 16-byte is the response to our sent challenge.
在这种情况下,我们的内容基本相同,但在本例中,消息更大,因为我们在这个正文中有两条 16 字节的消息。前 16 字节是服务器发送的质询,下一个 16 字节是对我们发送的质询的响应。
- First of all we have the header
首先,我们有标题08 00 01 00 1d 00 00 00
08 00 01 00 1d 00 00 00 00
- As we can see it is 8-bytes long (as indicated by the first byte). The next three bytes appear to be always the same and I do not known exactly their task.
正如我们所看到的,它的长度为 8 字节(如第一个字节所示)。接下来的三个字节似乎总是相同的,我不知道他们的任务。 - Then we have the next 4-bytes, indicating the length of the message.
然后我们有接下来的 4 个字节,表示消息的长度。
- The we have the sub header
我们有 sub 标头2d 03 09 10 00 00 00
2d 03 09 10 00 00 00 00
- This sub header is indicating the type of message,
2d 03 09
. Notice that before we had2d 03 09
.
此 sub 报头指示消息的类型,即 2d 03 09
。请注意,在我们之前有2d 03 09
。 - I do not know what
10 00 00 00
represent, it is the same sequence in both direction of the message.
我不知道10 00 00 00
代表什么,它在消息的两个方向上都是相同的序列。
- Then we have the 16-byte challenge sent by the server to the client.
然后我们有服务器发送到客户端的 16 字节质询。29 7e d4 88 48 ed 9e 18 5c 3a 4a 12 ce 6e ab 22
- After that comes the separator
之后是分隔符0a 10 00 00 00
0a 10 00 00 00 00
- Then we have the response to our challenge from the server.
然后,我们从服务器获得对质询的响应。4b 85 07 8b 3f 21 76 0d a5 fa 62 9b a7 5e d1 4a
- At the end we have the tail. I dot not know exactly what indicates this bytes, but it is always the same.
最后我们有尾巴。我不知道这个字节的确切含义,但它总是相同的。fe 01 00 00 00 01
费 01 00 00 00 01
Control IPC Message 控制 IPC 消息
Once the authentication has completed successfully the client sent to the server a message that contains the PID of process connecting and a identifier and the version, that need to Mach with the TeamViewer Service version. There is more data but I have not researched about it and appeared to not be relevant, so I just maintain the same bytes when connecting from the exploit.
身份验证成功完成后,客户端向服务器发送一条消息,其中包含进程连接的 PID 以及需要与 TeamViewer Service 版本配合使用的标识符和版本。有更多的数据,但我没有对其进行研究,而且似乎无关紧要,因此我在从漏洞利用连接时只保持相同的字节。
Here is an example message.
下面是一个示例消息。
0000 08 00 01 00 ac 00 00 00 01 12 01 04 00 00 00 78 ...............x 0010 22 00 00 02 04 00 00 00 02 00 00 00 03 01 00 00 "............... 0020 00 00 04 12 00 00 00 31 00 35 00 2e 00 35 00 33 .......1.5...5.3 0030 00 2e 00 37 00 20 00 00 00 05 04 00 00 00 01 00 ...7. .......... 0040 00 00 06 06 00 00 00 65 00 6e 00 00 00 07 01 00 .......e.n...... 0050 00 00 00 09 06 00 00 00 31 00 35 00 00 00 0a 06 ........1.5..... 0060 00 00 00 35 00 33 00 00 00 0b 04 00 00 00 37 00 ...5.3........7. 0070 00 00 0d 01 00 00 00 01 0e 04 00 00 00 dd 7b a7 ..............{. 0080 37 0f 04 00 00 00 1d bf 52 39 11 04 00 00 00 01 7.......R9...... 0090 00 00 00 f3 04 00 00 00 02 00 00 00 fd 04 00 00 ................ 00a0 00 fd cf ff 02 fe 01 00 00 00 01 ff 04 00 00 00 ................ 00b0 8c 83 14 3b ...; |
Again, we start with a similar header.
同样,我们从类似的标头开始。
- First of all we have the header
首先,我们有标题08 00 01 00 ac 00 00 00
08 00 01 00 交流 00 00 00
- As we can see it is 8-bytes long (as indicated by the first byte). The next three bytes appear to be always the same and I do not known exactly their task.
正如我们所看到的,它的长度为 8 字节(如第一个字节所示)。接下来的三个字节似乎总是相同的,我不知道他们的任务。 - Then we have the next 4-bytes, indicating the length of the message.
然后我们有接下来的 4 个字节,表示消息的长度。
- The we have the sub header
我们有 sub 标头01 12 01 04 00 00 00
. This indicates the type of message.
01 12 01 04 00 00 00
.这表示消息的类型。
- Then, we have 4-byte indicating the PID connecting.
然后,我们有 4 字节表示 PID 正在连接。78 22 00 00
. 8824 in this case.
78 22 00 00
.在本例中为 8824。
- Then, in bytes 0x27 to 0x34 we have the version of TeamViewer. In this case it is 15.53.7.
然后,以字节数0x27到 0x34 我们得到了 TeamViewer 的版本。在本例中为 15.53.7。- This needs to match with the TeamViewer service. In this case, if the TeamViewer client indicates a version different of 15.53.7 the IPC connection will be terminated by the service because of the version mismatch.
这需要与 TeamViewer 服务匹配。在这种情况下,如果 TeamViewer 客户端指示的版本不同于 15.53.7,则服务将因版本不匹配而终止 IPC 连接。 31 00 35 00 2e 00 35 00 33 00 2e 00 37
- This needs to match with the TeamViewer service. In this case, if the TeamViewer client indicates a version different of 15.53.7 the IPC connection will be terminated by the service because of the version mismatch.
- The version is later on the message again, but separated by each number of the versoin.
版本稍后再次出现在消息中,但由反面的每个数字分隔。- In bytes 0x58 to 0x5b we have the major number of the version. 15 in this case
以 0x58 到 0x5b 的字节数,我们有版本的主要编号。在本例中为 15 - In bytes 0x63 to 0x66 we have the medium number of the version.
以 0x63 到 0x66 的字节数,我们有版本的中等编号。 - In bytes 0x6e to 0x6f we have the last number of the version.
以字节数0x6e到 0x6f 我们得到了版本的最后一个数字。
- In bytes 0x58 to 0x5b we have the major number of the version. 15 in this case
- The rest of the body I do not known what it does, it was necessary only to write the correct PID.
我不知道正文的其余部分是做什么的,只需要编写正确的 PID。 - In this case the tail is a bit different because it contains the following bytes after the common one,
ff 04 00 00 00 95 d4 04 31
.
在这种情况下,尾部有点不同,因为它在公共字节之后包含以下字节,ff 04 00 00 00 95 d4 04 31
。 - At the end there it is a generated identifier that is used in later messages.
最后,它是一个生成的标识符,用于以后的消息。8c 83 14 3b
- I have also see that the language is indicate in this message. In this case en.
我还看到此消息中指示了语言。在本例中为 en.Driver Install Request Message
驱动程序安装请求消息
Once we have authenticated and we have send the Control IPC message with the correct PID we are able to send the Driver Install Message. YUP! :).
通过身份验证并发送具有正确 PID 的 Control IPC 消息后,我们就可以发送驱动程序安装消息。是的!:).
In this message, among other things, we are indicating the –inf parameter that will be used later by the SYSTEM process, allowing us to install an arbitrary Kernel Driver from an unprivileged user.
在此消息中,除其他外,我们指示 –inf 参数,该参数稍后将由 SYSTEM 进程使用,允许我们从非特权用户安装任意内核驱动程序。
Here is an example message.
下面是一个示例消息。
0000 08 00 01 00 35 01 00 00 33 0c 01 01 00 00 00 01 ....5...3....... 0010 02 04 00 00 00 02 00 00 00 03 96 00 00 00 2d 00 ..............-. 0020 2d 00 69 00 6e 00 66 00 20 00 43 00 3a 00 5c 00 -.i.n.f. .C.:.\. 0030 4e 00 6f 00 74 00 20 00 50 00 72 00 6f 00 67 00 N.o.t. .P.r.o.g. 0040 72 00 61 00 6d 00 20 00 46 00 5c 00 61 00 61 00 r.a.m. .F.\.a.a. 0050 61 00 61 00 61 00 61 00 61 00 61 00 61 00 61 00 a.a.a.a.a.a.a.a. 0060 5c 00 62 00 62 00 62 00 5c 00 41 00 6e 00 6f 00 \.b.b.b.\.A.n.o. 0070 74 00 68 00 65 00 72 00 54 00 68 00 69 00 6e 00 t.h.e.r.T.h.i.n. 0080 67 00 67 00 2e 00 69 00 6e 00 66 00 20 00 2d 00 g.g...i.n.f. .-. 0090 2d 00 69 00 64 00 20 00 54 00 45 00 41 00 4d 00 -.i.d. .T.E.A.M. 00a0 56 00 49 00 45 00 57 00 45 00 52 00 56 00 50 00 V.I.E.W.E.R.V.P. 00b0 4e 00 00 00 05 02 00 00 00 00 00 06 02 00 00 00 N............... 00c0 00 00 07 01 00 00 00 00 08 46 00 00 00 4c 00 6f .........F...L.o 00d0 00 63 00 61 00 6c 00 5c 00 44 00 72 00 69 00 76 .c.a.l.\.D.r.i.v 00e0 00 65 00 72 00 49 00 6e 00 73 00 74 00 61 00 6c .e.r.I.n.s.t.a.l 00f0 00 6c 00 46 00 69 00 6e 00 69 00 73 00 68 00 45 .l.F.i.n.i.s.h.E 0100 00 76 00 65 00 6e 00 74 00 5f 00 56 00 50 00 4e .v.e.n.t._.V.P.N 0110 00 00 00 09 04 00 00 00 00 00 00 00 f3 04 00 00 ................ 0120 00 02 00 00 00 fd 04 00 00 00 01 00 00 00 fe 01 ................ 0130 00 00 00 01 ff 04 00 00 00 95 d4 04 31 ............1 |
- First of all we have the header
首先,我们有标题08 00 01 00 35 01 00 00
- As we can see it is 8-bytes long (as indicated by the first byte). The next three bytes appear to be always the same and I do not known exactly their task.
正如我们所看到的,它的长度为 8 字节(如第一个字节所示)。接下来的三个字节似乎总是相同的,我不知道他们的任务。 - Then we have the next 4-bytes, indicating the length of the message.
然后我们有接下来的 4 个字节,表示消息的长度。
- The we have the sub header
我们有 sub 标头33 0c 01 01 00 00 00
. This indicates the type of message.
33 0c 01 01 00 00 00
.这表示消息的类型。
- Then, we have 22 bytes that I always maintain the same and I actually do not kwow that the mean.
然后,我们有 22 个字节,我总是保持相同,我实际上并不关心这个平均值。 - After that, there is the –inf parameter string.
之后是 –inf 参数字符串。 - There comes some other parameters and the end.
还有一些其他参数和结束。 - In this case the tail is a bit different because it contains the following bytes after the common one,
ff 04 00 00 00 95 d4 04 31
.
在这种情况下,尾部有点不同,因为它在公共字节之后包含以下字节,ff 04 00 00 00 95 d4 04 31
。First Fail: Authentication needed
第一次失败:需要身份验证
My first try was to just send the Driver installation request. Short story, it does not work.
我的第一次尝试是只发送驱动程序安装请求。短篇小说,它不起作用。
I started looking at the log and it contained an error message from the IPC Structure Parser because it is expecting some type of message (the authentication one) that is different from the one we are sending.
我开始查看日志,其中包含来自 IPC Structure Parser 的错误消息,因为它需要某种类型的消息(身份验证消息),这与我们发送的消息不同。
It was then when I started capturing legitimate traffic and searching for patterns. I notice that the server was sending the 16-byte message shown before and that when sending the same first message the server responds back with the same 16-byte.
就在那时,我开始捕获合法流量并搜索模式。我注意到服务器正在发送之前显示的 16 字节消息,并且在发送相同的第一条消息时,服务器会使用相同的 16 字节消息进行响应。
ChatGPT started to help me to perform some analytical analysis from different inputs and we concluded that TV was using some type of encryption or hashing and not simple binary operations.
ChatGPT 开始帮助我从不同的输入进行一些分析分析,我们得出结论,TV 使用的是某种类型的加密或哈希,而不是简单的二进制运算。
When sending a well formatted message TV started to log invalid response from Received_IPC_Auth().
发送格式良好的消息时,TV 开始记录来自 Received_IPC_Auth() 的无效响应。
2024/05/26 19:03:04.770 3268 3660 S0!! InterProcessNetwork::Received_IPCAuth() invalid response |
So, we have to correctly authenticate first. As we will see, the authentication algorithm is not robust.
因此,我们必须先正确进行身份验证。正如我们将看到的,身份验证算法并不健壮。
Second Fail: Failing back to reversing
第二次失败:故障回复到倒车
Before starting reversing I tried if it was possible to take a shortest path. I tried to figure if there where some way of making TV showing why the authentication was failing.
在开始倒车之前,我尝试了是否可以走最短的路径。我试图弄清楚是否有某种方法可以制作电视来显示身份验证失败的原因。
I found a way to enable verbose and debug log output. TV do not log why the authentication is failing in the IPC, but I think is work mentioning and documenting all the registry keys the TV service tries to query and to take a note on the most interesting ones.
我找到了一种启用详细和调试日志输出的方法。TV 不会记录 IPC 中身份验证失败的原因,但我认为是提及和记录 TV 服务尝试查询的所有注册表项并记下最有趣的注册表项的工作。
I attach the process monitor result here: TODO INSERT LINK
我将进程监视器结果附加到此处:TODO INSERT LINK
- IPC_Port_Service: can be used to change the port where the SYSTEM service IPC listens.
IPC_Port_Service:可用于更改 SYSTEM 服务 IPC 监听的端口。 - Log_Level: it enables to modify the type of logs included. A tried so many values but did not take note of all sorry. Only for the debug, 0x40.
Log_Level:它可以修改包含的日志类型。A 尝试了很多值,但没有注意到所有抱歉。仅用于调试,0x40。 - LogLevelVerboseStarted: I have not seen any difference, but apparently it enables verbosity logging.
LogLevelVerboseStarted:我没有看到任何差异,但显然它启用了详细日志记录。 - IPCPassword: I have not tested it, but it should change the IPC secret.
IPCPassword: 我还没有测试过它,但它应该会改变 IPC 密钥。 - HooksLogVerbose: enable logging TV hooks in the file TeamViewer15_Hooks.log.
HooksLogVerbose:启用在文件TeamViewer15_Hooks.log记录 TV Hooks。
This approach was not successful, unless it was funny to understand another parts of TV. Like enabling debug output in the logs for example, and I think is worth the time.
这种方法并不成功,除非理解电视的其他部分很有趣。例如,就像在日志中启用 debug 输出一样,我认为值得花时间。
Finally, I ended up reversing the authentication mechanism. We will see that in detail in Part 2.
最后,我最终反转了身份验证机制。我们将在第 2 部分中详细介绍这一点。
After that, in Part 3, we will take a look at the exploit and how all the gear parts agree in order to enable privilege scalation from user to Kernel.
之后,在 第 3 部分 中,我们将了解漏洞利用以及所有 gear 部分如何一致,以便实现从用户到 Kernel 的权限扩展。
原文始发于Peter Gabaldon:Finding TeamViewer 0days – Part I