запуск PE (exe) в памяти
От: explorus Россия  
Дата: 26.08.09 15:35
Оценка:
Решил поэкспериментировать с PE форматом и для начала просто попытаться файл с диска отобразить в память и запустить.
в качестве жертвы запуска — обычное Win32 GUI-приложение (MS Visual Studio сама генерит).
Вроде бы все хорошо, отлавливаю ExitProcess, пытаюсь освободить зарезервированную память, и пытаюсь вызвать оригинальную ExitProcess... И тут лажа происходит типа Access violation at 0xC0000005 и DEP под Vistой срабатывает, цуко...
Короче не пойму как это юзать нужно...
см. в коде коммент: ПАДАЕТ ТУТ!!!
впрочем если закоментарить строчку с VirtualFree( g_hLoadedModule, 0, MEM_RELEASE ); тогда все работает
может у кого-нить придет умная мысль в голову насчет этого, поделитесь, плиз

// peloader.cpp : Defines the entry point for the application.
//

// Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms.
#ifndef WINVER                          // Specifies that the minimum required platform is Windows Vista.
#define WINVER 0x0600           // Change this to the appropriate value to target other versions of Windows.
#endif

#ifndef _WIN32_WINNT            // Specifies that the minimum required platform is Windows Vista.
#define _WIN32_WINNT 0x0600     // Change this to the appropriate value to target other versions of Windows.
#endif

#ifndef _WIN32_WINDOWS          // Specifies that the minimum required platform is Windows 98.
#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
#endif

#ifndef _WIN32_IE                       // Specifies that the minimum required platform is Internet Explorer 7.0.
#define _WIN32_IE 0x0700        // Change this to the appropriate value to target other versions of IE.
#endif

#include <windows.h>
#include <tchar.h>

#pragma code_seg(push,r1,".eccode")

#define SEH
#define spy_ExitProcess

#define ERR_IMAGE_IS_NOT_PE              1
#define ERR_IMAGE_NOT_VALLOC             2
#define ERR_IMAGE_NOT_HVALLOC            3
#define ERR_IMAGE_NOT_SVALLOC            4
#define ERR_IMAGE_NO_FIXUP               5
#define ERR_IMAGE_FIXUP_INVALID          6
#define ERR_IMAGE_SEC_PROTECTION_FAILED  7
#define ERR_IMAGE_NO_IMPORT              8
#define ERR_IMAGE_IMPLIB_NOT_LOADED      9

#define LDRP_RELOCATION_INCREMENT        0x1
#define LDRP_RELOCATION_FINAL            0x2

#define IMAGE_GET_DOSHEADER( lpbImage ) ((PIMAGE_DOS_HEADER)lpbImage)
#define IMAGE_GET_NTHEADER( lpbImage ) ((PIMAGE_NT_HEADERS32)((DWORD)lpbImage + IMAGE_GET_DOSHEADER(lpbImage)->e_lfanew))
#define IMAGE_IS_PE( lpbImage ) (IMAGE_GET_DOSHEADER(lpbImage)->e_magic == IMAGE_DOS_SIGNATURE ? \
    (IMAGE_GET_NTHEADER(lpbImage)->Signature == IMAGE_NT_SIGNATURE ? TRUE : FALSE) : FALSE)
#define IMAGE_GET_DIRECTORY( lpbImage, DIRECTORY_ID ) \
    (&IMAGE_GET_NTHEADER(lpbImage)->OptionalHeader.DataDirectory[DIRECTORY_ID])

// Global variable
HMODULE g_hLoadedModule = NULL;
#ifdef spy_ExitProcess
typedef VOID (WINAPI *_ExitProcess)(__in UINT uExitCode);
_ExitProcess g_ExitProcess = NULL;
LPDWORD g_ImpExitProcess = NULL;
#endif

typedef struct 
{
    WORD    wOffset:12;
    WORD    wType:4;
} IMAGE_FIXUP_ENTRY, *PIMAGE_FIXUP_ENTRY;

// Process Envorinment Block
typedef struct _PEB {
    DWORD smth[2]; // doesn't matter
    PVOID SectionBaseAddress;
} PEB, *PPEB;

// Thread Environment Block
typedef struct _TEB {
    DWORD smth[12]; // doesn't matter
    PPEB Peb;
} TEB, *PTEB;

typedef void (__cdecl *_mainCRTStartup)(void);

#ifdef _MSC_VER
#pragma function(memset)
#pragma function(memcpy)
#endif 

void * __cdecl memset (
        void *dst,
        int val,
        size_t count
        )
{
        void *start = dst;

        while (count--) {
                *(char *)dst = (char)val;
                dst = (char *)dst + 1;
        }

        return(start);
}

void * __cdecl memcpy (
        void * dst,
        const void * src,
        size_t count
        )
{
        void * ret = dst;

        while (count--) {
                *(char *)dst = *(char *)src;
                dst = (char *)dst + 1;
                src = (char *)src + 1;
        }

        return(ret);
}


VOID MessageGetLastError( HWND hWndParent, LPCTSTR szTitle )
{
  LPTSTR lpMsgBuf;
  if ( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | 
                      FORMAT_MESSAGE_FROM_SYSTEM | 
                      FORMAT_MESSAGE_IGNORE_INSERTS,
                      NULL,
                      GetLastError(),
                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                      (LPTSTR) &lpMsgBuf,
                      0,
                      NULL ) )
  {
    // Display the string.
    MessageBox( hWndParent, (LPCTSTR)lpMsgBuf, szTitle, MB_OK + MB_ICONERROR );
    // Free the buffer.
    LocalFree( lpMsgBuf );
  }
};

