PDA

View Full Version : Code Injection Errors


mark_E
February 8th, 2003, 13:52
Why do I get code injection errors debugging certain applications in NT4?

blabberer
February 9th, 2003, 03:04
yep i too have seen this message box pop up some times (mostly when it encounters a breakpoint where it is doing some thing with memory createfilemapping etc
Text strings referenced in OLLYDBG:.text, item 1420
Address=00430A6A
Disassembly=PUSH OLLYDBG.004A7113
Text string=ASCII 004A7113 In order to perform action that is not supported by OS, OllyDbg
004A7153 has injected short piece of code into the debugged application,
004A7193 but received no response within 5 seconds. Do you want to wait f
004A71D3 or another 5 seconds? (If you answer No, the consistency and sta
004A7213 bility of program is not guaranteed and you should restart it as
004A7253 soon as possible).

you answer yes and it pops one more time ( i have made it popup more than ten times and at last had to answer no )

well when you answer no it pops up a msgbox
saying
004A7293 Debugged program may get unstable, pl
004A72D3 ease reload it as soon as possible.

well dont know what it is

focht
February 9th, 2003, 04:57
Greets,

well there exist different hooking/code injection techniques..
The most common are:

- Registry AppInit_DLLs
- System-wide Hooks (SetWindowsHookEx)
- Injection DLL using CreateRemoteThread()

For Ollydbg case i assume its another approach (quick check he isnt using DLL injection in his _Injectcode export).

Hes writing small chuncks of code into enemy address space but with the exception that all code sections are guarded with INT3's.

This has the effect of automagically synchronizing the entry and exit points of the injection code with the debuggers main event loop.
Normally code injections have to use some "signal" mechanism like mutexes and shared memory to communicate from the injected proxy code with the injector process.

In this case the "Breakpoints" have the effect of causing DEBUG_EVENTs in the debuggers event main loop to appear. Now he can modify opcodes or transfer data, because all the debuggees threads are suspended. When ollydbg resumes the thread his "helper" code is executed.

Without looking deeper in the latter i assume that for some (unknown) reason the thread that the injected code belongs to got suspended due to some OS waitable objects. Then ollydbg main debugger loop detects this "timeout" (5 sec) and the message pops up.

Regards,

Anastasius Focht.

blabberer
February 9th, 2003, 05:38
hi focht
it seems you have got a deep understanding of olly and its procs and it seems that oleh has corrected (he says so ive not tried) the alt+f2 link problem in 1.09

any way ill give you a piece of action where i encountered the above problem most (this app is a piece of garbage remover from code )

its simple it getmodulehandles then creates openfilename struct then getopenfilenames cmp eax,1 you break point at that cmp eax,1 and this msgbox pops up

the code uptill the cmp eax is as follows

PUSH 0 ; /pModule = NULL
CALL <JMP.&KERNEL32.GetModuleHandleA> ; &#92;GetModuleHandleA
MOV DWORD PTR DS:[403558], EAX
MOV DWORD PTR DS:[403000], 4C
MOV DWORD PTR DS:[40300C], clean.00403385 ; ASCII "Executable Files"
MOV DWORD PTR DS:[40301C], clean.0040339D ; ASCII "C:&#92;.EXE"
MOV DWORD PTR DS:[403020], 200
MOV DWORD PTR DS:[403034], 281804 ; UNICODE "hor"
MOV DWORD PTR DS:[403030], clean.004034A1 ; ASCII "Choose to open"
PUSH clean.00403000 /pOpenFileName = clean.00403000
CALL <JMP.&comdlg32.GetOpenFileNameA> ; &#92;GetOpenFileNameA
CMP EAX, 1 <----- you break point here and the msgbox pops up

well you try to restart it pops up another message box saying

read the text

ollydbg requested termination of the debugged process but recieved no confirmation within 5 seconds WANNA WAIT( if ans == no ,stability not guarenteed
you may want to restart which is exactly what i was doing anyway

bye and greets focht

mark_E
February 9th, 2003, 14:38
Hi oh me anon,
Hi focht,

Well, what can I say! You lost me a bit there.

However, in saying that, ollydbg seems a bit erratic in when it decides to do it. With only 'Break on Winmain' option set, and no other breakpoints, it sometimes generates the code injection error on entry and sometimes doesn't. I would have thought it should be a consistent 'problem.'

When it doesn't generate the error here, it will later, when resizing the window with BP set on'DefWindowsProc' but none of the multiple previous calls to this.

mark_E

P.S. Don't have the exact details with me at the mo' so please excuse me if my terminology isn't quite correct. I'm sure you can guess at my meaning if incorrect.

focht
February 9th, 2003, 15:10
Greets again,

it seems that both of you (oh me anon, mark_e) share something - there are gui threads in your apps.
I can only guess that the message pump (which feeds default window proc) of the debuggees main gui thread doesnt run at the time ollydbg detects the timeout. This may be due to halt on breakpoint in the thread (suspended) or message deadlock.

In the latter of oh me anon:

"GetOpenFileName" calls shell browser helper objects which in turn create internal threads (timeout worker thread + rpc + additional gui thread). Maybe the main gui thread (which called GetOpenFileName) is waiting for messages from additional gui workers. If one or more of the gui threads get suspended in synchronous message call there may be a message deadlock.

I can look into the matter if the author of ollydbg publishes details of the small code pieces that get injected (and which thread context are they executed).

Regards,

Anastasius Focht

mark_E
February 9th, 2003, 21:02
You are certainly barking up the right tree there!

The 'DefWindowsProc' problem occurs when a Kernel32 thread is created (Error_Sucess = 0)

The code injection problem on start up hasn't occured yet using 1.09

mark_E

blabberer
December 13th, 2003, 08:47
well its an old thread and its same old problem
i have this same "in order" message popping up in one app i am tracing

it pops up if and only if i use break point any where in the app
after the proggy creates a thread

0063FB74 004015F8 /CALL to CreateThread from blah.004015F3
0063FB78 00000000 |pSecurity = NULL
0063FB7C 00000000 |StackSize = 0
0063FB80 00401774 |ThreadFunction = blah.00401774
0063FB84 0000094C |pThreadParm = 0000094C
0063FB88 00000020 |CreationFlags = NORMAL_PRIORITY_CLASS
0063FB8C 004052A4 &#92;pThreadId = blah.004052A4

i used w98 tracing this app

i break point any where in the thread function this message pops up
any ideas any one any ideas
focht are you there what am i supposed to do to eliminate this popup

focht
December 23rd, 2003, 13:34
Greetings!

Well the same applies as i said (ages ago).
The injected code might be "talking back" to the debugger.
If the code doesnt answer in a given time interval (5 secs), the debugger assumes something goes wrong.

I can only speculate what happens ... maybe the author of the debugger can shed any light on this:

- what kind of code is injected (some kind of SetWindowsHook(ex)/SetWindowLong equivalent?)
- under which thread context is the code executed (which of the debuggee's threads)
- state of all other debuggee threads during injection/communication stuff (suspended?)

If all of the debuggee's other threads are suspended, there might be a synchronization/message problem on the (single) running (message processing) thread if it depends on another thread to signal some sync object or process a message (which cant be fullfilled because the dependant thread is suspended -> deadlock/timeout).

Regards,

A. Focht

blabberer
December 24th, 2003, 10:13
well the same app when traced on w2k does NOT produce that "in order" warning
and neither hangs ollydbg and it breaks on the thread function
when it gets an input for WaitForSingleObject from SetEvent

00401B56 > &#92;FF35 C4524000 PUSH DWORD PTR [4052C4] ; /hEvent = NULL
00401B5C . E8 970F0000 CALL 00402AF8 ; &#92;SetEvent

some kind of lockout

focht
December 26th, 2003, 16:15
Hello again,

>well the same app when traced on w2k does NOT produce that "in order" warning
Maybe ollydbg doesnt need to inject any helper code on NT-based OS (win9X = inject code to work around some missing functionality)?

Maybe you can produce/extract a _tiny_ example app (with C source code) where the "hangup" effect can be clearly shown on win9X based OSes.

Regards,

A. Focht

blabberer
January 26th, 2004, 08:26
oops i got this in w2k too this time in one app so thought ill debug olly on olly with the proggie that causes this problem as a debuggee

well the _injectcode seems to write to the dos header address of the proc
address for writeprocmem is 400000

and it writes these instruction it seems

0012CAE0 0045DECE /CALL to WriteProcessMemory from blingo.0045DEC9 <---blingo is ollydbg i renamed it as i cuoldnt have two ollys in one dir lame maybe tell me if it can create probs (
0012CAE4 000000C0 |hProcess = 000000C0 (window)
0012CAE8 00400000 |Address = 400000
0012CAEC 00491778 |Buffer = blingo.00491778
0012CAF0 00000028 |BytesToWrite = 28 (40.)
0012CAF4 00000000 &#92;pBytesWritten = NULL




00491778 CC INT3
00491779 0F2906 MOVAPS DQWORD PTR DS:[ESI], XMM0
0049177C 0F294E 10 MOVAPS DQWORD PTR DS:[ESI+10], XMM1
00491780 0F2956 20 MOVAPS DQWORD PTR DS:[ESI+20], XMM2
00491784 0F295E 30 MOVAPS DQWORD PTR DS:[ESI+30], XMM3
00491788 0F2966 40 MOVAPS DQWORD PTR DS:[ESI+40], XMM4
0049178C 0F296E 50 MOVAPS DQWORD PTR DS:[ESI+50], XMM5
00491790 0F2976 60 MOVAPS DQWORD PTR DS:[ESI+60], XMM6
00491794 0F297E 70 MOVAPS DQWORD PTR DS:[ESI+70], XMM7
00491798 0FAE9E 800000>STMXCSR DWORD PTR DS:[ESI+80]
0049179F CC INT3
004917A0 2800 SUB BYTE PTR DS:[EAX], AL

what the hell it is writing it seems i gotta google for xmm instructions stmxcsr ???

i post here just so that i dont loos this info

p.s
focht how can i contact you

blabberer
January 28th, 2004, 04:54

and here is this infinite loop that goes on and on
msdn says postthreadmsg will fail if there is no msg queue
is this is the problem how can i find it if my debuggee has the msg que or not

0043250A /PUSH 64 ; /Timeout = 100. ms
0043250C |LEA EDX, DWORD PTR SS:[EBP-1B64] ; |
00432512 |PUSH EDX ; |pDebugEvent = FFFFFFFF
00432513 |CALL <JMP.&KERNEL32.WaitForDebugEvent> ; &#92;WaitForDebugEvent -------->this always returns ERROR_SEM_TIMEOUT (00000079)
00432518 |MOV EBX, EAX
0043251A |TEST EBX, EBX
0043251C |JNZ SHORT blingo.00432558
0043251E |PUSH 0 ; /lParam = 0
00432520 |PUSH 0 ; |wParam = 0
00432522 |PUSH 0 ; |Message = WM_NULL
00432524 |MOV EAX, DWORD PTR SS:[EBP+8] ; |
00432527 |PUSH EAX ; |ThreadId = 0
00432528 |CALL <JMP.&USER32.PostThreadMessageA> ; &#92;PostThreadMessageA --------> this always fails with this ERROR_INVALID_THREAD_ID (000005A4)If the function fails, the return value is zero. To get extended error information, call GetLastError. GetLastError returns ERROR_INVALID_THREAD_ID if idThread is not a valid thread identifier, or if the thread specified by idThread does not have a message queue.
0043252D |MOV EDX, DWORD PTR DS:[4CC480]
00432533 |PUSH EDX ; /hCursor = FFFFFFFF
00432534 |CALL <JMP.&USER32.SetCursor> ; &#92;SetCursor
00432539 |MOV DWORD PTR SS:[EBP-20], EAX
0043253C |PUSH 1356 ; /Timeout = 4950. ms
00432541 |LEA ECX, DWORD PTR SS:[EBP-1B64] ; |
00432547 |PUSH ECX ; |pDebugEvent = 01010101
00432548 |CALL <JMP.&KERNEL32.WaitForDebugEvent> ; &#92;WaitForDebugEvent----> this again returns ERROR_SEM_TIMEOUT (00000079)
0043254D |MOV EBX, EAX
0043254F |MOV EAX, DWORD PTR SS:[EBP-20]
00432552 |PUSH EAX ; /hCursor = NULL
00432553 |CALL <JMP.&USER32.SetCursor> ; &#92;SetCursor
00432558 |TEST EBX, EBX
0043255A |JNZ SHORT blingo.0043258F
0043255C |PUSH 2024 ; /Style = MB_YESNO|MB_ICONQUESTION|MB_TASKMODAL
00432561 |PUSH blingo.004AE54B ; |Title = "No response from injected code"
00432566 |PUSH blingo.004AE3F7 ; |Text = "In order to perform action that is not supported by OS, OllyDbg has injected short piece of code into the debugged application, but received no response within 5 seconds. Do you want to wait for another 5 seconds? (If you answer No, th"...
0043256B |MOV EDX, DWORD PTR DS:[4CAB2C] ; |
00432571 |PUSH EDX ; |hOwner = FFFFFFFF
00432572 |CALL <JMP.&USER32.MessageBoxA> ; &#92;MessageBoxA
00432577 |MOV EBX, EAX
00432579 |CMP EBX, 6
0043257C |JE SHORT blingo.0043250A

focht
January 28th, 2004, 12:50
Hello again...

<pre>
0043250A /PUSH 64 ; /Timeout = 100. ms
0043250C |LEA EDX, DWORD PTR SS:[EBP-1B64] ; |
00432512 |PUSH EDX ; |pDebugEvent = FFFFFFFF
00432513 |CALL <JMP.&KERNEL32.WaitForDebugEvent> ; &#92;WaitForDebugEvent -------->this always returns ERROR_SEM_TIMEOUT (00000079)
</pre>

....
The function returned FALSE (error).
Because the signalling mechanism didnt work or some race condition (debuggee didnt generate any event within 100 ms)

<pre>
00432527 |PUSH EAX ; |ThreadId = 0
00432528 |CALL <JMP.&USER32.PostThreadMessageA> ; &#92;PostThreadMessageA --------> this always fails with this ERROR_INVALID_THREAD_ID (000005A4)
</pre>

Can be anything

The target thread never existed (wrong tid, wrong thread handle) or terminated before (no more valid).
The target thread indeed may not have a message queue created yet.
The target belongs to a different windowstation or desktop (different locally unique identifier (LUID))

Generally speaking:

Any worker thread can become a gui thread if it calls any XXXMessage() based APIs (SendMessage, PostMessage, PeekMessage, ...)
That is if the target thread calls PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE) it will force the operating system to create the message queue.

The interesting information is missing

* Code snippet which gets injected.

* What target thread is addressed by Postthreadmessage().
Please stop before Postthreadmessage() call, get the thread id of the target thread.
Verify that the target thread exists (thread view).
Try to find out who created the thread: the debuggee itself on normal program flow or by debugger using implicit API calls on injected code.

If you post ollydbg code, please collect it block-by-block, every disassembly block copied immediately _before_ the API function call.
Reason: I'd like to see the 'real' caller parameters - before registers and stack frame gets modified -> wrong "comment hints".

Put bp before each:

CALL OLLYDBG._Writememory
CALL OLLYDBG._Runsinglethread
CALL <JMP.&USER32.PostThreadMessageA>

in _InjectCode.
Run. Break. Copy the snippet with _intact_ and _valid_ parameters to text file.

And tell which ollydbg version you use (hopefully latest) ...

Regards,

A. Focht

blabberer
January 29th, 2004, 09:47
well i am using 1.09b
i have those details in .txt
and it is too big to post here

that is why i asked you how can i contact you in one of the above posts
i used sysinternals process explorer to see if those threads exists

Process: blingo.exe Pid: 956

Type Name Handle Access

Thread Duck.exe(940): 696 0xBC 0x0002005B <--- hex 2b8
Process Duck.exe(940) 0xC0 0x0002047B
Thread Duck.exe(940): 1008 0xEC 0x0002005B <--- hex 3f0

0042C571 |CALL blingo._Injectcode ; &#92;_Injectcode

arguments to this call
0012F790 |Arg1 = 000002B8 <--- see 2b8
0012F794 |Arg2 = 00491768
0012F798 |Arg3 = 0012F7AC
0012F79C |Arg4 = 00000084
0012F7A0 |Arg5 = 00000000
0012F7A4 |Arg6 = 04CA02EC
0012F7A8 &#92;Arg7 = 00000000

here wait for debug event reports int3 (8000003)
so olly again uses injectcode

0042C571 |CALL blingo._Injectcode ; &#92;_Injectcode

0012F790 |Arg1 = 000003F0
0012F794 |Arg2 = 00491768
0012F798 |Arg3 = 0012F7AC
0012F79C |Arg4 = 00000084
0012F7A0 |Arg5 = 00000000
0012F7A4 |Arg6 = 04CA0958
0012F7A8 &#92;Arg7 = 00000000

here wait for debug event fails with error_sem_timeout

so it posts thread message
00432528 |CALL <JMP.&USER32.PostThreadMessageA>; &#92;PostThreadMessageA

0012D924 |ThreadId = 3F0
0012D928 |Message = WM_NULL
0012D92C |wParam = 0
0012D930 &#92;lParam = 0
this fails
ERROR_INVALID_THREAD_ID (000005A4)

so it waits for 5 more seconds and if i click yes it keeps on waiting
or if i say no it hangs

this may seem consistent behaviour but does this mean i cant debug multi threaded exes properly
one thread is waiting for single object in my debuggees(olly) debuggee(duck) iirc

blabberer
January 29th, 2004, 10:27
greets and thanks for taking pains to analyse and reply to my stupid quetions
you greet every time and i havent even in one

regards
there is no edit facility so i had to post one more time

focht
January 29th, 2004, 14:08
Hi,

ok i agree there is much information which would fill this thread up

>focht how can i contact you

Here is how...

Simply create a text file, call it whatever and paste the following code:

<pre>
e 100 EB 10 42 4B 47 4C 50 64 43 49 5C 0A 4A 41 50 29
e 110 2E 00 BE 02 01 89 F7 B3 24 AC 30 D8 AA 3C 24 75
e 120 F8 31 C0 B4 09 BA 02 01 CD 21 B8 4C 00 CD 21
g =100
q
</pre>

Pipe that file to debug.exe

<pre>
debug.exe < thefile
</pre>

Dont worry. No harm ... just reminisce about old DOS times. That was fun

--------

It would be extremly usefull if you can supply a small executable which show this behaviour and some setup instructions (send as .zip archive).

Regards,

A. Focht.

focht
January 29th, 2004, 16:07
Greetings,

i think i can trigger ollydbg's code injection by myself now.
While i was reading another thread "SSE/SSE2" registers i noticed the comment "ollydbg injects code to read the registers due to lack of OS support".
So i turned SSE stuff on and - voila - it injected code.

Here is how ollydbg's code injection technique works (IMHO):

(stuff pretty simplified/shortened)

1. Have a good chunk of target memory. Save it.
In this case it is the PE header itself, starting at base address.
Read sufficient bytes of memory to ollydbg internal save area.

2. Modify page protection.
Because some of the bytes later get executed and writes data, the initial page bits must be adjusted to PAGE_EXECUTE_READWRITE.

3. Suspend main thread. Write the injector code to target area (starting at base address).

code snippet for this case:

00000000 CC INT3
00000001 0F2906 MOVAPS DQWORD PTR DS:[ESI],XMM0
00000004 0F294E 10 MOVAPS DQWORD PTR DS:[ESI+10],XMM1
00000008 0F2956 20 MOVAPS DQWORD PTR DS:[ESI+20],XMM2
0000000C 0F295E 30 MOVAPS DQWORD PTR DS:[ESI+30],XMM3
00000010 0F2966 40 MOVAPS DQWORD PTR DS:[ESI+40],XMM4
00000014 0F296E 50 MOVAPS DQWORD PTR DS:[ESI+50],XMM5
00000018 0F2976 60 MOVAPS DQWORD PTR DS:[ESI+60],XMM6
0000001C 0F297E 70 MOVAPS DQWORD PTR DS:[ESI+70],XMM7
00000020 0FAE9E 80000000 STMXCSR DWORD PTR DS:[ESI+80]
00000027 CC INT3
00000028 0000 ADD BYTE PTR DS:[EAX],AL
0000002A 0000 ADD BYTE PTR DS:[EAX],AL
0000002C 0000 ADD BYTE PTR DS:[EAX],AL
0000002E 0000 ADD BYTE PTR DS:[EAX],AL
.....
"local data area"
...

4. Adjust the target thread's context structure to appropriate values so the injector code gets executed next time, the thread resumes.
This means setting the register values to match injector code (esi offsets).

5. Set the targets thread context and resume the thread.

6. The thread will now run and execute INT3 instruction.
This is on purpose because it helps to synchronize execution with the debugger itself.

7. Ollydbg uses WaitForDebugEvent() to synchronize with the injectors code starting INT3 "ENTER" and ending INT3 "LEAVE".
Both debug events will occur if target thread executes the injector code.
After second event, the debugger knows the injector code has been "completed". The target thread is now suspended state.

8. The Debugger reads the targets process memory, especially the pseudo "data" area, where the injected code wrote the floating point register data (offset+0x30).

9. Time to restore. The debugger writes the old memory chunk back, restoring PE header. The page flags are restored to PAGE_READONLY.

10. The target thread context itself is adjusted to old state before the injection and then resumed.

Thats all so far.

If you encounter the injection errors, please could you bp on ResumeThread() and check the return value (suspend count). It might be possible that the target thread's suspend count prevents it from being scheduled.

Regards,

A. Focht

blabberer
January 29th, 2004, 22:48
greets
yep you are on dot and dos is fun and tr252 is even funnier to use
set source index(si) and destination index(di) to this
FHQBBAVdWMB].GKI

btw you have an accurate description of the inject code process
only thing you havent mentioned is it flushes the instruction cache before it sets the thread context in fact i have the dump of context registers content
before the setthread

k ill let you know

blabberer
February 1st, 2004, 09:18
greets focht,

resume thread happens four times inside the inject
here are the details
======================================================
retn values are 1 to both and they are different hThreads

0045E010 |CALL <JMP.&KERNEL32.ResumeThread> ; &#92;ResumeThread
0012CAF4 000000EC &#92;hThread = 000000EC (window)
return value when single stepped=00000001

0045E010 |CALL <JMP.&KERNEL32.ResumeThread> ; &#92;ResumeThread
0012CAF4 000000BC &#92;hThread = 000000BC (window)
retn value= 00000001
========================================================

==============================================================
hThreads are same here and both times it returns 0

004746A9 ||CALL <JMP.&KERNEL32.ResumeThread> ; &#92;ResumeThread
0012D910 000000EC &#92;hThread = 000000EC (window)
retn value = 00000000

004746A9 ||CALL <JMP.&KERNEL32.ResumeThread> ; &#92;ResumeThread
0012D8EC 000000EC &#92;hThread = 000000EC (window)
retn value = 00000000
======================================================

from here it goes here
0042F3C8 CALL <JMP.&KERNEL32.ContinueDebugEven>; &#92;ContinueDebugEvent

btw did you get the .txts
thanks and regards

focht
February 1st, 2004, 09:58
Hi again,

well i reviewed the part just to notice the loop over ResumeThread().

In this case i think its not related.
We need a way (some application) to simulate the "injection timeout" problem every time not just randomly...

>btw did you get the .txts

Nope. Seems my inbound (server side) spam filter did its job too good
I usually let the server automagically move "spam" marked mail into some dump folder. I never review/download them, they get recycled once a day ...

Maybe you can resend the stuff.
Dont use obvious words like money, p0rn and the like in header/body .. Ok, that was a joke

Regards,

A. Focht

focht
February 1st, 2004, 10:37
Some annotation... skip my previous statement "not related".

I could provoke the injection timeout by debugging in chain of 3 ollydbg instances itself.
Its a lot confusing having all the duplicate stuff (rename the ollydbg instances would be - of course - a way).

It happended when i paused a debugger instance in the middle of the chain.
From what i can see, ollydbg uses _not_ the main thread to run the injected code in this case.

That is _Runsinglethread() is not called on main ollydbg thread but on the mapped debugger thread of the debugged ollydbg instance (confusing ey )

I spyed the thread's call stack with external process monitor just to see it was waiting in WaitForMultiple() call.

And that is the root cause of the problem.
You can't in fact externally force a thread to run via ResumeThread() if it is waiting for some user/kernel synchronization object.
That is ResumeThread() can't change the lock state of any synchronization object to let the thread wake up.

"Restarting" a thread if it was suspended using SuspendThread() or the debuggers event loop works as proposed.

Now the question is how does ollydbg determine which thread to run the injected code on.

Regards,

A. Focht

blabberer
February 1st, 2004, 10:50
i have forwarded that again from my sent mail
subject is as below
Fwd refer olly dbg forum these are the files you wanted to see regarding inject process

body is below
greets focht

i have attached some six .txt in that zip
please read the readmefirst.txt first before reading any other files

hope it helps
if you feel it looks rubbish then mail me back
ill try to send you a cleaner version without those registers cluttering

thanks and regards

and one attachment in .zip which contains 8 nos .txt files

just one minute before posting this

focht
February 1st, 2004, 11:50
Greetings,

ok i have your stuff now

I used both versions of ollydbg (1.09d and 1.10b), they show same behaviour.
The executable you supplied shows the "anomalies" thats for sure.

From what i've seen so far i can say the following:

The problem only appears if the application is multithreaded and at least one thread is suspended due to call to an OS synchronization API, like:

SleepEx
WaitForSingleObjectEx
WaitForMultipleObjectsEx
SignalObjectAndWait
MsgWaitForMultipleObjectsEx

It seems the thread where the injector code is run on differ from time to time.
Example: target has two application created threads

------------------

thread id: 2708 (this is the main gui thread of the application)
It just pumps messages.

Duck.exe+0x13d3
USER32.dll!InternalCallWinProc+0x1b
USER32.dll!UserCallDlgProcCheckWow+0x146
USER32.dll!DefDlgProcWorker+0xa6
USER32.dll!DefDlgProcA+0x21
USER32.dll!InternalCallWinProc+0x1b
USER32.dll!UserCallWinProcCheckWow+0x150
USER32.dll!SendMessageWorker+0x4a3
USER32.dll!SendMessageW+0x7d
USER32.dll!xxxButtonNotifyParent+0x3e
USER32.dll!xxxBNReleaseCapture+0xf5
USER32.dll!ButtonWndProcWorker+0x6ba
USER32.dll!ButtonWndProcA+0x4a
USER32.dll!InternalCallWinProc+0x1b
USER32.dll!UserCallWinProcCheckWow+0x150
USER32.dll!DispatchMessageWorker+0x306
USER32.dll!DispatchMessageW+0xb
USER32.dll!IsDialogMessageW+0x570
USER32.dll!DialogBox2+0x142
USER32.dll!InternalDialogBox+0xce
USER32.dll!DialogBoxIndirectParamAorW+0x35
USER32.dll!DialogBoxParamA+0x4a
Duck.exe+0x1315

------------------

thread id: 2792 (this is a worker thread, waiting for some event to be signaled)

ntdll.dll+0x8090304
ntdll.dll!NtWaitForSingleObject+0xc
kernel32.dll!WaitForSingleObjectEx+0xa8
kernel32.dll!WaitForSingleObject+0xf
Duck.exe+0x17ad
kernel32.dll!BaseThreadStart+0x37

One time, ollydbg did the following, trying to run the injector code:

...
RunSingleThread( 2708)
...

This worked, because the thread itself wasnt in any waitable/alertable state.

Some time later:

...
RunsingleThread( 2792)
...

This causes the infamous "Injection timeout" message.
The reason is clear (i told in my last message).
You can't wake up thread using ResumeThread() if it is in any Waitable/Alertable state. This behaviour is by OS design.

So the question remains ... why does ollydbg try to run the injector code on a thread which is in alertable state while another non-alertable thread is available?

I think that can only answer the author of ollydbg itself...

Of course there is an extremly clever way (first introduced by Jeffrey Richter) to circuumvent this and wake up even threads in alertable state.
The magic is called QueueUserAPC().

Regards,

A. Focht

j_petrucci
February 2nd, 2004, 15:29
Hi Focht!
I'm really astonished about your knowledge about OS internals.. :-) congratulations
Regarding that code-injection behaviour, sure the Jeffrey Richter solution is better.. why don't you tell about it to Olly? it could be nice to suggest him some feature requests before 1.10.. ;-)

*guido*

focht
February 3rd, 2004, 02:38
Greets,

>Hi Focht!
>I'm really astonished about your knowledge about OS internals.. :-) congratulations

Well i code for a living. About 10 years experience with NT based systems kernel/usermode

>Regarding that code-injection behaviour, sure the Jeffrey Richter solution is better..
>why don't you tell about it to Olly?
>it could be nice to suggest him some feature requests before 1.10.. ;-)

The reasons why i kept this discussion public was:

- share knowledge
- develop possible solutions before contacting the autor
- the author might be reading this too...

After some thinking about this problem i can offer two possible solutions - both with drawbacks.

1)

