I have a Windows GUI x86 executable and I have identified, in the .rsrc section, where the error string I want to trace is. Let's assume it is in id=83Ah.

I have set a bpx user32:LoadStringA and then a break condition breakif([esp+8] == 83A).

The BP fires correctly, when required. My problem now is how to identify which user code took the decision to load the string. For example, imagine this situation:

if(....) {
   displayError()  <-- This will call LoadString at some point 

I am able to break on the LoadString, but when I RET, I get to a function that is used in many other code sections (such as AfxMessageBox). And I RET again and it is also a function that is used by many other code sections (like a Windows dispatcher)... and so on and so forth until I get lost without knowing where the user code that triggered the message is. I avoid system DLLs, but the portions of user code I land in look very generic and shared by other GUI components.

This is for example the Call Stack of my program:

Address  To       From     Size     Comment            Party 
0019EF84 0041FA5E 76AC8BA0 58       user32.76AC8BA0    User
0019EFDC 004037C1 0041FA5E 24       s3.sub_41FA42+1C   User
0019F000 0041EE3D 004037C1 30       s3.sub_4037B0+11   User
0019F030 0041DCE0 0041EE3D 24       s3.0041EE3D        User
0019F054 00421883 0041DCE0 50       s3.sub_41DCC5+1B   User
0019F0A4 004210A3 00421883 A8       s3.sub_421820+63   User
0019F14C 00421050 004210A3 24       s3.sub_421073+30   User
0019F170 0041FDB9 00421050 6C       s3.sub_42102A+26   User
0019F1DC 004200BE 0041FDB9 1C       s3.sub_41FD36+83   User
0019F1F8 76AE5CAB 004200BE 2C       s3.sub_4200A4+1A   System
0019F224 76AD67BC 76AE5CAB E4       user32.76AE5CAB    System
0019F308 76AD5F6D 76AD67BC 64       user32.76AD67BC    System
0019F36C 76AD5C33 76AD5F6D 34       user32.76AD5F6D    System
0019F3A0 76B008E2 76AD5C33 24       user32.76AD5C33    System
0019F3C4 76B005DF 76B008E2 28       user32.76B008E2    System
0019F3EC 76AFFAE8 76B005DF A0       user32.76B005DF    System
0019F48C 76AFEF92 76AFFAE8 2C       user32.76AFFAE8    System
0019F4B8 76AE5CAB 76AFEF92 2C       user32.76AFEF92    System
0019F4E4 76AD67BC 76AE5CAB E4       user32.76AE5CAB    System
0019F5C8 76AC6C22 76AD67BC 38       user32.76AD67BC    System
0019F600 004209FA 76AC6C22 20       user32.76AC6C22    User
0019F620 00421065 004209FA 20       s3.sub_4209B6+44   User
0019F640 0041FDB9 00421065 6C       s3.sub_42102A+3B   User
0019F6AC 004200BE 0041FDB9 1C       s3.sub_41FD36+83   User
0019F6C8 76AE5CAB 004200BE 2C       s3.sub_4200A4+1A   System
0019F6F4 76AD67BC 76AE5CAB E4       user32.76AE5CAB    System
0019F7D8 76AD58FB 76AD67BC 74       user32.76AD67BC    System
0019F84C 76AD97B1 76AD58FB 30       user32.76AD58FB    System
0019F87C 76ACEB4E 76AD97B1 2C       user32.76AD97B1    System
0019F8A8 00422C49 76ACEB4E 7C       user32.76ACEB4E    User
0019F924 0041E194 00422C49 FFE606E0 s3.sub_422C1F+2A   User
00000004 00000000 0041E194          s3.sub_41E0DC+B8   User

I initially tried to investigate some close User sections near a System section... but they all seem like shared code that is used when other GUI elements in the application have to be displayed.

So what is the best approach to determine where the if(....) comparison is?

Note: I am using x64dbg, but the process should not change wrt other debuggers

  • If the original developer wanted to separate the GUI message from the actual code that triggered the message there are various ways to do so. One way would be to use custom window messages such as WM_USER message type. In such a case the stack trace would just lead to to the event handling code. Check the process for events e.g. using Spy++ (spyxx.exe). – Robert Mar 28 at 16:12
  • So you mean my stack is not enough to find out (I would ned to capture WM_USER) and that with a debugger it is too complicated to find the trigger (I would need Spy++)? – user1156544 Mar 28 at 18:14
  • As I said using messages is just one potential way. I don't know if it is true in your case. Thee question is more how many effort the developer made to hide what you are searching. In the end there is also the possibility that you found the wrong call or misinterpreted something. – Robert Mar 28 at 20:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.