HMODULE PeLoadModule(LPBYTE lpbImage, LPDWORD lpdwError)
{
    if (lpdwError) *lpdwError = 0;
    if (IMAGE_IS_PE(lpbImage))
    {
        HMODULE lpbBase = (HMODULE) VirtualAlloc( NULL,
            //LPVOID)IMAGE_GET_NTHEADER(lpbImage)->OptionalHeader.ImageBase,
            IMAGE_GET_NTHEADER(lpbImage)->OptionalHeader.SizeOfImage, 
            MEM_RESERVE, PAGE_NOACCESS );
        if (lpbBase)
        {
            // headers copy
            LPBYTE lpbHeaders = (LPBYTE) VirtualAlloc( lpbBase, 
                IMAGE_GET_NTHEADER(lpbImage)->OptionalHeader.SizeOfHeaders, 
                MEM_COMMIT, PAGE_READWRITE );
            if(lpbHeaders)    
            {
                CopyMemory( lpbHeaders, lpbImage, IMAGE_GET_NTHEADER(lpbImage)->OptionalHeader.SizeOfHeaders );

                // section loading
                // macro IMAGE_FIRST_SECTION defined in WinNT.h
                PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(IMAGE_GET_NTHEADER(lpbImage)); 
                for (DWORD i=0;i<IMAGE_GET_NTHEADER(lpbImage)->FileHeader.NumberOfSections;i++,pish++)
                {
                    if (pish->VirtualAddress)
                    {
                        LPBYTE lpbSectionBase = (LPBYTE) VirtualAlloc(
                            (LPVOID)((DWORD)lpbBase+pish->VirtualAddress),
                            pish->Misc.VirtualSize,MEM_COMMIT,PAGE_READWRITE);
                        if (lpbSectionBase)
                        {
                            ZeroMemory(lpbSectionBase,pish->Misc.VirtualSize);
                            // macro min defined in WinDef.h
                            CopyMemory(lpbSectionBase, lpbImage + pish->PointerToRawData, 
                                min(pish->Misc.VirtualSize,pish->SizeOfRawData));
                        }
                        else if (lpdwError) *lpdwError = ERR_IMAGE_NOT_SVALLOC;
                    }
                }
                DWORD dwOldProtect = 0;
                VirtualProtect(lpbBase, 
                    IMAGE_GET_NTHEADER(lpbImage)->OptionalHeader.SizeOfHeaders, 
                    PAGE_READONLY, &dwOldProtect);

                return lpbBase;
            }
            else if (lpdwError) *lpdwError = ERR_IMAGE_NOT_HVALLOC;
        }
        else if (lpdwError) *lpdwError = ERR_IMAGE_NOT_VALLOC;
    }
    else if (lpdwError) *lpdwError = ERR_IMAGE_IS_NOT_PE;
    return 0;
}

DWORD PeUnloadModule()
{
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = 
        &IMAGE_GET_NTHEADER(g_hLoadedModule)->OptionalHeader;
    PIMAGE_DATA_DIRECTORY pDirectoryImport = 
        IMAGE_GET_DIRECTORY(g_hLoadedModule,IMAGE_DIRECTORY_ENTRY_IMPORT);
    if (pDirectoryImport->VirtualAddress)
    {
        PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)g_hLoadedModule + pDirectoryImport->VirtualAddress);
        // loop for IMAGE_IMPORT_DESCRIPTOR[]
        while (pImportDescriptor->Name)
        {
            TCHAR szModuleName[MINCHAR] = _TEXT("");
            #ifdef UNICODE
            MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, 
                (LPCSTR)((DWORD)g_hLoadedModule + pImportDescriptor->Name), -1, 
                szModuleName, MINCHAR );
            #else
            lstrcpy(szModuleName,(LPCSTR)((DWORD)hModule + pImportDescriptor->Name));
            #endif
            HMODULE hImpModule = ::GetModuleHandle(szModuleName);
//            if (hImpModule) ::FreeLibrary(hImpModule);
            // Next
            pImportDescriptor++;
        }
    }
    PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(IMAGE_GET_NTHEADER(g_hLoadedModule)); 
    for (DWORD i=0;i<IMAGE_GET_NTHEADER(g_hLoadedModule)->FileHeader.NumberOfSections;i++,pish++)
    {
        if (pish->VirtualAddress)
        {
            VirtualFree((LPVOID)((DWORD)g_hLoadedModule+pish->VirtualAddress),
                0,MEM_DECOMMIT);
        }
    }
    VirtualFree( g_hLoadedModule, 
        IMAGE_GET_NTHEADER(g_hLoadedModule)->OptionalHeader.SizeOfHeaders, 
        MEM_DECOMMIT);
    VirtualFree( g_hLoadedModule, 0, MEM_RELEASE );
    return 0;
}

#ifdef spy_ExitProcess
// spy
VOID WINAPI spyExitProcess(__in UINT uExitCode)
{
    DWORD dwOldProtection = 0;
    if (VirtualProtect((LPVOID)g_ImpExitProcess,sizeof(DWORD),
                PAGE_READWRITE,&dwOldProtection))
    {
        *g_ImpExitProcess = (DWORD)g_ExitProcess;
        VirtualProtect((LPVOID)g_ImpExitProcess,sizeof(DWORD),
                dwOldProtection,&dwOldProtection);
    }
    PeUnloadModule();
    g_ExitProcess(uExitCode); // ПАДАЕТ ТУТ!!!
}
#endif

DWORD PeProcessRelocations(HMODULE hModule,LONG lImageBaseDelta)
{
    PIMAGE_FIXUP_ENTRY pFixup;
    PIMAGE_DATA_DIRECTORY pDirectoryBaseReloc = 
        IMAGE_GET_DIRECTORY(hModule,IMAGE_DIRECTORY_ENTRY_BASERELOC);
    if (pDirectoryBaseReloc->VirtualAddress)
    {
        PIMAGE_BASE_RELOCATION pRelocation = 
            (PIMAGE_BASE_RELOCATION)((DWORD)hModule + pDirectoryBaseReloc->VirtualAddress);

        DWORD dwRelocsSize = pDirectoryBaseReloc->Size;

        while (dwRelocsSize > 0)
        {
            dwRelocsSize -= pRelocation->SizeOfBlock;
            // Process current relocation block
            for (pFixup = (PIMAGE_FIXUP_ENTRY) 
                    (((LPBYTE) pRelocation) + IMAGE_SIZEOF_BASE_RELOCATION);
                (DWORD)pFixup < (DWORD)pRelocation + pRelocation->SizeOfBlock;
                pFixup++)
            {
                LPDWORD pFixupVA = NULL;
                DWORD t = 0;
                switch (pFixup->wType)
                {
                case IMAGE_REL_BASED_ABSOLUTE:
                    // no fixup required
                    break;
                case IMAGE_REL_BASED_HIGHLOW:
                    // HighLow - (32-bits) relocate the high and low half
                    // of an address.
                    pFixupVA = (LPDWORD) ((DWORD)hModule + pRelocation->VirtualAddress + 
                        pFixup->wOffset);
    
                    t = (DWORD)lImageBaseDelta;
                    *pFixupVA += t;

                    break;
                default:
                    return ERR_IMAGE_FIXUP_INVALID;
                }
            }
            pRelocation = (PIMAGE_BASE_RELOCATION)pFixup;
        }
    }
    else
        // Decided to load at different base, but no relocs present
        return ERR_IMAGE_NO_FIXUP;

    return 0;
}