Ollydbg detects the "injection timeout".
It is very likely that the target thread is in alertable state

The alertable state itself can't be detected easily without additional work:

- QueueUserAPC (needs additional target thread to run on)
- a helper kernel driver which reads the appropriate kernel ETHREAD structure flags
- walk the stack frame of the target thread, checking for one of the WaitXXX functions

If the timeout occurs ollydbg should abort the attempt to run the injector code on this "alertable" thread.
Restore stuff/cleanup (Memory, context).

Select the next thread in debuggee's process space.
Try the run the injector stuff again until success or no more threads available.

Drawback: If all the debuggee's threads are in alertable state this method fails.

2)

QueueUserAPC() is a possible solution but it needs a thread to be called on.
If all threads in target process are in alertable state, an additional thread must be created.
This can be done using:

- CreateRemoteThread() - drawback: only supported on NT based systems
- global hook (loading custom dll which creates the helper thread)

If a helper thread needs to be created to execute QueueUserAPC() - why to use QueueUserAPC() at all when the injector code itself can be run in the context of the helper thread

So QueueUserAPC() can be dropped for this case.
(It has some nasty side effects if the target application doesnt handle waitable function results properly).

So the solution is to create the additional helper thread in target process just for the task of running injector code or waiting for debuggers requests.

Careful: Dont use events to implement passive wait - the thread must _not_ enter alertable state!

