SEH,DEP, Compiler,FS:[0], LOAD_CONFIG and PE format
原贴地址:
http://spaces.msn.com/eparg/blog/cns!59BFC22C0E7E1A76!712.entry
原贴时间:
2006-04-16
原贴作者:
eparg
{
char* pmsg;
public:
ExcepStackMsg(char *msg)
{
pmsg=(char*)malloc(strlen(msg)+1);
strcpy(pmsg,msg);
};
~ExcepStackMsg()
{
if(EXCEPTION)
printf("Exception happens: %s/n",pmsg);
free(pmsg);
};
__cdecl
_except_handler(
struct _EXCEPTION_RECORD *ExceptionRecord,
void * EstablisherFrame,
struct _CONTEXT *ContextRecord,
void * DispatcherContext )
{
EXCEPTION=1;
//printf("got it/n");
return ExceptionContinueSearch; //Allow C++ handler to run
}
void foo1()
{
//printf("in foo1/n");
//ExcepStackMsg e("foo1");
throw 1;
};
void foo2()
{
//printf("in foo2/n");
//ExcepStackMsg e("foo2");
foo1();
};
void foo3()
{
//printf("in foo3/n");
//ExcepStackMsg e("foo3");
foo2();
};
DWORD WINAPI ThreadProc( LPVOID lpParameter)
{
DWORD myESP;
void * test=_except_handler;
DWORD handler = (DWORD)_except_handler;
//_except_handler(0,0,0,0);
printf("1/n");
getchar();
__asm
{
mov myESP,ESP //Save Stack register pointers
push _except_handler // Address of handler function
// push test // Address of handler function
push FS:[0] // Address of previous handler
mov FS:[0],ESP // Install new EXECEPTION_REGISTRATION
// mov FS:[0],100
}
{
printf("2/n");
getchar();
foo3();
}
catch(...)
{
EXCEPTION=0;
printf("catch/n");
};
__asm
{
mov ESP,myESP //Restore Stack register pointers
}
return 0;
}
0012f618 7c8155dc ntdll!RtlImageDirectoryEntryToData+0x57
0012f634 7c815638 ntdll!RtlCaptureImageExceptionValues+0x32
0012f670 7c813fe2 ntdll!RtlLookupFunctionTable+0xd0
0012f6c4 7c8140b3 ntdll!RtlIsValidHandler+0x24
0012f738 7c82ecc6 ntdll!RtlDispatchException+0x78
0012f738 77e55dea ntdll!KiUserExceptionDispatcher+0xe
0012fa90 10243990 kernel32!RaiseException+0x53
0012fad0 0041154c MSVCR80D!_CxxThrowException+0x50
Local var @ 0x12fa6c Type _IMAGE_NT_HEADERS*
0x004000f8
+0x000 Signature : 0x4550
+0x004 FileHeader : _IMAGE_FILE_HEADER
+0x000 Machine : 0x14c
+0x002 NumberOfSections : 4
+0x004 TimeDateStamp : 0x4442f434
+0x008 PointerToSymbolTable : 0
+0x00c NumberOfSymbols : 0
+0x010 SizeOfOptionalHeader : 0xe0
+0x012 Characteristics : 0x103
+0x018 OptionalHeader : _IMAGE_OPTIONAL_HEADER
+0x000 Magic : 0x10b
+0x002 MajorLinkerVersion : 0x8 ''
+0x003 MinorLinkerVersion : 0 ''
+0x004 SizeOfCode : 0xc00
+0x008 SizeOfInitializedData : 0xe00
+0x00c SizeOfUninitializedData : 0
+0x010 AddressOfEntryPoint : 0x1473
+0x014 BaseOfCode : 0x1000
+0x018 BaseOfData : 0x2000
+0x01c ImageBase : 0x400000
+0x020 SectionAlignment : 0x1000
+0x024 FileAlignment : 0x200
+0x028 MajorOperatingSystemVersion : 4
+0x02a MinorOperatingSystemVersion : 0
+0x02c MajorImageVersion : 0
+0x02e MinorImageVersion : 0
+0x030 MajorSubsystemVersion : 4
+0x032 MinorSubsystemVersion : 0
+0x034 Win32VersionValue : 0
+0x038 SizeOfImage : 0x5000
+0x03c SizeOfHeaders : 0x400
+0x040 CheckSum : 0x8862
+0x044 Subsystem : 3
+0x046 DllCharacteristics : 0
+0x048 SizeOfStackReserve : 0x100000
+0x04c SizeOfStackCommit : 0x1000
+0x050 SizeOfHeapReserve : 0x100000
+0x054 SizeOfHeapCommit : 0x1000
+0x058 LoaderFlags : 0
+0x05c NumberOfRvaAndSizes : 0x10
+0x060 DataDirectory :
[00] _IMAGE_DATA_DIRECTORY
+0x000 VirtualAddress : 0
+0x004 Size : 0
[01]
+0x000 VirtualAddress : 0x23a4
+0x004 Size : 0x3c
[02]
+0x000 VirtualAddress : 0x4000
+0x004 Size : 0x1ac
[03]
+0x000 VirtualAddress : 0
+0x004 Size : 0
[04]
+0x000 VirtualAddress : 0
+0x004 Size : 0
[05]
+0x000 VirtualAddress : 0
+0x004 Size : 0
[06]
+0x000 VirtualAddress : 0x20e0
+0x004 Size : 0x1c
[07]
+0x000 VirtualAddress : 0
+0x004 Size : 0
[08]
+0x000 VirtualAddress : 0
+0x004 Size : 0
[09]
+0x000 VirtualAddress : 0
+0x004 Size : 0
[10]
+0x000 VirtualAddress : 0x2148
+0x004 Size : 0x40
[11]
+0x000 VirtualAddress : 0
+0x004 Size : 0
[12]
+0x000 VirtualAddress : 0x2000
+0x004 Size : 0xc4
[13]
+0x000 VirtualAddress : 0
+0x004 Size : 0
[14]
+0x000 VirtualAddress : 0
+0x004 Size : 0
[15]
+0x000 VirtualAddress : 0
+0x004 Size : 0
Dump of file RSE.EXE
Machine: 014C (I386)
Number of Sections: 0004
TimeDateStamp: 4442F434 -> Mon Apr 17 09:49:40 2006
PointerToSymbolTable: 00000000
NumberOfSymbols: 00000000
SizeOfOptionalHeader: 00E0
Characteristics: 0103
RELOCS_STRIPPED
EXECUTABLE_IMAGE
32BIT_MACHINE
Magic 010B
linker version 8.00
size of code C00
size of initialized data E00
size of uninitialized data 0
entrypoint RVA 1473
base of code 1000
base of data 2000
image base 400000
section align 1000
file align 200
required OS version 4.00
image version 0.00
subsystem version 4.00
Win32 Version 0
size of image 5000
size of headers 400
checksum 8862
Subsystem 0003 (Windows character)
DLL flags 0000
stack reserve size 100000
stack commit size 1000
heap reserve size 100000
heap commit size 1000
RVAs & sizes 10
EXPORT rva: 00000000 size: 00000000
IMPORT rva: 000023A4 size: 0000003C
RESOURCE rva: 00004000 size: 000001AC
EXCEPTION rva: 00000000 size: 00000000
SECURITY rva: 00000000 size: 00000000
BASERELOC rva: 00000000 size: 00000000
DEBUG rva: 000020E0 size: 0000001C
ARCHITECTURE rva: 00000000 size: 00000000
GLOBALPTR rva: 00000000 size: 00000000
TLS rva: 00000000 size: 00000000
LOAD_CONFIG rva: 00002148 size: 00000040
BOUND_IMPORT rva: 00000000 size: 00000000
IAT rva: 00002000 size: 000000C4
DELAY_IMPORT rva: 00000000 size: 00000000
COM_DESCRPTR rva: 00000000 size: 00000000
unused rva: 00000000 size: 00000000
Local var @ 0x12f610 Type _IMAGE_NT_HEADERS*
0x004000f0
+0x000 Signature : 0x4550
+0x004 FileHeader : _IMAGE_FILE_HEADER
+0x000 Machine : 0x14c
+0x002 NumberOfSections : 6
+0x004 TimeDateStamp : 0x4442f2da
+0x008 PointerToSymbolTable : 0
+0x00c NumberOfSymbols : 0
+0x010 SizeOfOptionalHeader : 0xe0
+0x012 Characteristics : 0x103
+0x018 OptionalHeader : _IMAGE_OPTIONAL_HEADER
+0x000 Magic : 0x10b
+0x002 MajorLinkerVersion : 0x8 ''
+0x003 MinorLinkerVersion : 0 ''
+0x004 SizeOfCode : 0x5000
+0x008 SizeOfInitializedData : 0x5000
+0x00c SizeOfUninitializedData : 0
+0x010 AddressOfEntryPoint : 0x1108c
+0x014 BaseOfCode : 0x1000
+0x018 BaseOfData : 0x1000
+0x01c ImageBase : 0x400000
+0x020 SectionAlignment : 0x1000
+0x024 FileAlignment : 0x1000
+0x028 MajorOperatingSystemVersion : 4
+0x02a MinorOperatingSystemVersion : 0
+0x02c MajorImageVersion : 0
+0x02e MinorImageVersion : 0
+0x030 MajorSubsystemVersion : 4
+0x032 MinorSubsystemVersion : 0
+0x034 Win32VersionValue : 0
+0x038 SizeOfImage : 0x1b000
+0x03c SizeOfHeaders : 0x1000
+0x040 CheckSum : 0
+0x044 Subsystem : 3
+0x046 DllCharacteristics : 0
+0x048 SizeOfStackReserve : 0x100000
+0x04c SizeOfStackCommit : 0x1000
+0x050 SizeOfHeapReserve : 0x100000
+0x054 SizeOfHeapCommit : 0x1000
+0x058 LoaderFlags : 0
+0x05c NumberOfRvaAndSizes : 0x10
+0x060 DataDirectory :
[00] _IMAGE_DATA_DIRECTORY
+0x000 VirtualAddress : 0
+0x004 Size : 0
[01]
+0x000 VirtualAddress : 0x19000
+0x004 Size : 0x3c
[02]
+0x000 VirtualAddress : 0x1a000
+0x004 Size : 0x459
[03]
+0x000 VirtualAddress : 0
+0x004 Size : 0
[04]
+0x000 VirtualAddress : 0
+0x004 Size : 0
[05]
+0x000 VirtualAddress : 0
+0x004 Size : 0
[06]
+0x000 VirtualAddress : 0x16620
+0x004 Size : 0x1c
[07]
+0x000 VirtualAddress : 0
+0x004 Size : 0
[08]
+0x000 VirtualAddress : 0
+0x004 Size : 0
[09]
+0x000 VirtualAddress : 0
+0x004 Size : 0
[10]
+0x000 VirtualAddress : 0
+0x004 Size : 0
[11]
+0x000 VirtualAddress : 0
+0x004 Size : 0
[12]
+0x000 VirtualAddress : 0x191cc
+0x004 Size : 0x190
[13]
+0x000 VirtualAddress : 0
+0x004 Size : 0
[14]
+0x000 VirtualAddress : 0
+0x004 Size : 0
[15]
+0x000 VirtualAddress : 0
+0x004 Size : 0
Machine: 014C (I386)
Number of Sections: 0006
TimeDateStamp: 4442F2DA -> Mon Apr 17 09:43:54 2006
PointerToSymbolTable: 00000000
NumberOfSymbols: 00000000
SizeOfOptionalHeader: 00E0
Characteristics: 0103
RELOCS_STRIPPED
EXECUTABLE_IMAGE
32BIT_MACHINE
Magic 010B
linker version 8.00
size of code 5000
size of initialized data 5000
size of uninitialized data 0
entrypoint RVA 1108C
base of code 1000
base of data 1000
image base 400000
section align 1000
file align 1000
required OS version 4.00
image version 0.00
subsystem version 4.00
Win32 Version 0
size of image 1B000
size of headers 1000
checksum 0
Subsystem 0003 (Windows character)
DLL flags 0000
stack reserve size 100000
stack commit size 1000
heap reserve size 100000
heap commit size 1000
RVAs & sizes 10
EXPORT rva: 00000000 size: 00000000
IMPORT rva: 00019000 size: 0000003C
RESOURCE rva: 0001A000 size: 00000459
EXCEPTION rva: 00000000 size: 00000000
SECURITY rva: 00000000 size: 00000000
BASERELOC rva: 00000000 size: 00000000
DEBUG rva: 00016620 size: 0000001C
ARCHITECTURE rva: 00000000 size: 00000000
GLOBALPTR rva: 00000000 size: 00000000
TLS rva: 00000000 size: 00000000
LOAD_CONFIG rva: 00000000 size: 00000000
BOUND_IMPORT rva: 00000000 size: 00000000
IAT rva: 000191CC size: 00000190
DELAY_IMPORT rva: 00000000 size: 00000000
COM_DESCRPTR rva: 00000000 size: 00000000
unused rva: 00000000 size: 00000000
my guess is:
it actually relate with safe exception handlers. compiler/linker generated handlers, new MS C compiler will add security cookie to ensure the stack is ok when invoke exception handler, the corresponding RVA is added to the look up table. so manually embedded assembler seh handler won't appear in the table,
os will consider it's an invalid handler.
a workaround is to sweep the load config directory in PE image, dynamically programming...
modify image file as your own exe name.
// =========================================================================
HMODULE h = GetModuleHandle(L"exchain.exe");
PUCHAR Base = (PUCHAR)h;
ULONG OldProtect;
VirtualProtect(Base, 0x1000, PAGE_READWRITE, &OldProtect);
IMAGE_NT_HEADERS *NtHeader = ImageNtHeader(Base);
NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress = 0;
NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size = 0;
VirtualProtect(Base, 0x1000, PAGE_READONLY, &OldProtect);
//
Basically, you're running afowl of /SafeSEH. /SafeSEH is incompatable with incremental linking, so it is probably disabled in debug builds.
What /SafeSEH is designed to do is prevent a buffer overrun (or other exploitable code) from overwriting the exception handler on the stack and point it at the hacker's code. The way they do this is at compile time, a list of all valid exception handlers is built up, and at runtime, before a handler is called, it is checked to see if it is on the list. [The loadconfig structure you find gives that list, and a bit in the header says whether the binary was built with /SafeSEH or not.]
If your ASM code was in an .asm file, then you'd use the .safeseh directive to tell the assembler (and hence, the linker), that this function is an exception handler function. I don't know any mechansim in inline asm that will achieve the same effect.
If you compile with warnings enabled, you get warning C4733 telling you that you're going to explode at runtime.