DWORD PeProcessImports(HMODULE hModule)
{
#ifdef spy_ExitProcess
    WORD wEP = 0;
#endif
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = 
        &IMAGE_GET_NTHEADER(hModule)->OptionalHeader;
    PIMAGE_DATA_DIRECTORY pDirectoryImport = 
        IMAGE_GET_DIRECTORY(hModule,IMAGE_DIRECTORY_ENTRY_IMPORT);
    if (pDirectoryImport->VirtualAddress)
    {
        PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)hModule + pDirectoryImport->VirtualAddress);
        // loop for IMAGE_IMPORT_DESCRIPTOR[]
        while (pImportDescriptor->Name)
        {
            TCHAR szModuleName[MINCHAR] = _TEXT("");
            #ifdef UNICODE
            MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, 
                (LPCSTR)((DWORD)hModule+pImportDescriptor->Name), -1, 
                szModuleName, MINCHAR );
            #else
            lstrcpy(szModuleName,(LPCSTR)((DWORD)hModule+pImportDescriptor->Name));
            #endif
            HMODULE hImpModule = ::LoadLibrary(szModuleName);
            if (!hImpModule) 
            {
                // + message for name of dll
                return ERR_IMAGE_IMPLIB_NOT_LOADED;
            }
#ifdef spy_ExitProcess
            if (lstrcmpi(szModuleName,_TEXT("KERNEL32.DLL"))==0) wEP = 1;
            else wEP = 0;
#endif
            // Thunk[]
            PIMAGE_THUNK_DATA pitd = (PIMAGE_THUNK_DATA)
            ((DWORD)hModule + (pImportDescriptor->OriginalFirstThunk ? 
                pImportDescriptor->OriginalFirstThunk : 
                pImportDescriptor->FirstThunk));
            PIMAGE_THUNK_DATA pFirstThunk = (PIMAGE_THUNK_DATA)
                ((DWORD)hModule + pImportDescriptor->FirstThunk);

            // loop for IMAGE_THUNK_DATA
            while(pitd->u1.AddressOfData)
            {
                LPCSTR lpProcName = ((pitd->u1.Ordinal & IMAGE_ORDINAL_FLAG32) ? 
                    (LPCSTR)(IMAGE_ORDINAL32(pitd->u1.Ordinal)) :
                    (LPCSTR)((PIMAGE_IMPORT_BY_NAME)((DWORD)hModule + pitd->u1.AddressOfData))->Name);
                DWORD dwFunc = (DWORD)GetProcAddress(hImpModule,lpProcName);
#ifdef spy_ExitProcess
                if (wEP)
                {
                    if (pitd->u1.Ordinal & IMAGE_ORDINAL_FLAG32)
                    {
                        if (IMAGE_ORDINAL32(pitd->u1.Ordinal)==183) wEP |= 0x0100;
                    }
                    else
                    {
                        TCHAR szProcName[MINCHAR] = _TEXT("");
                        #ifdef UNICODE
                        MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, 
                            (LPCSTR)((PIMAGE_IMPORT_BY_NAME)((DWORD)hModule + pitd->u1.AddressOfData))->Name, -1, 
                            szProcName, MINCHAR );
                        #else
                        lstrcpy(szProcName,(LPCSTR)((PIMAGE_IMPORT_BY_NAME)((DWORD)hModule + pitd->u1.AddressOfData))->Name);
                        #endif
                        if (lstrcmpi(szProcName,_TEXT("ExitProcess"))==0)  wEP |= 0x0100;
                    }
                    if (wEP&0x0100) 
                    {
                        g_ExitProcess = (_ExitProcess)dwFunc;
                        dwFunc = (DWORD)spyExitProcess;
                        g_ImpExitProcess = &(pFirstThunk->u1.Function);
                        wEP = 0;
                    }
                }
#endif
                pFirstThunk->u1.Function = dwFunc;
                pFirstThunk++;
                pitd++;
            }
            // Next
            pImportDescriptor++;
        }
    }
    else return ERR_IMAGE_NO_IMPORT;
    return 0;
}

DWORD PeGetSectionProtection(DWORD dwCharacteristics)
{
    DWORD dwProtection = 0;

    if (dwCharacteristics & IMAGE_SCN_MEM_NOT_CACHED)
        dwProtection |= PAGE_NOCACHE;

    if ((dwCharacteristics & IMAGE_SCN_MEM_EXECUTE) &&
        (dwCharacteristics & IMAGE_SCN_MEM_READ) &&
        (dwCharacteristics & IMAGE_SCN_MEM_WRITE))
        dwProtection |= PAGE_EXECUTE_READWRITE;
    else if ((dwCharacteristics & IMAGE_SCN_MEM_EXECUTE) &&
        (dwCharacteristics & IMAGE_SCN_MEM_READ))
        dwProtection |= PAGE_EXECUTE_READ;
    else if ((dwCharacteristics & IMAGE_SCN_MEM_READ) && 
        (dwCharacteristics & IMAGE_SCN_MEM_WRITE))
        dwProtection |= PAGE_READWRITE;
    else if (dwCharacteristics & IMAGE_SCN_MEM_WRITE)
        dwProtection |= PAGE_WRITECOPY;
    else if (dwCharacteristics & IMAGE_SCN_MEM_READ)
        dwProtection |= PAGE_READONLY;
    else
        dwProtection |= PAGE_EXECUTE_READWRITE;

    return dwProtection;
}

DWORD PeSetSectionProtection(HMODULE hModule)
{
    DWORD dwReturn = 0;
    PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(IMAGE_GET_NTHEADER(hModule)); 
    for (DWORD i=0;i<IMAGE_GET_NTHEADER(hModule)->FileHeader.NumberOfSections;i++,pish++)
    {
        if (pish->VirtualAddress)
        {
            DWORD dwOldProtection = 0;
            if (!VirtualProtect((LPVOID)((DWORD)hModule + pish->VirtualAddress),pish->Misc.VirtualSize,
                PeGetSectionProtection(pish->Characteristics),&dwOldProtection))
                dwReturn = ERR_IMAGE_SEC_PROTECTION_FAILED;
        }
    }
    return dwReturn;
}

void peExecute(HMODULE hModule)
{
    // PEB.ImageBaseAddress correction for resource functions
//    ((TEB*)__readfsdword(PcTeb))->Peb->SectionBaseAddress = (PVOID)hModule;
    _mainCRTStartup newmain = (_mainCRTStartup)((DWORD)hModule + IMAGE_GET_NTHEADER(hModule)->OptionalHeader.AddressOfEntryPoint);
    newmain();
}

