Creating Ida Sigs
Matt Hurd / April 2024 (375 Words, 3 Minutes)
When reverse engineering in IDA, there’s an incredibly useful feature called Signatures. IDA in particular uses something they call FLIRT, or Fast Library Identification and Recognition Technology. By checking the first 32 bytes of a function and seeing if it matches any known pattern, we’re able to identify whether or not a function is part of a library. IDA comes with a large number of signature files (.sig
) for common libraries and architectures. For our case, we’re working with a niche compiler which won’t have any matches. Thankfully, we can create our own signatures.
The Process
Finding the library
The ADS1.2 Compilers and Libraries PDF can be downloaded here
Combing through the ADS1.2 documentation, we can find information on the library directory structure, as well as the library naming convention:
Based on the compiler flags I’ve identified for Winx Club on GBA, I’m going to move forward with the armlib/c_t__un.l
variant. This means we’re looking at the C core library, with basic C++ runtime support. We’re using Thumb interworking, no floating-point instructions, no software stack checking, non-reentrant functions, and are working with little-endian.
Extracting the library
IDA’s tooling only supports relocatable ELFs (.o
files in this case), not full libraries. As a result, we’ll need to extract all of the .o
files out of these libraries. Lucky these libraries use the standard Unix Archiver file format which can be extracted using the ar
utility.
As an aside, the official GBA SDK includes some .alf
libraries that are for older versions of ADS but still maintain compatibility. At least with the GBA SDK 3.0 that I have, there weren’t any actual function matches. The tooling I wrote to extract signatures from those is not pretty…
After extracting all of the .o
files, we’re now able to start using IDA’s FLAIR tools. By running pelf.exe
on a .o
file, we can generate a PAT file. After generating PAT files for all of our objects and merging the PATs together, we can feed it into the sigmake.exe
command. With this, we’re able to make our .sig
which can be passed to IDA. After applying the sigs to our existing project, we can take a look at our functions and see a lot of success!
Overall, we end up matching 122 functions. This is incredibly useful, as now we know we don’t have to reverse engineer these functions. Instead, we can call them from our assembly and include them directly from the library during linking.
Another benefit of this is that since some of these library functions call functions that are generally user-defined, we can use them to identify some of our decomp functions. For example in _rt_entry (in kernel.o
)
Here we can expect a call to main
. Let’s see what it looks like in our program.
We now know that sub_800B0D8
is actually named main
! Renaming this function will be important for our linker to be able to work properly.