Home > Software design >  Program with while loop causes stack overflow, but only in x86 and only when injected into another p
Program with while loop causes stack overflow, but only in x86 and only when injected into another p

Time:10-12

I have an unfortunately convoluted problem that I am hopeful someone might be able to help me with.

I have written a reasonably large program that I have converted into position independent code (see here for reference: stackoverflow

Examining the contents of the stack at crash time shows this:

stack contents

Looking at the contents of IntermedBuf (which is one of the arguments passed to the strstr call) I can see that the program IS copying data from IOBuf to IntermedBuf and removing spaces as intended, however the program crashes after copying ~80k.

IOBuf (raw data):

IOBuf

IntermedBuf(After removing spaces)

IntermedBuf

My preliminary understanding of what is happening here is that strstr (and potentially memcpy) are pushing data to the stack with each call, and given the length of the loop (lengthIOBuf is ~325K, spaces occur randomly every 2-11 characters throught) the stack is overflowing before the while loop finishes and the stack unwinds. However this doesn't explain why this succeeds in x64 in both cases, and in x86 when the PIC program is running in a user-made program as opposed to injected into a legitimate process.

I have ran the x86 PIC program in the local injector, where it succeeds, and also attached Windbg to it in order to examine what is happening differently there. The stack similarly contains the same sort of pattern of characters as seen in the above screenshot, however later in the loop (because again the program succeeds), the stack appears to... jump? I examined the contents of the stack early into the while loop (having set bp on strstr) and see that it contains much the same pattern seen in the stack in the remote injector session:

localStack

I also added another MessageBox this time inside the while loop, set to pop when j > lenIOBuf - 500 in order to catch the program as it neared completion of the while loop.

            char* locSpace;
            while (j < lenIOBuf)
            {
                if (j > lenIOBuf - 500)
                {
                    ((MEMSET)Apis.memsetFunc)(tools, 0, 100 * sizeof(char));
                    ((SPRINTF)Apis.sprintfFunc)(tools, StringVars->poi, IntermedBuf);
                    ((MESSAGEBOXA)Apis.MessageBoxAFunc)(NULL, tools, NULL, NULL);
                }
                locSpace = ((STRSTR)Apis.strstrFunc)(IOBuf   j, StringVars->space);
                if (locSpace == 0)
                    locSpace = IOBuf   lenIOBuf;

                strLen = locSpace - IOBuf - j;

                ((MEMCPY)Apis.memcpyFunc)(IntermedBuf   i, IOBuf   j, strLen);
                i  = strLen, j  = strLen   1;
            }

When this MessageBox popped, I paused execution and found that ESP was now 649fd80; previously it was around 13beb24? bpMessageBox

So it appears that the stack relocated, or the local injector added more memory to the stack or something (I am embarassingly naive about this stuff). Looking at the "original" stack location at this stage in execution shows that the data there previously is still there at this point when the loop is near completion:

lateStack

So bottom line, this code which runs successfully by all accounts in x64 local/remote and x86 local is crashing when ran in another process in x86. It appears that in the local injector case the stack fills in a similar fashion as in the remote injector where it crashes, however the local injector is relocating the stack or adding more stack space or something which isn't happening in the remote injector. Does anyone have any ideas why, or more importantly, how I could alter the code to achieve the goal of removing spaces from a large, arbitrary buffer in a different way where I might not encounter the overflow that I am currently?

Thanks for any help

CodePudding user response:

typedef void*(WINAPI* MEMCPY)(void * destination, const void * source, size_t num); 

typedef char*(WINAPI* STRSTR)(const char *haystack, const char *needle);

is wrong declarations. both this api used __cdecl calling convention - this mean that caller must up stack ( add esp,4*param_count) after call. but because you declare it as __stdcall (== WINAPI) compiler not generate add esp,4*param_count instruction. so you have unbalanced push for parameters.

you need use

typedef void *  (__cdecl * MEMCPY)(void * _Dst, const void * _Src, _In_ size_t _MaxCount);
typedef char* (__cdecl* STRSTR)(_In_z_ char* const _String, _In_z_ char const* const _SubString);

and so on..

  • Related