VOID LoadExe(LPCTSTR szFileName)
{
    if (::GetFileAttributes(szFileName)!=INVALID_FILE_ATTRIBUTES)
    {
        HANDLE hFile = ::CreateFile( szFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 
            FILE_ATTRIBUTE_NORMAL, NULL );
        if(hFile!=INVALID_HANDLE_VALUE) {
            DWORD dwFileSizeHigh = 0;
            DWORD dwImageSize = ::GetFileSize(hFile,&dwFileSizeHigh);
            if (dwFileSizeHigh==0)
            {
                HANDLE hMappedFile = ::CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
                ::CloseHandle(hFile);
                if(hMappedFile) {
                    LPVOID lpMappedFile = ::MapViewOfFile(hMappedFile,FILE_MAP_READ,0,0,0);
                    ::CloseHandle(hMappedFile);
                    if(lpMappedFile) {
                        DWORD dwError = 0;
                        g_hLoadedModule = PeLoadModule((LPBYTE)lpMappedFile,&dwError);
                        ::UnmapViewOfFile(lpMappedFile); 
                        if (g_hLoadedModule)
                        {
                            if (dwError) 
                                ::MessageBox(::GetDesktopWindow(),_TEXT("File loaded unsuccessful"),_TEXT("Peloader"),MB_OK+MB_ICONERROR);
//                                print_f(_TEXT("file loaded unsuccessful: %u\n"),dwError);
                            else
                            {
                                LONG lImageBaseDelta = (LONG)((DWORD)g_hLoadedModule - IMAGE_GET_NTHEADER(g_hLoadedModule)->OptionalHeader.ImageBase);
                                if (lImageBaseDelta)
                                {
                                    // Processing relocs
                                    dwError = PeProcessRelocations(g_hLoadedModule,lImageBaseDelta);
//                                    if (dwError) print_f(_TEXT("can't processed relocations: %u\n"),dwError);
                                }
//                                else print_f(_TEXT("relocations not processed\n"));
                                // Processing import
                                dwError = PeProcessImports(g_hLoadedModule);
//                                if (dwError) print_f(_TEXT("can't process import : %u\n"),dwError);
                                // Set protection
                                dwError = PeSetSectionProtection(g_hLoadedModule);
//                                if (dwError) print_f(_TEXT("can't section protect : %u\n"),dwError);
                                peExecute(g_hLoadedModule);
/*
                                dwError = PeUnloadModule();
                                if (dwError) print_f(_TEXT("can't unload pe image: %u\n"),dwError);
*/
                            }
                        }
//                        else print_f(_TEXT("can't load pe image: %08X\n"),dwError);
                    }
                    else MessageGetLastError(::GetDesktopWindow(),_TEXT("Can't mapview file"));
                }
                else MessageGetLastError(::GetDesktopWindow(),_TEXT("Can't mapping file"));
            }
            else
            {
                ::MessageBox(::GetDesktopWindow(),_TEXT("File is very large"),_TEXT("Peloader"),MB_OK+MB_ICONERROR);
                ::CloseHandle(hFile);
            }
        }
        else MessageGetLastError(::GetDesktopWindow(),_TEXT("Can't open file"));
    }
    else MessageGetLastError(::GetDesktopWindow(),_TEXT("Can't find file"));
}

#ifdef SEH
LONG CALLBACK TopLevelExceptionFilter( EXCEPTION_POINTERS *ExceptionInfo )
{
  if (
      ::MessageBox(
      ::GetDesktopWindow(),
      _TEXT("Unhandled exception was detected.\nClose application?"),
      _TEXT("Peloader: error"),
      MB_OKCANCEL+MB_ICONERROR
    ) == IDOK
    ) ::ExitProcess(0);
  return EXCEPTION_EXECUTE_HANDLER;
}
#endif

int WinMainCRTStartup(void)
{
#ifdef SEH
    // enables an application to supersede the top-level exception handler 
    // of each thread and process
    SetUnhandledExceptionFilter( TopLevelExceptionFilter );
#endif
    LoadExe(_TEXT("Test.exe"));
    ::ExitProcess(0);
    return 0;
}

#pragma code_seg(pop, r1)


И не нужно флудить вопросами типа: а нафига оно тебе?...
Re: запуск PE (exe) в памяти
От: explorus Россия  
Дата: 26.08.09 15:45
Оценка:
+ модуль кстати можно вставить в пустой проект и собрать с отключенным crt
Re: запуск PE (exe) в памяти
От: explorus Россия  
Дата: 28.08.09 15:03
Оценка:
разобрался, теперь и под вистой работает
решение простое: VirtualFree( g_hLoadedModule, 0, MEM_DECOMMIT | MEM_RELEASE );
я сперва перемудрил немного
// peloader.cpp : Defines the entry point for the application.
//

// Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms.
#ifndef WINVER                          // Specifies that the minimum required platform is Windows Vista.
#define WINVER 0x0600           // Change this to the appropriate value to target other versions of Windows.
#endif

#ifndef _WIN32_WINNT            // Specifies that the minimum required platform is Windows Vista.
#define _WIN32_WINNT 0x0600     // Change this to the appropriate value to target other versions of Windows.
#endif

#ifndef _WIN32_WINDOWS          // Specifies that the minimum required platform is Windows 98.
#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
#endif

#ifndef _WIN32_IE                       // Specifies that the minimum required platform is Internet Explorer 7.0.
#define _WIN32_IE 0x0700        // Change this to the appropriate value to target other versions of IE.
#endif

#include <windows.h>
#include <tchar.h>

#pragma code_seg(push,r1,".eccode")

#define SEH
#define spy_ExitProcess

#define ERR_IMAGE_IS_NOT_PE              1
#define ERR_IMAGE_NOT_VALLOC             2
#define ERR_IMAGE_NOT_HVALLOC            3
#define ERR_IMAGE_NOT_SVALLOC            4
#define ERR_IMAGE_NO_FIXUP               5
#define ERR_IMAGE_FIXUP_INVALID          6
#define ERR_IMAGE_SEC_PROTECTION_FAILED  7
#define ERR_IMAGE_NO_IMPORT              8
#define ERR_IMAGE_IMPLIB_NOT_LOADED      9

#define LDRP_RELOCATION_INCREMENT        0x1
#define LDRP_RELOCATION_FINAL            0x2