One solution is to fake a gui worker thread.
Just create a message queue and pump messages with to wait for event using PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE) API.

Take care if the application main thread terminates.
The helper thread must be terminated then by debugger too.
The debugger could communicate with the helper thread using PostThreadMessage( custom message) to exit it.

Any additional ideas are welcome.

Regards,

A. Focht

blabberer
February 3rd, 2004, 09:38
Quote:

It seems the thread where the injector code is run on differ from time to time.
Example: target has two application created threads


yep and one thread is waiting for single object so its stall and stall only
for the time being it seems

so do you have any ideas how olly chooses it or where
i can try tracing it out
(leaving the scenerio where all threads are in waitable state
where it is going to fail for sure we can atleast find
why it changes behaviour even where there is one
thread not in alertable state )
does my query sound stupid if not tell me some work
to do with the combo i have so that i can trace it and post it here

and this question has been bugging me for more than one year
i hate to see this happen and let olly hang coz it detected a time out and
i have to pull the lever

focht
February 3rd, 2004, 10:52
Hello again,

>so do you have any ideas how olly chooses it or where i can try tracing it out

Nope ... and to be honest: i would not invest more time in it
The task to identify the cause was challenging.
I like tasks that demand knowledge of internal workings or require to learn something new.
I refreshed some my knowledge on the usermode APCs.

