FreeRTOS Introduction
FreeRTOS is a mini real-time operating system kernel. As a lightweight operating system, it includes functionalities such as task management, time management, semaphores, message queues, memory management, logging features, software timers, coroutines, etc., which can basically meet the needs of smaller systems.
Compiling FreeRTOS
Compilation Environment
· Windows 10 20H2
· Keil V5.33.0.0
Download the official source code from the FreeRTOS download link.

Unzip the downloaded file, and the obtained directory is as follows

Here we focus on FreeRTOS, which contains the FreeRTOS kernel code and the code we want to test.

We choose the STM32F103 series code for compilation, using Keil to open the project code for this series


Through Keil, we can see the entire project’s involved code.
Since the firmware we extracted is generally in BIN format, we need to set it in Keil, and finally compile to generate a BIN file.

Add the following code in the After Build/Rebuild option at Run#1:
D:\keilv5_core\ARM\ARMCC\bin\fromelf.exe --bin -o .\bin\RTOSDemo.bin .\RTOSDemo.axf
Here fromelf.exe is the application that formats it into BIN, -o indicates that the compiled BIN file will be stored in the bin directory under the current directory, and if the bin directory does not exist, it will be created automatically. The RTOSDemo.axf file is the file generated by Keil after compilation.
Upon successful compilation, we can obtain the RTOSDemo.bin firmware file, which contains all our application code!


Reverse Engineering FreeRTOS
Reverse Analysis Environment:
· IDA 7.0
· binwalk
Here we use IDA to perform reverse analysis on the successfully compiled BIN firmware. First, this BIN firmware is structured as ARM Little-endian.



In the processor type, select ARM little endian, and open processor options. In the screenshot, you can see the settings suitable for my environment. My Cortex-M3 is based on the ARMv7-M architecture, so it is set this way.
Next, when we load IDA, it will ask us to input the base addresses for ROM, RAM, etc. Here we can add them in two ways.
Method One
Since the entire firmware is compiled by ourselves, we can check the ROM, RAM, and other loading address information in Keil.

Here we can see the starting addresses and sizes corresponding to RAM and ROM. We will add the corresponding data to IDA for analysis in the Disassembly memory organization corresponding to ROM and RAM, as follows:

We gradually confirm that IDA loads automatically, and finally obtain the following analysis results

However, since IDA does not automatically parse the BIN firmware, we need to parse it ourselves. First, we set IDA to support ARM Thumb instructions, which can be set using the shortcut key Alt+G to set the instruction analysis format


It can be seen that it has already become CODE16 assembly code. Here we press the C key for automatic analysis, and the analyzed code is as follows:

Here we can see that there are already functions and disassembled code. This method can only help us analyze the firmware we compiled ourselves.
Method Two
Next, let’s look at Method Two, which is often used in reverse engineering.
Now assume that the firmware is firmware we extracted from a device, and we currently do not know any useful information.
Using conventional methods, we use binwalk for a simple scan analysis, and get the following results:

Here we get no information. However, we know this is an RTOS, so we directly use IDA; it’s straightforward! 😄
Here we also need to choose the architecture; common architectures in embedded systems are ARM, MIPS, PowerPC. If we do not know the specific architecture, we can try them all and gradually determine based on the code analysis results. Here we choose the ARM architecture, but we do not know the specific ROM, RAM, and other address information, we can just default it, and IDA loads the following results:

It can be seen that the results obtained are still quite similar to the previous ones, but the previous addresses have changed to start from 00000000. We also set the Thumb instruction format, and then perform disassembly analysis to get the following results:

Here we can see that we have only obtained two functions, so let’s analyze them from the beginning.

Here we see two relatively large segment addresses of 0x20000000 and 0x8000000, so we can guess whether these are the addresses related to ROM and RAM? At this point, we can analyze it again by reloading it, but first, let’s look at the memory layout of the STM32F103 board.

Here we can also roughly see the base addresses of RAM, ROM, etc. So we can use the operations of Method One to analyze the firmware, and successfully obtain the disassembled code.

FreeRTOS consists of tasks, which are written by users. Therefore, we conduct reverse analysis based on the key code of FreeRTOS.
We search for the IDLE task (provided the user has not changed the native code), and we track IDLE through string search.

We follow the string and get the following code

We disassemble the code

Let’s take a look at the source code in Keil

Here we can confirm that the sub_8003F5C() function is the task function of xTaskCreate(). We rename sub_8003F5C() and sub_80047B8() to xTaskCreate and vTaskStartScheduler(), and check the entire function’s call relationship.


From here we can see that there are also two xTaskCreate() task functions. These two task functions are user-defined code. Let’s take a look at the source code situation.


The two addresses correspond to vCheckTask and vLCDTask task handling functions. We track the addresses and get the following content:

It can be seen that no analysis has been performed here. We will manually analyze it because we have already confirmed that this corresponds to the actual function. Select the code section, right-click and choose Analyze selected area for code analysis, and get the following content.


We compare the source code to confirm that this is indeed the task handling function. We set this address as a Function, obtaining the following content:

Automatically generate the function based on the address.

However, the address corresponding to the calling location is incorrect.

We relocate the address code to correspond to the actual task handling function address.

Finally, we obtain the actual task handling function.

This is our vCheckTask() function. We can see the actual task handling function through source code comparison.
If IDLE is processed, then what we need to look for is the code related to xTaskCreate(). Let’s take a look at the code for xTaskCreate().


Through the assembly code comparison, we can see the corresponding relationship of xTaskCreate(). If IDLE is processed, we can guess and analyze according to the function parameter stack rules.
Conclusion
The above is the reverse analysis of FreeRTOS. This mainly uses the Demo that comes with FreeRTOS for reverse analysis, helping to familiarize oneself with RTOS reverse engineering. The reverse engineering of RTOS is somewhat different from traditional Linux firmware, but the analysis logic is no different.
End
Recruitment Advertisement
ChaMd5 Venom is recruiting talented individuals
Newly formed group IOT + Industrial Control + Sample Analysis Long-term recruitment
Contact us at[email protected]