#define IMAGE_GET_DOSHEADER( lpbImage ) ((PIMAGE_DOS_HEADER)lpbImage)
#define IMAGE_GET_NTHEADER( lpbImage ) ((PIMAGE_NT_HEADERS32)((DWORD)lpbImage + IMAGE_GET_DOSHEADER(lpbImage)->e_lfanew))
#define IMAGE_IS_PE( lpbImage ) (IMAGE_GET_DOSHEADER(lpbImage)->e_magic == IMAGE_DOS_SIGNATURE ? \
    (IMAGE_GET_NTHEADER(lpbImage)->Signature == IMAGE_NT_SIGNATURE ? TRUE : FALSE) : FALSE)
#define IMAGE_GET_DIRECTORY( lpbImage, DIRECTORY_ID ) \
    (&IMAGE_GET_NTHEADER(lpbImage)->OptionalHeader.DataDirectory[DIRECTORY_ID])

// Global variables
HMODULE g_hLoadedModule = NULL;
#ifdef spy_ExitProcess
typedef VOID (WINAPI *_ExitProcess)(__in UINT uExitCode);
_ExitProcess g_ExitProcess = NULL;
LPDWORD g_ImpExitProcess = NULL;
#endif

typedef struct 
{
    WORD    wOffset:12;
    WORD    wType:4;
} IMAGE_FIXUP_ENTRY, *PIMAGE_FIXUP_ENTRY;

// Process Envorinment Block
typedef struct _PEB {
    DWORD smth[2]; // doesn't matter
    PVOID SectionBaseAddress;
} PEB, *PPEB;

// Thread Environment Block
typedef struct _TEB {
    DWORD smth[12]; // doesn't matter
    PPEB Peb;
} TEB, *PTEB;

typedef void (__cdecl *_mainCRTStartup)(void);

#ifdef _MSC_VER
#pragma function(memset)
#pragma function(memcpy)
#endif 

void * __cdecl memset (
        void *dst,
        int val,
        size_t count
        )
{
        void *start = dst;

        while (count--) {
                *(char *)dst = (char)val;
                dst = (char *)dst + 1;
        }

        return(start);
}

void * __cdecl memcpy (
        void * dst,
        const void * src,
        size_t count
        )
{
        void * ret = dst;

        while (count--) {
                *(char *)dst = *(char *)src;
                dst = (char *)dst + 1;
                src = (char *)src + 1;
        }

        return(ret);
}


VOID MessageGetLastError( HWND hWndParent, LPCTSTR szTitle )
{
  LPTSTR lpMsgBuf;
  if ( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | 
                      FORMAT_MESSAGE_FROM_SYSTEM | 
                      FORMAT_MESSAGE_IGNORE_INSERTS,
                      NULL,
                      GetLastError(),
                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                      (LPTSTR) &lpMsgBuf,
                      0,
                      NULL ) )
  {
    // Display the string.
    MessageBox( hWndParent, (LPCTSTR)lpMsgBuf, szTitle, MB_OK + MB_ICONERROR );
    // Free the buffer.
    LocalFree( lpMsgBuf );
  }
};

HMODULE PeLoadModule(LPBYTE lpbImage, LPDWORD lpdwError)
{
    if (lpdwError) *lpdwError = 0;
    if (IMAGE_IS_PE(lpbImage))
    {
        HMODULE lpbBase = (HMODULE) VirtualAlloc( NULL,
            //LPVOID)IMAGE_GET_NTHEADER(lpbImage)->OptionalHeader.ImageBase,
            IMAGE_GET_NTHEADER(lpbImage)->OptionalHeader.SizeOfImage, 
            MEM_RESERVE, PAGE_NOACCESS );
        if (lpbBase)
        {
            // headers copy
            LPBYTE lpbHeaders = (LPBYTE) VirtualAlloc( lpbBase, 
                IMAGE_GET_NTHEADER(lpbImage)->OptionalHeader.SizeOfHeaders, 
                MEM_COMMIT, PAGE_READWRITE );
            if(lpbHeaders)    
            {
                CopyMemory( lpbHeaders, lpbImage, IMAGE_GET_NTHEADER(lpbImage)->OptionalHeader.SizeOfHeaders );

                // section loading
                // macro IMAGE_FIRST_SECTION defined in WinNT.h
                PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(IMAGE_GET_NTHEADER(lpbImage)); 
                for (DWORD i=0;i<IMAGE_GET_NTHEADER(lpbImage)->FileHeader.NumberOfSections;i++,pish++)
                {
                    if (pish->VirtualAddress)
                    {
                        LPBYTE lpbSectionBase = (LPBYTE) VirtualAlloc(
                            (LPVOID)((DWORD)lpbBase+pish->VirtualAddress),
                            pish->Misc.VirtualSize,MEM_COMMIT,PAGE_READWRITE);
                        if (lpbSectionBase)
                        {
                            ZeroMemory(lpbSectionBase,pish->Misc.VirtualSize);
                            // macro min defined in WinDef.h
                            CopyMemory(lpbSectionBase, lpbImage + pish->PointerToRawData, 
                                min(pish->Misc.VirtualSize,pish->SizeOfRawData));
                        }
                        else if (lpdwError) *lpdwError = ERR_IMAGE_NOT_SVALLOC;
                    }
                }
                DWORD dwOldProtect = 0;
                VirtualProtect(lpbHeaders, 
                    IMAGE_GET_NTHEADER(lpbImage)->OptionalHeader.SizeOfHeaders, 
                    PAGE_READONLY, &dwOldProtect);

                return lpbBase;
            }
            else if (lpdwError) *lpdwError = ERR_IMAGE_NOT_HVALLOC;
        }
        else if (lpdwError) *lpdwError = ERR_IMAGE_NOT_VALLOC;
    }
    else if (lpdwError) *lpdwError = ERR_IMAGE_IS_NOT_PE;
    return 0;
}

DWORD PeUnloadModule()
{
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = 
        &IMAGE_GET_NTHEADER(g_hLoadedModule)->OptionalHeader;
    PIMAGE_DATA_DIRECTORY pDirectoryImport = 
        IMAGE_GET_DIRECTORY(g_hLoadedModule,IMAGE_DIRECTORY_ENTRY_IMPORT);
    if (pDirectoryImport->VirtualAddress)
    {
        PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)g_hLoadedModule + pDirectoryImport->VirtualAddress);
        // loop for IMAGE_IMPORT_DESCRIPTOR[]
        while (pImportDescriptor->Name)
        {
            TCHAR szModuleName[MINCHAR] = _TEXT("");
            #ifdef UNICODE
            MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, 
                (LPCSTR)((DWORD)g_hLoadedModule + pImportDescriptor->Name), -1, 
                szModuleName, MINCHAR );
            #else
            lstrcpy(szModuleName,(LPCSTR)((DWORD)hModule + pImportDescriptor->Name));
            #endif
            HMODULE hImpModule = ::GetModuleHandle(szModuleName);
            if (hImpModule) ::FreeLibrary(hImpModule);
            // Next
            pImportDescriptor++;
        }
    }
    VirtualFree( g_hLoadedModule, 0, MEM_DECOMMIT | MEM_RELEASE );
    return 0;
}