But now its no more than finding an explanation for the "strange thread selection" behaviour.
It can be a time consuming task which is IMHO not worth it.
The author of ollydbg could find/explain it much faster and might fix it using some of my suggestions.

Just send the author a message with a link to this message board thread (pointing at the last posts) asking him for an explanation or a time line for a fix.

Regards,

A. Focht

blabberer
February 4th, 2004, 03:00
greets,
and first of all thank you very much for taking time to analyze and suggest solutions and thanks very much for sharing your knowledge where i also learned many things that are tangible as well as intangible and as you rightly said it maybe not a challenge any more just asked you what i thought could be hair splitting approch

ok ill post the author a letter (hehe with the filled registration form he sent with the package asking me to register from version 1.06)

ps:
for all who reads this thread any additional info or ideas are welcome

regards
oh me anon

blabberer
February 6th, 2004, 10:07
k posted a letter to author with a link to this topic lets wait and see ill post here if he replies or if he does some thing about it
thanks and regards
oh me anon

blabberer
February 13th, 2004, 01:33
i got a reply from oleh but there isnt an iota of trace or any comment regarding the link in that reply i think it was auto generated reply
;( dont know
anyway ill wait for some more time

Quoting Ollydbg@t-online.de:

thank you very much for the registration. I will keep you informed about new OllyDbg releases. Do not hesitate to ask questions, report all found bugs and propose improvements, even small. Without your feedback, I will be unable to improve my (hopefully useful) product.
Sincerely,
Oleh Yuschuk

blabberer
February 23rd, 2004, 10:29
well i told ill post if olly replies some thing on this problem
here is his reply

and yes he will do some thing about it in v2 sincerly

so topic closed for now till v2 is released

>thanks very much for this reply is this reply auto generated
> i dont see even a hint of whether you have read the problem i posted along
> with that registration letter and whether you have visited the link i
posted
> in ollydbg forum and what are your comments on that problems

There is no way to generate answers automatically. Some of registrations are
even in .BMP format (printed and scanned). The problem is with my free time
(or, rather, with the lack of it). Yes, I have seen your deep and thorough
analysis on the forum and will try to do something. Still, the best solution
would be to avoid injection by all means. Maybe I'll implement it differently in

v2.0 (DLL injection + extra thread?)

Sincerely,

Olly

Bob
December 3rd, 2004, 02:47
I'm getting this "lack of OS support" injection error in a lot of C programs, a few programs I cannot debug at all due to crash, keys and buttons on olly do nothing.. Then when I exit Olly, I get the "waiting for thread" error, which yes just repeats the question

Is there some option (I have looked that I've missed to turn the cause of this annoying error off? I'd rather not see some register than crash all the time.

Cheers ~BoB~

in frustration
December 3rd, 2004, 21:16
Very confused guys...Please help!!!!!....Ok so im trying to make a code cave and i copy an adress

" 0046AFB9 8B86 AC000000 MOV EAX,DWORD PTR DS:[ESI+AC] "

but when i try to assemble " MOV EAX,DWORD PTR DS:[ESI+AC] " to create an exact copy of it but in the code cave it gives me the error "Unknown identifier".....im a newb at this so can you please help

blabberer
December 4th, 2004, 02:59
bob

are you having this problem in mundane programs too or it happens in some apps which have one of the Wait Function and all the threads are paused

if it is first then you can turn off
1) options --->debugging options--->security--->allow code injection to get the address of winproc
2)options -->debugging options ---> registers--->automatical fpu/mmx/3d now registers and decode sse registers

