Carder
Professional
- Messages
- 2,635
- Reaction score
- 2,055
- Points
- 113
This article is presented for informational purposes only and does not constitute a call to action. All information is aimed at protecting readers from illegal actions.
The link above leads to a page dedicated to a similar device like mine - Alcatel MW40V, but the program also worked on my Alcatel MW41 and seems to work on other similar devices as well. The work of the program is apparently based on the fact that when the router is connected to a computer, it looks like an external hard drive. TCL-SWITCH-TOOL does something with the device, it goes into debug mode, which gives us root access to the shell.
The program is designed exclusively for Windows. But, most likely, it should work under Wine as well. I downloaded the program, launched it, pressed the button SWITCH : 0x16 0xF9(debug)to switch the device to debug mode and ...
50? Strange ... Closing this window results in another error.
In the terminal that I used to start the program, I saw a warning with the following content:
It looks like we're being told that a program is using a feature that Wine does not fully support.
Here I could find a Windows computer and use it. But we are not looking for easy ways! Can you find out exactly how this program works and reproduce it yourself?
In the XREF list, you can see that there are references to the string in four different functions
Given that the program asks for the drive letter for the router, it seems reasonable to assume that it is somehow sending some special commands to the drive using an existing connection. That is, it does not use some exotic USB protocol. A feeling that it confirms the presence of such a line code: \\.\PHYSICALDRIVE%c. This may indicate that some mechanism is being used for direct disk access.
Mysterious line \\. \ PHYSICALDRIVE% c
Imagine that the program somehow opens the disk, and then, performing some mysterious actions, puts the router into debug mode. The complexity of TCL-SWITCH-TOOL is not important in this case, because in the end, to perform both of these operations, you need to use the Windows API, which is an external resource in relation to the program.
This is very similar to how strace works on Linux. But here all the code runs in user mode, and we just watch the crossing of boundaries between two different DLLs. Strace, on the other hand, monitors system calls when a kernel feature is requested. A closer analogue of this from the Linux world is called ltrace.
So, I ran the following command:
Then I entered the drive name and clicked a button to put the router into debug mode. As a result, I ended up with a rather long log file (namely, its size was 150 MB). I searched for the PHYSICALDRIVE keyword, which I know from previous experiments, and ... nothing. Since this approach didn't work, I decided to look up the drive name I entered (F), believing that the program should probably convey the Windows drive name in some way.
Then TCL-SWITCH-TOOL makes another call. This time, the DeviceIoControl function from KERNEL32 is called. This function is similar to what we are looking for; it is passed a single parameter, 4d014. This value corresponds to the error message that we constantly received from Wine at the very beginning. True, I still did not understand what happened to the \\ line. \ PHYSICALDRIVE% c. And later it turned out that this is one of the ways to access disks in Windows, when the disk index was used, not its name. This line was probably used in another component of the program.
What is it DeviceIoControl? If you look at the official Microsoft documentation, it turns out that this is a fairly universal function that performs certain actions based on a parameter dwIoControlCode(in general, it can be called the Windows version of ioctl). In our case, the value dwIoControlCodeis 0x4d014what corresponds to IOCTL_SCSI_PASS_THROUGH_DIRECT, which, according to the documentation, "allows the application to send almost any SCSI command to the target device."
In the lower right corner of the previous illustration, there is a line that starts with XREF. It tells us that there is only one reference to this function in the entire program (that is, we are told that the function is called only once in the program). Double clicking on this line takes us to the code that calls DeviceIoControl.
So, I winedbg --gdb TCL-SWITCH-TOOL.exeran the command and used the command b *0x4031d4to set a breakpoint. After that, I tried to use the program again.
The breakpoint was hit! How do we deal with function arguments now?
Windows x86 systems use the cdecl function calling convention (that is, a set of rules that, among other things, indicate where function arguments and return values go). This means that the arguments had to be pushed onto the stack. GDB allows you to take a look at the current contents of the stack.
The command we're using here x/10x $sptells GDB to print 10 hexadecimal words starting at the address stored in the register sp(stack pointer). This approach works because the stack grows downward on x86 systems. See here for details.
The values from the stack can be mapped to the arguments of DeviceIoControl (I repeat, their description can be found here). The documentation says that IOCTL_SCSI_PASS_THROUGH_DIRECT accepts a SCSI command to send to the device via an input buffer, which must match the third argument of DeviceIoControl - lpInBuffer. In our case, the third argument is 0x32ed90. And the fourth argument, nInBufferSize, contains information about the size of this input buffer. This is 0x50 bytes. So let's take a look at 0x50 bytes from 0x32ed90.
So, is this the very command that allows the program to hack the router? The IOCTL documentation page tells us that it should be a structure SCSI_PASS_THROUGH_DIRECT. This is how it looks:
Data retrieved from GDB can be mapped to fields in this structure. On Windows, the data type ULONGis a 32-bit integer. In addition, when debugging 32-bit applications, keep in mind that PVOIDthis is also a 32-bit value.
Note that three bytes are used to align the data (this is PADDING in the table). The point is that the Microsoft C compiler must align DataTransferLength on 4-byte boundaries.
In other words, it should be the same command that puts your router into debug mode! Then when this command is sent because the DataIn flag is set to 0x01 (which is equivalent to SCSI_IOCTL_DATA_IN), Windows will read 0xc0 or 192 bytes (DataTransferLength value) from the device. The x86 architecture uses the little-endian format. Hence, bytes 0xc0 0x00 0x00 0x00 are interpreted as a 32-bit integer 0x000000c0.
Some research led me to the sg_raw command, a Linux tool that lets you send arbitrary commands to SCSI devices (in Ubuntu, this tool can be found in the sg3-utils package). If you use the value from Cdb, then the command we are interested in will look like this:
Here Xis the number corresponding to the disk of the router. It will probably be either 1 or - 2. You can use the command to view the list of SCSI devices connected to your computer ls /dev/sg*.
I tried this command.
Also, our last command only worked because the debug protocol is relatively simple. Having found the command we needed, we were able to recreate it ourselves. If the debug protocol was more complex (for example, if the command could have changed under the influence of some parameter, which, for example, could contain information about the current time), then a deeper analysis of the program should be carried out.
And one more thing - adb (Android Debug Bridge, Android debug bridge) is used to access the command shell of the router. While the router is not running Android, it probably uses adbd as well as some other Android components.
TCL-SWITCH-TOOL
Some research has led me to an affirmative answer to the first question. The device really runs Linux. And I also learned that there is a special program that can give root access to a mobile router. This is TCL-SWITCH-TOOL. The only mention of this program I found on one Russian forum. Where this program came from is not reported. The program looks damp, but not much.The link above leads to a page dedicated to a similar device like mine - Alcatel MW40V, but the program also worked on my Alcatel MW41 and seems to work on other similar devices as well. The work of the program is apparently based on the fact that when the router is connected to a computer, it looks like an external hard drive. TCL-SWITCH-TOOL does something with the device, it goes into debug mode, which gives us root access to the shell.
The program is designed exclusively for Windows. But, most likely, it should work under Wine as well. I downloaded the program, launched it, pressed the button SWITCH : 0x16 0xF9(debug)to switch the device to debug mode and ...
50? Strange ... Closing this window results in another error.
In the terminal that I used to start the program, I saw a warning with the following content:
Code:
0009: fixme: ntdll: server_ioctl_file Unsupported ioctl 4d014 (device = 4 access = 3 func = 405 method = 0)
It looks like we're being told that a program is using a feature that Wine does not fully support.
Here I could find a Windows computer and use it. But we are not looking for easy ways! Can you find out exactly how this program works and reproduce it yourself?
How it works?
I decided to investigate the program using Ghidra, a software reverse engineering tool. While searching through the text of the previous error message switch device error, I found several links to the corresponding string. They all looked like parts of relatively complex functions. Of course, this approach would also allow us to understand how the program works. But maybe there is an easier way to find out?
In the XREF list, you can see that there are references to the string in four different functions
Given that the program asks for the drive letter for the router, it seems reasonable to assume that it is somehow sending some special commands to the drive using an existing connection. That is, it does not use some exotic USB protocol. A feeling that it confirms the presence of such a line code: \\.\PHYSICALDRIVE%c. This may indicate that some mechanism is being used for direct disk access.
Mysterious line \\. \ PHYSICALDRIVE% c
Imagine that the program somehow opens the disk, and then, performing some mysterious actions, puts the router into debug mode. The complexity of TCL-SWITCH-TOOL is not important in this case, because in the end, to perform both of these operations, you need to use the Windows API, which is an external resource in relation to the program.
Wine Debug Materials
You can monitor API calls by using Wine's debugging capabilities to enable the relay debug channel. This system makes a log entry every time TCL-SWITCH-TOOL accesses an external library (on Windows, such libraries are called DLLs). I was hoping that it would be possible to detect a call to a certain Windows DLL, which is responsible for opening the disk, and send this DLL the appropriate commands. This would clarify the situation with exactly how the program works.This is very similar to how strace works on Linux. But here all the code runs in user mode, and we just watch the crossing of boundaries between two different DLLs. Strace, on the other hand, monitors system calls when a kernel feature is requested. A closer analogue of this from the Linux world is called ltrace.
So, I ran the following command:
Code:
WINEDEBUG = relay wine TCL-SWITCH-TOOL.exe &> tcllog.log
Then I entered the drive name and clicked a button to put the router into debug mode. As a result, I ended up with a rather long log file (namely, its size was 150 MB). I searched for the PHYSICALDRIVE keyword, which I know from previous experiments, and ... nothing. Since this approach didn't work, I decided to look up the drive name I entered (F), believing that the program should probably convey the Windows drive name in some way.
It worked!
It seemed to work! In the log, each line corresponds to either a function call (these are the lines labeled Call) or a return from it (the lines labeled Ret). At the top of the previous figure, you can see how TCL-SWITCH-TOOL calls the CreateFileA function, which is part of KERNEL32, passing \\. \\ F: (there is a double backslash in the log file, which is the result of escaping characters in double quotes) Then the Wine implementation for KERNEL32 itself calls some functions, after which it decides it is time to return some value (line 0009: Ret KERNEL32.CreateFileA () near the bottom of the above log snippet).Then TCL-SWITCH-TOOL makes another call. This time, the DeviceIoControl function from KERNEL32 is called. This function is similar to what we are looking for; it is passed a single parameter, 4d014. This value corresponds to the error message that we constantly received from Wine at the very beginning. True, I still did not understand what happened to the \\ line. \ PHYSICALDRIVE% c. And later it turned out that this is one of the ways to access disks in Windows, when the disk index was used, not its name. This line was probably used in another component of the program.
What is it DeviceIoControl? If you look at the official Microsoft documentation, it turns out that this is a fairly universal function that performs certain actions based on a parameter dwIoControlCode(in general, it can be called the Windows version of ioctl). In our case, the value dwIoControlCodeis 0x4d014what corresponds to IOCTL_SCSI_PASS_THROUGH_DIRECT, which, according to the documentation, "allows the application to send almost any SCSI command to the target device."
Command search
At this point, I got the impression that calling this function is the essence of TCL-SWITCH-TOOL. What SCSI command does the program send to the device? I used the Ghidra tool again to find out where the DeviceIoControl is being called from.
In the lower right corner of the previous illustration, there is a line that starts with XREF. It tells us that there is only one reference to this function in the entire program (that is, we are told that the function is called only once in the program). Double clicking on this line takes us to the code that calls DeviceIoControl.
Build in Ghidra
Now you can examine the assembly in Ghidra and see how the various arguments for DeviceIoControl are constructed. But the same can be done easier. We know that the function call is located at 0x4031d4. Hence, you can use the Wine debugger to set a breakpoint at this address. Then we can run the program, it will stop where we want it, and we can display the function arguments. Function addresses are usually randomized due to the use of ASLR. But GDB automatically disables ASLR. Therefore, we have nothing to worry about.So, I winedbg --gdb TCL-SWITCH-TOOL.exeran the command and used the command b *0x4031d4to set a breakpoint. After that, I tried to use the program again.
The breakpoint was hit! How do we deal with function arguments now?
Windows x86 systems use the cdecl function calling convention (that is, a set of rules that, among other things, indicate where function arguments and return values go). This means that the arguments had to be pushed onto the stack. GDB allows you to take a look at the current contents of the stack.
The command we're using here x/10x $sptells GDB to print 10 hexadecimal words starting at the address stored in the register sp(stack pointer). This approach works because the stack grows downward on x86 systems. See here for details.
The values from the stack can be mapped to the arguments of DeviceIoControl (I repeat, their description can be found here). The documentation says that IOCTL_SCSI_PASS_THROUGH_DIRECT accepts a SCSI command to send to the device via an input buffer, which must match the third argument of DeviceIoControl - lpInBuffer. In our case, the third argument is 0x32ed90. And the fourth argument, nInBufferSize, contains information about the size of this input buffer. This is 0x50 bytes. So let's take a look at 0x50 bytes from 0x32ed90.
So, is this the very command that allows the program to hack the router? The IOCTL documentation page tells us that it should be a structure SCSI_PASS_THROUGH_DIRECT. This is how it looks:
Code:
typedef struct _SCSI_PASS_THROUGH_DIRECT {
USHORT Length;
UCHAR ScsiStatus;
UCHAR PathId;
UCHAR TargetId;
UCHAR Lun;
UCHAR CdbLength;
UCHAR SenseInfoLength;
UCHAR DataIn;
ULONG DataTransferLength;
ULONG TimeOutValue;
PVOID DataBuffer;
ULONG SenseInfoOffset;
UCHAR Cdb [16];
} SCSI_PASS_THROUGH_DIRECT, * PSCSI_PASS_THROUGH_DIRECT;
Data retrieved from GDB can be mapped to fields in this structure. On Windows, the data type ULONGis a 32-bit integer. In addition, when debugging 32-bit applications, keep in mind that PVOIDthis is also a 32-bit value.
Note that three bytes are used to align the data (this is PADDING in the table). The point is that the Microsoft C compiler must align DataTransferLength on 4-byte boundaries.
Play command
Now that we have decoded the structure above, let's find out exactly what actions this structure suggests to start Windows. Most areas are not interesting to us. The most important field for us is Cdb. According to the documentation, it "defines the SCSI command descriptor block to be sent to the target device."In other words, it should be the same command that puts your router into debug mode! Then when this command is sent because the DataIn flag is set to 0x01 (which is equivalent to SCSI_IOCTL_DATA_IN), Windows will read 0xc0 or 192 bytes (DataTransferLength value) from the device. The x86 architecture uses the little-endian format. Hence, bytes 0xc0 0x00 0x00 0x00 are interpreted as a 32-bit integer 0x000000c0.
Some research led me to the sg_raw command, a Linux tool that lets you send arbitrary commands to SCSI devices (in Ubuntu, this tool can be found in the sg3-utils package). If you use the value from Cdb, then the command we are interested in will look like this:
Code:
sudo sg_raw / dev / sgX 16 f9 00 00 00 00 00 00 00 00 00 00 00 00 00 -v
Here Xis the number corresponding to the disk of the router. It will probably be either 1 or - 2. You can use the command to view the list of SCSI devices connected to your computer ls /dev/sg*.
I tried this command.
Outcome
If you read my story carefully, you might have noticed that the first two bytes of the command (0x16 0xf9) are the same, written in TCL-SWITCH-TOOL, SWITCH: 0x16 0xF9 (debug), the button used to put the router into debug mode (You can see this in the screenshot at the beginning of the article). But, although the solution to our problem was initially so close, I don't think I did all this work in vain. All of this helped me understand exactly how these bytes are formed. In addition, this means that perhaps the device can be switched to "diagnostic mode", "diag", because the other button has the corresponding SWITCH inscription: 0x16 0xF5 (diag) (I think the word "diag" The button is associated with the Qualcomm DIAG protocol, but I'm still looking for this problem).Also, our last command only worked because the debug protocol is relatively simple. Having found the command we needed, we were able to recreate it ourselves. If the debug protocol was more complex (for example, if the command could have changed under the influence of some parameter, which, for example, could contain information about the current time), then a deeper analysis of the program should be carried out.
And one more thing - adb (Android Debug Bridge, Android debug bridge) is used to access the command shell of the router. While the router is not running Android, it probably uses adbd as well as some other Android components.