#ifdef spy_ExitProcess
// spy
VOID WINAPI spyExitProcess(__in UINT uExitCode)
{
    PeUnloadModule();
    g_ExitProcess(uExitCode);
}
#endif

DWORD PeProcessRelocations(HMODULE hModule,LONG lImageBaseDelta)
{
    PIMAGE_FIXUP_ENTRY pFixup;
    PIMAGE_DATA_DIRECTORY pDirectoryBaseReloc = 
        IMAGE_GET_DIRECTORY(hModule,IMAGE_DIRECTORY_ENTRY_BASERELOC);
    if (pDirectoryBaseReloc->VirtualAddress)
    {
        PIMAGE_BASE_RELOCATION pRelocation = 
            (PIMAGE_BASE_RELOCATION)((DWORD)hModule + pDirectoryBaseReloc->VirtualAddress);

        DWORD dwRelocsSize = pDirectoryBaseReloc->Size;

        while (dwRelocsSize > 0)
        {
            dwRelocsSize -= pRelocation->SizeOfBlock;
            // Process current relocation block
            for (pFixup = (PIMAGE_FIXUP_ENTRY) 
                    (((LPBYTE) pRelocation) + IMAGE_SIZEOF_BASE_RELOCATION);
                (DWORD)pFixup < (DWORD)pRelocation + pRelocation->SizeOfBlock;
                pFixup++)
            {
                LPDWORD pFixupVA = NULL;
                DWORD t = 0;
                switch (pFixup->wType)
                {
                case IMAGE_REL_BASED_ABSOLUTE:
                    // no fixup required
                    break;
                case IMAGE_REL_BASED_HIGHLOW:
                    // HighLow - (32-bits) relocate the high and low half
                    // of an address.
                    pFixupVA = (LPDWORD) ((DWORD)hModule + pRelocation->VirtualAddress + 
                        pFixup->wOffset);
    
                    t = (DWORD)lImageBaseDelta;
                    *pFixupVA += t;

                    break;
                default:
                    return ERR_IMAGE_FIXUP_INVALID;
                }
            }
            pRelocation = (PIMAGE_BASE_RELOCATION)pFixup;
        }
    }
    else
        // Decided to load at different base, but no relocs present
        return ERR_IMAGE_NO_FIXUP;

    return 0;
}

DWORD PeProcessImports(HMODULE hModule)
{
#ifdef spy_ExitProcess
    WORD wEP = 0;
#endif
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = 
        &IMAGE_GET_NTHEADER(hModule)->OptionalHeader;
    PIMAGE_DATA_DIRECTORY pDirectoryImport = 
        IMAGE_GET_DIRECTORY(hModule,IMAGE_DIRECTORY_ENTRY_IMPORT);
    if (pDirectoryImport->VirtualAddress)
    {
        PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)hModule + pDirectoryImport->VirtualAddress);
        // loop for IMAGE_IMPORT_DESCRIPTOR[]
        while (pImportDescriptor->Name)
        {
            TCHAR szModuleName[MINCHAR] = _TEXT("");
            #ifdef UNICODE
            MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, 
                (LPCSTR)((DWORD)hModule+pImportDescriptor->Name), -1, 
                szModuleName, MINCHAR );
            #else
            lstrcpy(szModuleName,(LPCSTR)((DWORD)hModule+pImportDescriptor->Name));
            #endif
            HMODULE hImpModule = ::LoadLibrary(szModuleName);
            if (!hImpModule) 
            {
                // + message for name of dll
                return ERR_IMAGE_IMPLIB_NOT_LOADED;
            }
#ifdef spy_ExitProcess
            if (lstrcmpi(szModuleName,_TEXT("KERNEL32.DLL"))==0) wEP = 1;
            else wEP = 0;
#endif
            // Thunk[]
            PIMAGE_THUNK_DATA pitd = (PIMAGE_THUNK_DATA)
            ((DWORD)hModule + (pImportDescriptor->OriginalFirstThunk ? 
                pImportDescriptor->OriginalFirstThunk : 
                pImportDescriptor->FirstThunk));
            PIMAGE_THUNK_DATA pFirstThunk = (PIMAGE_THUNK_DATA)
                ((DWORD)hModule + pImportDescriptor->FirstThunk);

            // loop for IMAGE_THUNK_DATA
            while(pitd->u1.AddressOfData)
            {
                LPCSTR lpProcName = ((pitd->u1.Ordinal & IMAGE_ORDINAL_FLAG32) ? 
                    (LPCSTR)(IMAGE_ORDINAL32(pitd->u1.Ordinal)) :
                    (LPCSTR)((PIMAGE_IMPORT_BY_NAME)((DWORD)hModule + pitd->u1.AddressOfData))->Name);
                DWORD dwFunc = (DWORD)GetProcAddress(hImpModule,lpProcName);
#ifdef spy_ExitProcess
                if (wEP)
                {
                    if (pitd->u1.Ordinal & IMAGE_ORDINAL_FLAG32)
                    {
                        if (IMAGE_ORDINAL32(pitd->u1.Ordinal)==183) wEP |= 0x0100;
                    }
                    else
                    {
                        TCHAR szProcName[MINCHAR] = _TEXT("");
                        #ifdef UNICODE
                        MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, 
                            (LPCSTR)((PIMAGE_IMPORT_BY_NAME)((DWORD)hModule + pitd->u1.AddressOfData))->Name, -1, 
                            szProcName, MINCHAR );
                        #else
                        lstrcpy(szProcName,(LPCSTR)((PIMAGE_IMPORT_BY_NAME)((DWORD)hModule + pitd->u1.AddressOfData))->Name);
                        #endif
                        if (lstrcmpi(szProcName,_TEXT("ExitProcess"))==0)  wEP |= 0x0100;
                    }
                    if (wEP&0x0100) 
                    {
                        g_ExitProcess = (_ExitProcess)dwFunc;
                        dwFunc = (DWORD)spyExitProcess;
                        g_ImpExitProcess = &(pFirstThunk->u1.Function);
                        wEP = 0;
                    }
                }
#endif
                pFirstThunk->u1.Function = dwFunc;
                pFirstThunk++;
                pitd++;
            }
            // Next
            pImportDescriptor++;
        }
    }
    else return ERR_IMAGE_NO_IMPORT;
    return 0;
}