both these use code injection to perform the task

but if it latter (hanging in one of the wait functions then i would suggest you to read the whole thread (i am not aware of any solutions as yet and oleh replied that he would look into the matter in v 2.0)


in frustration
" 0046AFB9 8B86 AC000000 MOV EAX,DWORD PTR DS:[ESI+AC] "

this topic is no way connected with the problem you are facing please post in appropriate threads to avoid confusion and or create a new topic
any way the answer to your question is very simple any hex numbers that you refer should be implicitly defined as hex (what will any app yhink if it see AC
is it air conditioner ?? or all cracked ?? or ahhh crap !!!?? or absolutely crude ??? or just string AC or is it 0xAC
if you add a 0 in front of AC ollydbg will happily accept it and will assemble it properly as
00401417 8B86 AC000000 MOV EAX, DWORD PTR DS:[ESI+AC]
have fun

Bob
December 14th, 2004, 07:27
Oh me Anon,
Thanks for the tips, I did read the whole thread before, but I'm getting this 'error' all the time in any kind of app except Asm (so far). I tried turning off the options, but still I get the 'injected small piece of code' blah blah
Following from my original post, I get this in not just C# programs as I originally thought, I've since got this error (increasingly frequently) in C++, Delphi and VB apps.

I'm not entirely convinced that this isn't to do with plugins, I'm going to remove them all, one by one, and see if that changes anything, failing that I'll downgrade olly versions, failing that? Return to Softice until V2 maybe..

This has really become a problem, but it's only in last 2 months. I didn't ever have this error before I downloaded plugins.


~BoB~