The page you linked states that the ENCODING
directive in the cfg file only applies to 1-byte-per-unit (1bpu) encodings, which this is not. UTF-16 is a 2bpu format.
The ENCODING
directive is important because 1bpu characters are encoded differently depending on your culture. The values in the character table between 32 and 126 are usually the same, matching ASCII, but the low values and extended half (127-255) depend on the which alphabet encoding is being used, which is defined by the current culture. These encodings are defined in ISO 8859, which defines 14 different encodings for different cultures. ISO 8859-1 (Latin-1) is the most widely used, but other notable parts include 8859-5 (Cyrillic), 8859-6 (Arabic), and 8859-8 (Hebrew).
This then gets a little more complicated, because each implementation of these character sets (often referred to as codepages) is a little different. While ISO 8859-1 "Latin-1" is commonly considered to be the defining standard for Latin languages, you're significantly more likely to see Windows-1252 in practice, which is backward-compatible with ISO 8859-1 but includes many extended characters and defines encodings for control codes like \r
and \n
.
As you can imagine, this is effectively impossible to guess at the time of analysis. It's also tricky because UTF-8 is a variable length multibyte encoding that uses 1bpu a lot of the time for basic ASCII-range characters. The word cafe
encodes to the same bytes in ASCII, ISO 8859-1, Windows-1252, and UTF-8. But add an accent on the e, to get café
, and the encodings vary, with plain ASCII having no codepoint for é
, ISO 8859-1 and Windows-1252 both encoding it as E9
, and UTF-8 encoding it as C3A9
. If you try to do this in reverse, ISO 8859-1 and Windows-1252 will turn C3A9
into é
, which is completely valid but obviously not what was intended.
When you load a binary, IDA attempts to guess which 1bpu encoding was used based on the OS's current language settings. It uses that detected encoding (e.g. Windows-1252) in order to decode any 1bpu string literal bytes that it finds, into readable characters. If it can't guess, it defaults to UTF-8.
If the detected encoding isn't UTF-8, IDA then picks a culture based on the character encoding it picked. Each culture is defined in a .clt
file and defines a number of common characters that exist outside of the common (ASCII-like) range for that particular culture. This is then used when detecting if a sequence of bytes might be a string literal. If the culture is incorrectly detected, IDA will still be able to identify ASCII strings, but strings with extended characters (e.g. café
) might just show up as hexadecimal.
In short: for 1bpu strings, IDA detects the encoding in order to be able to turn bytes into readable strings, and (unless it's UTF-8) it uses a culture definition to detect string literals that contain extended codepoints.
The reason that UTF-8 is unaffected by these issues is that UTF-8 is just UTF-8 - the codepoints are the same everywhere regardless of the current culture or language.
IDA offers two config directives that can affect this process. The first is ENCODING
, which overrides that first step and provides a specific character encoding to be used for decoding 1bpu characters. The second is CULTURE
, which tells IDA which .clt
file to use in order to detect which literals might be strings in the program.
Your situation is entirely unaffected by this, so setting ENCODING
or CULTURE
won't help you. UTF-16 is a 2bpu encoding that, like UTF-8, does not have different encodings depending on culture.
Unfortunately, I'm unclear as to why you're having that specific problem. The first thing to check is that you haven't selected the "character terminated" option in the string literal style dialog, as those individual instruction operands are not terminated strings. The only other thing I would suggest is attempting to interpret the strings as big-endian (UTF16-BE) in case IDA is attempting to convert the byte order incorrectly.
r
while having cursor at hex value?r
trick should work, it's essentially the way you can change the "base" of a value and also make it appear as a character. I think you can define somewhere in the settings which string types you expect, perhaps this affects how you can convert to characters as well?!