DWORD PeGetSectionProtection(DWORD dwCharacteristics)
{
    DWORD dwProtection = 0;

    if (dwCharacteristics & IMAGE_SCN_MEM_NOT_CACHED)
        dwProtection |= PAGE_NOCACHE;

    if ((dwCharacteristics & IMAGE_SCN_MEM_EXECUTE) &&
        (dwCharacteristics & IMAGE_SCN_MEM_READ) &&
        (dwCharacteristics & IMAGE_SCN_MEM_WRITE))
        dwProtection |= PAGE_EXECUTE_READWRITE;
    else if ((dwCharacteristics & IMAGE_SCN_MEM_EXECUTE) &&
        (dwCharacteristics & IMAGE_SCN_MEM_READ))
        dwProtection |= PAGE_EXECUTE_READ;
    else if ((dwCharacteristics & IMAGE_SCN_MEM_READ) && 
        (dwCharacteristics & IMAGE_SCN_MEM_WRITE))
        dwProtection |= PAGE_READWRITE;
    else if (dwCharacteristics & IMAGE_SCN_MEM_WRITE)
        dwProtection |= PAGE_WRITECOPY;
    else if (dwCharacteristics & IMAGE_SCN_MEM_READ)
        dwProtection |= PAGE_READONLY;
    else
        dwProtection |= PAGE_EXECUTE_READWRITE;

    return dwProtection;
}

DWORD PeSetSectionProtection(HMODULE hModule)
{
    DWORD dwReturn = 0;
    PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(IMAGE_GET_NTHEADER(hModule)); 
    for (DWORD i=0;i<IMAGE_GET_NTHEADER(hModule)->FileHeader.NumberOfSections;i++,pish++)
    {
        if (pish->VirtualAddress)
        {
            DWORD dwOldProtection = 0;
            if (!VirtualProtect((LPVOID)((DWORD)hModule + pish->VirtualAddress),pish->Misc.VirtualSize,
                PeGetSectionProtection(pish->Characteristics),&dwOldProtection))
                dwReturn = ERR_IMAGE_SEC_PROTECTION_FAILED;
        }
    }
    return dwReturn;
}

void peExecute(HMODULE hModule)
{
    // PEB.ImageBaseAddress correction for resource functions
//    ((TEB*)__readfsdword(PcTeb))->Peb->SectionBaseAddress = (PVOID)hModule;
    _mainCRTStartup newmain = (_mainCRTStartup)((DWORD)hModule + IMAGE_GET_NTHEADER(hModule)->OptionalHeader.AddressOfEntryPoint);
    newmain();
}

VOID LoadExe(LPCTSTR szFileName)
{
    if (::GetFileAttributes(szFileName)!=INVALID_FILE_ATTRIBUTES)
    {
        HANDLE hFile = ::CreateFile( szFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 
            FILE_ATTRIBUTE_NORMAL, NULL );
        if(hFile!=INVALID_HANDLE_VALUE) {
            DWORD dwFileSizeHigh = 0;
            DWORD dwImageSize = ::GetFileSize(hFile,&dwFileSizeHigh);
            if (dwFileSizeHigh==0)
            {
                HANDLE hMappedFile = ::CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
                ::CloseHandle(hFile);
                if(hMappedFile) {
                    LPVOID lpMappedFile = ::MapViewOfFile(hMappedFile,FILE_MAP_READ,0,0,0);
                    ::CloseHandle(hMappedFile);
                    if(lpMappedFile) {
                        DWORD dwError = 0;
                        g_hLoadedModule = PeLoadModule((LPBYTE)lpMappedFile,&dwError);
                        ::UnmapViewOfFile(lpMappedFile); 
                        if (g_hLoadedModule)
                        {
                            if (dwError) 
                                ::MessageBox(::GetDesktopWindow(),_TEXT("File loaded unsuccessful"),_TEXT("Peloader"),MB_OK+MB_ICONERROR);
//                                print_f(_TEXT("file loaded unsuccessful: %u\n"),dwError);
                            else
                            {
                                LONG lImageBaseDelta = (LONG)((DWORD)g_hLoadedModule - IMAGE_GET_NTHEADER(g_hLoadedModule)->OptionalHeader.ImageBase);
                                if (lImageBaseDelta)
                                {
                                    // Processing relocs
                                    dwError = PeProcessRelocations(g_hLoadedModule,lImageBaseDelta);
//                                    if (dwError) print_f(_TEXT("can't processed relocations: %u\n"),dwError);
                                }
//                                else print_f(_TEXT("relocations not processed\n"));
                                // Processing import
                                dwError = PeProcessImports(g_hLoadedModule);
//                                if (dwError) print_f(_TEXT("can't process import : %u\n"),dwError);
                                // Set protection
                                dwError = PeSetSectionProtection(g_hLoadedModule);
//                                if (dwError) print_f(_TEXT("can't section protect : %u\n"),dwError);
                                peExecute(g_hLoadedModule);
                                // unreachable

/*
                                dwError = PeUnloadModule();
                                if (dwError) print_f(_TEXT("can't unload pe image: %u\n"),dwError);
*/
                            }
                        }
//                        else print_f(_TEXT("can't load pe image: %08X\n"),dwError);
                    }
                    else MessageGetLastError(::GetDesktopWindow(),_TEXT("Can't mapview file"));
                }
                else MessageGetLastError(::GetDesktopWindow(),_TEXT("Can't mapping file"));
            }
            else
            {
                ::MessageBox(::GetDesktopWindow(),_TEXT("File is very large"),_TEXT("Peloader"),MB_OK+MB_ICONERROR);
                ::CloseHandle(hFile);
            }
        }
        else MessageGetLastError(::GetDesktopWindow(),_TEXT("Can't open file"));
    }
    else MessageGetLastError(::GetDesktopWindow(),_TEXT("Can't find file"));
}

#ifdef SEH
LONG CALLBACK TopLevelExceptionFilter( EXCEPTION_POINTERS *ExceptionInfo )
{
  if (
      ::MessageBox(
      ::GetDesktopWindow(),
      _TEXT("Unhandled exception was detected.\nClose application?"),
      _TEXT("Peloader: error"),
      MB_OKCANCEL+MB_ICONERROR
    ) == IDOK
    ) ::ExitProcess(0);
  return EXCEPTION_EXECUTE_HANDLER;
}
#endif

