Thread: Segmentation fault!?!?!?

  1. #1
    Registered User
    Join Date
    Jun 2008
    Posts
    161

    Segmentation fault!?!?!?

    I don't get it. My whole program compiles fine, but it throws an Access Violation segmentation fault when it tries to access this function. The function is declared properly and so are the arguments, but it it can't even be stepped into with Dev-C++ debugger before throwing that error. I try to look at "Next Step" in the debugger and I get that error. It's not making any sense.

    (u32 is just my designation for Unsigned Int)

    Code:
    DumpRAM(sdFileName, &NewRAM);
    
    u32 DumpRAM(char* DumpName, u8 **ramdata)
    {
        u32 filesize = 0;
        u32 chunksize = 0x1000000;
        DWORD bytesread;
        u8 buffer[0x1000000];
        u32 RamStart = Settings.Hook.rOffset;
        if (!VerifyHook()) {
            MessageBox(NULL,"ProcessID no longer valid. Unable to read memory (DumpRAM, 1)", "Error", MB_OK);
            return 0;
        }
        if (Settings.Hook.sType == RAM_POINTER) {
            if (!ReadProcessMemory(HookedProcess.hProcess, (void*)Settings.Hook.rOffset, (void*)RamStart, chunksize, &bytesread)) {
                return 0;
            }
    
        }
        //testing
        sprintf(ErrTxt, "%u", RamStart);
        MessageBox(NULL,ErrTxt,"Error",0);
        return 0;
        //testing
        if (*ramdata) { free(*ramdata); *ramdata = 0; }
        do {
            if ((Settings.Hook.AutoRam == BST_UNCHECKED) && (Settings.Hook.MaxRamSize)) {
                filesize = Settings.Hook.MaxRamSize;
            } else { filesize += chunksize; }
            if (ReadProcessMemory(HookedProcess.hProcess, (void*)RamStart, (void *)buffer, chunksize, &bytesread)) {
            }
            if (!(*ramdata = (unsigned char*)realloc(*ramdata, filesize))) {
                MessageBox(NULL, "Unable to allocate buffer memory (DumpRAM,1).", "Error", MB_OK);
                return 0;
            }
        } while((Settings.Hook.AutoRam == BST_CHECKED) && (chunksize > 0));
        return 0;
    }
    
    int VerifyHook()
    {
        char szProcessName[MAX_PATH];
        GetModuleBaseName( HookedProcess.hProcess, NULL, szProcessName, MAX_PATH );
        if (StringCompareCI(szProcessName, Settings.Hook.FileName)) { return 0; }
        return 1; //returns 1 if hook is still good
    }

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    You can't use
    Code:
    u8 buffer[0x1000000];
    as a local variable, it takes up 16MB, and that's about 8 times more than the normal stack-size given to a Windows applicaton. Use a global, local static or use malloc.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    I think you would need to do "step into" to actually get into the function with the debugger.

    Will your system allow you to have a 16M buffer?

    I suppose if ramdata is itself NULL then if (*ramdata) will die a horrible death.

    Those are the things I can think of right off the top of my head.

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by tabstop View Post
    I think you would need to do "step into" to actually get into the function with the debugger.

    Will your system allow you to have a 16M buffer?

    I suppose if ramdata is itself NULL then if (*ramdata) will die a horrible death.

    Those are the things I can think of right off the top of my head.
    I think it crashes on the first step into when it tries to step over the prologue of the function, which allocates the 16MB of stack-space, which as I pointed out above is causing a problem.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by matsp View Post
    I think it crashes on the first step into when it tries to step over the prologue of the function, which allocates the 16MB of stack-space, which as I pointed out above is causing a problem.

    --
    Mats
    That's possible. I can never remember whether "next step" does step over or step into or something else.

  6. #6
    Registered User
    Join Date
    Jun 2008
    Posts
    161
    You gotta be kidding me. Compilers can't be bothered to warn about excessive local variables? How the hell is anyone supposed to know that?

    As far as ramdata, I've always done it that way. If there's a better way, I'm all ears.

  7. #7
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    It's difficult for compilers to warn about any run-time error. (Stack size is I believe set in the linker, and can probably be changed if you are wise in the ways of the linker.)

    As to ramdata, if you know that the function will never be called with NULL as the second parameter, then there's no problem. If it's possible, you would just need to add a check. Given what the function is probably doing, passing 0 as a second parameter doesn't appear to be at all sensible, so you may not need to have to worry about it.

    Edit: by "just need to add a check" I mean in order to avoid dereferencing a NULL pointer. Making the semantics work with a NULL pointer is something else altogether.

  8. #8
    Registered User
    Join Date
    Jun 2008
    Posts
    161
    thanks. Situations like this make me want to rip my hair out quick. I have a serious lack of patience, especially when something looks like it should work but refuses to.

  9. #9
    Registered User
    Join Date
    Jun 2008
    Posts
    161
    Ok, new problem.

    Ok, I've got this nutty pointer-array setup going...

    unsigned char *NewRAM = NULL; //global declare

    Then I send a pointer to a function that fills it...

    DumpRAM(sdFileName, &NewRAM);

    Code:
    u32 DumpRAM(char* DumpName, u8 **ramdata)
    {
        u32 filesize = 0;
        u32 chunksize = 0x100000;
        DWORD bytesread;
        u8 *buffer = NULL;
        u32 RamStart = 0;
        char *CopyAddr;
        if (!VerifyHook()) {
            MessageBox(NULL,"ProcessID no longer valid. Unable to read memory (DumpRAM, 1)", "Error", MB_OK);
            return 0;
        }
        if (Settings.Hook.sType == RAM_POINTER) {
            if (ReadProcessMemory(HookedProcess.hProcess, (void*)Settings.Hook.rOffset, &RamStart, 4, &bytesread) == 0) {
                return 0;
            }
    
        } else { RamStart = Settings.Hook.rOffset; }
        if (*ramdata) { free(*ramdata); *ramdata = NULL; }
        if ((Settings.Hook.AutoRam == BST_UNCHECKED) && (Settings.Hook.MaxRamSize)) {
            chunksize = Settings.Hook.MaxRamSize;
        } else { RamStart = 0; }
        do {
            if (!(buffer = (unsigned char*)realloc(&buffer, chunksize))) {
                MessageBox(NULL, "Unable to allocate buffer memory (DumpRAM,1).", "Error", MB_OK);
                return 0;
            }
            if (ReadProcessMemory(HookedProcess.hProcess, (void*)RamStart, (void*)buffer, chunksize, &bytesread) == 0) {
                if (chunksize > 0) { chunksize /= 2; }
                continue;
            }
            filesize += chunksize;
            RamStart += chunksize;
            if (!(*ramdata = (unsigned char*)realloc(*ramdata, filesize))) {
                MessageBox(NULL, "Unable to allocate ramdata memory (DumpRAM,1).", "Error", MB_OK);
                return 0;
            }
            if (filesize > chunksize) { CopyAddr = &(*ramdata[filesize-chunksize]); }
            else { CopyAddr = &(*ramdata[0]); }
            memcpy(CopyAddr, buffer, chunksize);
        } while((Settings.Hook.AutoRam == BST_CHECKED) && (chunksize > 0));
        //spit out the 4 bytes at 0x4D6A1C to test
        sprintf(ErrTxt, "%X", (int)(*ramdata)[0x4D6A1C]);
        MessageBox(NULL,ErrTxt,"Error",0);
        return 0;
    }
    See what I'm attempting to do with memcpy? I can't figure out how the syntax goes though, assuming this is even possible. I'm trying to get a pointer and add the buffer to the end of the main array after increasing its size as needed. Basically, I'm trying to dump the entire memory of the process unless an exact region has been specified.

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by tabstop View Post
    It's difficult for compilers to warn about any run-time error. (Stack size is I believe set in the linker, and can probably be changed if you are wise in the ways of the linker.)

    As to ramdata, if you know that the function will never be called with NULL as the second parameter, then there's no problem. If it's possible, you would just need to add a check. Given what the function is probably doing, passing 0 as a second parameter doesn't appear to be at all sensible, so you may not need to have to worry about it.

    Edit: by "just need to add a check" I mean in order to avoid dereferencing a NULL pointer. Making the semantics work with a NULL pointer is something else altogether.
    And further, you can, if you like, change the stack to be in a differnet piece of memory than the original assigned by the OS (just make sure you set it back again before leaving - we used to have our own dynamically allocated stack in a driver I worked on, since stacks in the Windows kernel is some pitifull small amount like 12KB, and we were running a full "new graphics processor" simulator inside the graphics driver - it could easily use a few hundred kilobytes of stack). If you create a differnet thread, then that code will have the stack-size assigned by CreateThread, where you can give it a stack-size yourself, so the compiler and linker will have very little chance of knowing what size stack you are actually using.

    As to your last question:
    Code:
    CopyAddr = &(*ramdata[0])
    probably should be:
    Code:
    CopyAddr = &(*ramdata)[0]
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    Registered User
    Join Date
    Jun 2008
    Posts
    161
    Ok. This is ........ing me off. Is there something I should know about XP SP3? I can't get ReadProcessMemory to work at all. I either get a 299 or 998 error.

    Edit: I got it to read now, but I still can't get the loop-memcpy method to work. Is there some reason Trying to ReaDProcessMemory starting at 0 seems to throw the 299 every time?
    Last edited by Viper187; 09-22-2008 at 11:48 AM.

  12. #12
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Viper187 View Post
    Ok. This is ........ing me off. Is there something I should know about XP SP3? I can't get ReadProcessMemory to work at all. I either get a 299 or 998 error.
    There's been some discussions before about ReadProcessMemory and protection/privileges. Whils searching for "Error Code 299", I found this thread, which also tells you what that error code means.
    http://cboard.cprogramming.com/showthread.php?p=757973

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  13. #13
    Registered User
    Join Date
    Jun 2008
    Posts
    161
    Doesn't really help me.

    edit: Ok, what gives? I can read a meg from 0x400000 and 4 megs from 0x3B0A0000 but I can't read a meg from 0x500000 or anywhere below 0x400000 in the same process. That makes no sense.
    Last edited by Viper187; 09-22-2008 at 03:26 PM.

  14. #14
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    Basically, I'm trying to dump the entire memory of the process unless an exact region has been specified.
    I just couldn't understand your "rocket science" code. I'm assuming that you're running this code under an Admin account and if so, have you enabled the debug privilege? By default these privileges are NOT enabled for an Admin account. Thus, if the debug privileges are not enabled, you're pretty much guaranteed to crash and burn if you try the read the memory of, let's say Notepad.exe. My gut feeling is that you may have a wild pointer somewhere. Especially, if you're generating a 998 error, invalid access to memory location.

    I've attached a simple process memory reader example. Input the process id of notepad.exe and it will determine where "Format" from the notepad menu is located. Hopefully, this example can be of some help to you.

    Code:
    #pragma comment(lib, "advapi32.lib")
    #pragma comment(lib, "psapi.lib")
    
    #include <windows.h>
    #include <stdio.h>
    #include <psapi.h>
    // Binary equivalent of "Format" which is used as a search against Notepad.exe
    const BYTE bPattern[6]={0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74};
    
    BOOL EnableTokenPrivilege (LPTSTR privilege)
    {
        HANDLE hToken;                        
        TOKEN_PRIVILEGES token_privileges;                  
        DWORD dwSize;                        
        ZeroMemory (&token_privileges, sizeof (token_privileges));
        token_privileges.PrivilegeCount = 1;
        if ( !OpenProcessToken (GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
            return FALSE;
        if (!LookupPrivilegeValue ( NULL, privilege, &token_privileges.Privileges[0].Luid))
        { 
            CloseHandle (hToken);
            return FALSE;
        }
    
        token_privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        if (!AdjustTokenPrivileges ( hToken, FALSE, &token_privileges, 0, NULL, &dwSize))
        { 
            CloseHandle (hToken);
            return FALSE;
        }
        CloseHandle (hToken);
        return TRUE;
    }
    
    BOOL SearchProcessMemory(int iProcessId)
    {
        DWORD  cbRead, cbNeeded, iIndex;
        HMODULE hModule;
        MODULEINFO ModuleInfo;
        BYTE *bBuffer = 0; 
        HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE, iProcessId);
        EnumProcessModules(hProcess, &hModule, sizeof(hModule), &cbNeeded);
        GetModuleInformation(hProcess, hModule, &ModuleInfo, sizeof(MODULEINFO));
        bBuffer = (LPBYTE)GlobalAlloc(GMEM_FIXED, ModuleInfo.SizeOfImage+1);
        ReadProcessMemory(hProcess, ModuleInfo.lpBaseOfDll, bBuffer, ModuleInfo.SizeOfImage, &cbRead);
        //Search the entire memory of our target process
        for( iIndex = 0; iIndex < ModuleInfo.SizeOfImage; iIndex++)
        {
            if (!memcmp(&bBuffer[iIndex], bPattern, 6))
            { 
                // calculate of lpBaseOfDll (start of exe + i)
                DWORD dwFoundAtAddress = (DWORD)ModuleInfo.lpBaseOfDll + iIndex;
                printf("we found it at 0x%2X\n", dwFoundAtAddress);
                return TRUE;
            }
        }
        return FALSE;
    }
    
    int main(int argc, char **argv)
    {
        if ( !EnableTokenPrivilege (SE_DEBUG_NAME) )
        {
            printf ( "Cannot get required privilege %lu\n", GetLastError () );
            return 0;
        }
        if(SearchProcessMemory(atoi(argv[1])) == FALSE)
            printf("Binary signature NOT found\n");
        return 0;
    }

  15. #15
    Registered User
    Join Date
    Jun 2008
    Posts
    161
    I'm working on implementing that to see if it solves the problem. I've never used GlobalAlloc though. Is there some reason to choose that over malloc() or realloc()? You also didn't free (GlobalFree?) the memory when it finishes.

    edit: This SUCKS. It doesn't appear to be dumping the whole process, only the first 0x154000. Don't tell me I have to use the token privileges thing and still loop to find the actual size of the process' memory. Task Manager can tell me the damn thing is using 50 megs, why can't one of these bloody API calls?

    Code:
    u32 DumpRAM(char* DumpName, u8 **ramdata)
    {
        u32 filesize = 0;
        u32 chunksize = 0x100000;
        DWORD bytesread;
        u8 *buffer = NULL;
        u32 RamStart;
        u32 i;
        char *CopyAddr;
        if (!VerifyHook()) {
            MessageBox(NULL,"ProcessID no longer valid. Unable to read memory (DumpRAM, 1)", "Error", MB_OK);
            return 0;
        }
        HMODULE hModule;
        MODULEINFO ModuleInfo;
        DWORD cbNeeded;
        if (Settings.Hook.sType == RAM_POINTER) {
            if (ReadProcessMemory(HookedProcess.hProcess, (void*)Settings.Hook.rOffset, &RamStart, 4, &bytesread) == 0) {
                return 0;
            }
    
        } else { RamStart = Settings.Hook.rOffset; }
        if ((Settings.Hook.AutoRam == BST_UNCHECKED) && (Settings.Hook.MaxRamSize)) {
            chunksize = Settings.Hook.MaxRamSize;
        } else {
            EnumProcessModules(HookedProcess.hProcess, &hModule, sizeof(hModule), &cbNeeded);
            GetModuleInformation(HookedProcess.hProcess, hModule, &ModuleInfo, sizeof(MODULEINFO));
            RamStart = (DWORD)ModuleInfo.lpBaseOfDll;
            chunksize = ModuleInfo.SizeOfImage;
        }
        if (*ramdata) { free(*ramdata); *ramdata = NULL; }
        if (!(*ramdata = (unsigned char*)malloc(chunksize+1))) {
            MessageBox(NULL, "Unable to allocate ramdata memory (DumpRAM,1).", "Error", MB_OK);
            return 0;
        }
        if (ReadProcessMemory(HookedProcess.hProcess, (void*)RamStart, *ramdata, chunksize, &bytesread) == 0) {
            sprintf(ErrTxt, "&#37;x,%x,%x, %u", RamStart, chunksize, sizeof(buffer), GetLastError());
            MessageBox(NULL,ErrTxt,"Error",0);
        }
        sprintf(ErrTxt, "%X", (*ramdata)[0x4D6A1c]);
        MessageBox(NULL,ErrTxt,"Debug",0);
    free(*ramdata); *ramdata = NULL;
        return 0;
    }
    
    BOOL EnableTokenPrivilege (LPTSTR privilege)
    {
        HANDLE hToken;
        TOKEN_PRIVILEGES token_privileges;
        DWORD dwSize;
        ZeroMemory (&token_privileges, sizeof (token_privileges));
        token_privileges.PrivilegeCount = 1;
        if ( !OpenProcessToken (GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
            return FALSE;
        if (!LookupPrivilegeValue ( NULL, privilege, &token_privileges.Privileges[0].Luid))
        {
            CloseHandle (hToken);
            return FALSE;
        }
    
        token_privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        if (!AdjustTokenPrivileges ( hToken, FALSE, &token_privileges, 0, NULL, &dwSize))
        {
            CloseHandle (hToken);
            return FALSE;
        }
        CloseHandle (hToken);
        return TRUE;
    }
    
    int InitHook()
    {
        if ( !EnableTokenPrivilege (SE_DEBUG_NAME) )
        {
            MessageBox(NULL, "Cannot get required privilege", "Error", MB_OK);
            return 1;
        }
        HookedProcess.hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, HookedProcess.dwProcessId);
        char txtTitle[100];
        strcpy(txtTitle,PROGRAM_NAME); strcat(txtTitle," - ");
        strcat(txtTitle,Settings.Hook.FileName);
        SetWindowText(hwndMain,txtTitle);
        return 0;
    }
    Last edited by Viper187; 09-22-2008 at 09:41 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Segmentation fault problem
    By odedbobi in forum Linux Programming
    Replies: 1
    Last Post: 11-19-2008, 03:36 AM
  2. Segmentation fault
    By bennyandthejets in forum C++ Programming
    Replies: 7
    Last Post: 09-07-2005, 05:04 PM
  3. Segmentation fault
    By NoUse in forum C Programming
    Replies: 4
    Last Post: 03-26-2005, 03:29 PM
  4. Locating A Segmentation Fault
    By Stack Overflow in forum C Programming
    Replies: 12
    Last Post: 12-14-2004, 01:33 PM
  5. Segmentation fault...
    By alvifarooq in forum C++ Programming
    Replies: 14
    Last Post: 09-26-2004, 12:53 PM