0

If I have a resource like this:

STRINGTABLE
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
{
100,    "OK"
101,    "Warning"
102,    "Error"
103,    "Name"
104,    "Size"
}

1- How can I place a BP (conditional) to break when the string 102 is accessed (x64. I do not know which function is used to load the string)?

2- How could I detect this code in a disassembler such as Ghidra/IDA?

2 Answers 2

1
  1. you don't ... there's a slim chance to use a hardware breakpoint to trigger when the (mapped) resource string gets accessed, though.
  2. you need to stake out what APIs get used which could be used to read the string(s). The first one to go to here would be LoadString for obvious reasons. But it's possible that your target uses FindResource (or the corresponding *Ex-function), followed by LoadResource, LockResource etc.

So if I were you I'd look at the import table first. Check if either LoadStringA or LoadStringW exists and check all instances. The ID parameter for the resource ID should be pretty obvious.

Failing that I'd look for GetProcAddress and friends and whether that is used to get the function LoadString and call it.

Failing that I'd look for the other functions I mentioned above.

Failing that I'd investigate which internal functions inside ntdll.dll are used to implement resource handling and break on those, then investigate the call stack.

If all of the above fails I'd set a hardware breakpoint on the resource string itself in an attempt to catch the program accessing the string.

NB: in multilingual applications the resource ID would still matter and typically be identical across languages, but there's a chance the string you're after is in another (resource-only) DLL altogether. Such DLLs have no entry point or code and are purely mapped as data. This could be relevant if you come up empty-handed in all but the last approach ... because for the last approach you'll have to set the breakpoint on the right data.

0

1- How can I place a BP (conditional) to break when the string 102 is accessed (x64. I do not know which function is used to load the string)?

First, it is necessary to find the right method used to load the string. The standard one is LoadString but, as @0xC0000022L mentioned, there are other options. Check the imports from the PE file and determine which one can be.

In my case, I found out it was LoadStringW, from user32.dll.

In x86, you will normally place a BP with a condition on some stack value. In x64 this normally works differently (x64 calling convention):

By default, the x64 calling convention passes the first four arguments to a function in registers. The registers used for these arguments depend on the position and type of the argument. Remaining arguments get pushed on the stack in right-to-left order. Integer valued arguments in the leftmost four positions are passed in left-to-right order in RCX, RDX, R8, and R9, respectively...

According to the documentation LoadStringW function:

int LoadStringW(
  HINSTANCE hInstance,
  UINT      uID,           // --> The identifier of the string to be loaded.
  LPWSTR    lpBuffer,
  int       cchBufferMax
);

Therefore, uID will be loaded in EDX. The right breakpoint for x64dbg is:

bp user32:LoadStringW;bpcnd user32:LoadStringW,EDX==66

Note: 102 is 66h


2- How could I detect this code in a disassembler such as Ghidra/IDA?

In Ghidra this is automatically managed. By looking into the Defined Strings you can find the strings in the resources:

                     pu_Error_140312196                              XREF[12]:
FUN_1400... (*) ,FUN_140...
   140312196 05004500...      p_unicode  u"Error"    Rsrc String ID 102

From here it is trivial to go to the references.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.