int WinMainCRTStartup(void)
{
#ifdef SEH
    // enables an application to supersede the top-level exception handler 
    // of each thread and process
    SetUnhandledExceptionFilter( TopLevelExceptionFilter );
#endif
    LoadExe(_TEXT("Test.exe"));
    ::ExitProcess(0);
    return 0;
}

#pragma code_seg(pop, r1)
Re[2]: запуск PE (exe) в памяти
От: gear nuke  
Дата: 29.08.09 01:16
Оценка:
Здравствуйте, explorus, Вы писали:

E>разобрался, теперь и под вистой работает


А в чём проблема, разобрался? Я сначала подумал, что возникает гонка подобная FreeLibrary & ExitThread, но в коде её не увидел. А про отладчик ты и сам должен знать

Что не понравилось — VirtualAlloc на каждую секцию PE, на каких-то образах это сработает, на каких-то нет, из-за разной гранулярности VirtualAlloc и выравнивания секций. Ну это, как оказывалось, наследие статьи
Автор(ы): Максим М. Гумеров
Дата: 20.03.2003
Не вдаваясь в подробности, скажу лишь, что исследование было начато ради сокрытия использования программой на Delphi некоей DLL (написанной на VC++). То есть оператор видит один только Exe-файл, запускает его, а тот каким-то образом подключает функции, содержащиеся изначально (при компиляции проекта) в некоторой DLL.
. И выгрузка в статье сделана (почти) как в последнем твоем варианте.

И так есть файл на диске, и так есть MapViewOfFile — можно добавить SEC_IMAGE, и выкинуть половину кода Или можно вычитывать файл сразу в образ в памяти, как сделано здесь в load_image.

E>решение простое: VirtualFree( g_hLoadedModule, 0, MEM_DECOMMIT | MEM_RELEASE );

E>я сперва перемудрил немного

MSDN о MEM_RELEASE -

Do not use this value with MEM_DECOMMIT

Возвращаемые API значения не проверяются, поэтому исправление вероятно аналогично

если закоментарить строчку с VirtualFree( g_hLoadedModule, 0, MEM_RELEASE ); тогда все работает

.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[3]: запуск PE (exe) в памяти
От: explorus Россия  
Дата: 02.09.09 18:31
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>А в чём проблема, разобрался? Я сначала подумал, что возникает гонка подобная FreeLibrary & ExitThread, но в коде её не увидел. А про отладчик ты и сам должен знать


ExitProcess не должен возвращаться в тело вызывающего, иначе на висте все падает. Почему до конца не понятно, буду в исходниках Винды ковырять, наверное.

гонка подобная FreeLibrary & ExitThread

— речь про critical section или чего? непонятно, да и потоки я не создаю, и про отладчик... ???

GN>Что не понравилось — VirtualAlloc на каждую секцию PE, на каких-то образах это сработает, на каких-то нет, из-за разной гранулярности VirtualAlloc и выравнивания секций. Ну это, как оказывалось, наследие статьи
Автор(ы): Максим М. Гумеров
Дата: 20.03.2003
Не вдаваясь в подробности, скажу лишь, что исследование было начато ради сокрытия использования программой на Delphi некоей DLL (написанной на VC++). То есть оператор видит один только Exe-файл, запускает его, а тот каким-то образом подключает функции, содержащиеся изначально (при компиляции проекта) в некоторой DLL.
. И выгрузка в статье сделана (почти) как в последнем твоем варианте.


Конструктивная критика всегда принимается!!!
Это тестовое приложение, файл не диска будет грузиться, а по частям в виртуальную память, сперва заголовок, потом все остальное... Про гранулярность не совсем понятно, это что за выравнивание такое должно быть, чтоб VirtualAllloc не сработал, можно примерчик?

GN>И так есть файл на диске, и так есть MapViewOfFile — можно добавить SEC_IMAGE, и выкинуть половину кода


Добавить что, что это? Пля, моя жена щас прочитала весь этот пост, покрутила у виска и поперлась дальше тупить у телика...

GN>Или можно вычитывать файл сразу в образ в памяти, как сделано здесь в load_image.


E>>решение простое: VirtualFree( g_hLoadedModule, 0, MEM_DECOMMIT | MEM_RELEASE );

E>>я сперва перемудрил немного

GN>MSDN о MEM_RELEASE -

Do not use this value with MEM_DECOMMIT

GN>Возвращаемые API значения не проверяются, поэтому исправление вероятно аналогично

если закоментарить строчку с VirtualFree( g_hLoadedModule, 0, MEM_RELEASE ); тогда все работает


Про MEM_DECOMMIT | MEM_RELEASE согласен — тут лажа. Мне нужно обязательно ресурсы высвобождать, поскольку загружаться в памяти должно несколько мелких утилит, и после их работы высвобождать ресурсы.
сырцы обязательно гляну, спасиб
В ближайшее время попробую переделать...
Re[3]: запуск PE (exe) в памяти
От: Аноним  
Дата: 02.09.09 22:51
Оценка:
GN>А в чём проблема, разобрался? Я сначала подумал, что возникает гонка подобная FreeLibrary & ExitThread, но в коде её не увидел. А про отладчик ты и сам должен знать
GN>Что не понравилось — VirtualAlloc на каждую секцию PE, на каких-то образах это сработает, на каких-то нет, из-за разной гранулярности VirtualAlloc и выравнивания секций.
Кроме гранулярности есть еще маленький нередко используемый trick в виде получения базы модуля вызовом VirtualQuery на адрес гдето в его середине. Такими фокусами например даэе занимается делфевая VCL сама по себе.
Re[4]: запуск PE (exe) в памяти
От: Сергей Мухин Россия  
Дата: 03.09.09 03:57
Оценка:
Здравствуйте, Аноним, Вы писали:

GN>>А в чём проблема, разобрался? Я сначала подумал, что возникает гонка подобная FreeLibrary & ExitThread, но в коде её не увидел. А про отладчик ты и сам должен знать

GN>>Что не понравилось — VirtualAlloc на каждую секцию PE, на каких-то образах это сработает, на каких-то нет, из-за разной гранулярности VirtualAlloc и выравнивания секций.
А>Кроме гранулярности есть еще маленький нередко используемый trick в виде получения базы модуля вызовом VirtualQuery на адрес гдето в его середине. Такими фокусами например даэе занимается делфевая VCL сама по себе.

Это чуть ли не официальный способ, в MSDN отражён
---
С уважением,
Сергей Мухин
Re[4]: запуск PE (exe) в памяти
От: Аноним  
Дата: 04.09.09 20:13
Оценка:
Здравствуйте, explorus, Вы писали:

E>В ближайшее время попробую переделать...


кинь сюда код плз когда переделаеш; интересно/
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.