I'm looking for the information about COM_DESCRIPTOR directory in PE files. What is it and what is it used for? I've read the structure of PE-files and still don't understand what is COM_DESCRIPTOR.
Thanks!
"COM Descriptor Directory" in PE Header is also known as "CLR Header". It is only present in Managed PE Images (created with C# and other Dot Net compilers). You can dump content of this directory with DumpBin /CLRHRADER option. For example:
DumBin /CLRHEADER someapp.exe
clr Header:
48 cb
2.05 runtime version
30C4 [ 1DEC] RVA [size] of MetaData Directory
1 flags
IL Only
6000004 entry point token
4EB0 [ 2560] RVA [size] of Resources Directory
0 [ 0] RVA [size] of StrongNameSignature Directory
0 [ 0] RVA [size] of CodeManagerTable Directory
0 [ 0] RVA [size] of VTableFixups Directory
0 [ 0] RVA [size] of ExportAddressTableJumps Directory
0 [ 0] RVA [size] of ManagedNativeHeader Directory
RVA in this directory entry points to IMAGE_COR20_HEADER defined in WinNt.h. It is also defined in CorHdr.h :
typedef struct IMAGE_COR20_HEADER
{
// Header versioning
DWORD cb;
WORD MajorRuntimeVersion;
WORD MinorRuntimeVersion;
// Symbol table and startup information
IMAGE_DATA_DIRECTORY MetaData;
DWORD Flags;
// The main program if it is an EXE (not used if a DLL?)
// If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is not set, EntryPointToken represents a managed entrypoint.
// If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is set, EntryPointRVA represents an RVA to a native entrypoint
// (depricated for DLLs, use modules constructors intead).
union {
DWORD EntryPointToken;
DWORD EntryPointRVA;
};
// This is the blob of managed resources. Fetched using code:AssemblyNative.GetResource and
// code:PEFile.GetResource and accessible from managed code from
// System.Assembly.GetManifestResourceStream. The meta data has a table that maps names to offsets into
// this blob, so logically the blob is a set of resources.
IMAGE_DATA_DIRECTORY Resources;
// IL assemblies can be signed with a public-private key to validate who created it. The signature goes
// here if this feature is used.
IMAGE_DATA_DIRECTORY StrongNameSignature;
IMAGE_DATA_DIRECTORY CodeManagerTable; // Depricated, not used
// Used for manged codee that has unmaanaged code inside it (or exports methods as unmanaged entry points)
IMAGE_DATA_DIRECTORY VTableFixups;
IMAGE_DATA_DIRECTORY ExportAddressTableJumps;
// null for ordinary IL images. NGEN images it points at a code:CORCOMPILE_HEADER structure
IMAGE_DATA_DIRECTORY ManagedNativeHeader;
} IMAGE_COR20_HEADER, *PIMAGE_COR20_HEADER;
Related
When I call memmap in the UEFI shell, I got two different attributes like the following:
Shell> memmap
Type Start End # Pages Attributes
Available 0000000080000000-00000000CFFFFFFF 0000000000050000 000000000000000E
Available 0000002000000000-000000237FFFFFFF 0000000000380000 000000000000000F
The problem is that I cannot use the second region of memory whose attribute marks as 000000000000000F. I've already registered that part of memory to my page table. But, my OS will panic when I convert a physical address from that region to a virtual address.
So, my problem is:
What does the attribute means?
How can I change the attribute so that I can use that part of memory?
The memmap command displays the memory map that is maintained by the UEFI environment by listing the contents of EFI_MEMORY_DESCRIPTOR for each memory region.
typedef struct {
UINT32 Type;
EFI_PHYSICAL_ADDRESS PhysicalStart;
EFI_VIRTUAL_ADDRESS VirtualStart;
UINT64 NumberOfPages;
UINT64 Attribute;
} EFI_MEMORY_DESCRIPTOR;
The Attribute field of a memory region describes the bit mask of capabilities for that memory region, and not necessarily the current settings for that memory region.
//*******************************************************
// Memory Attribute Definitions
//*******************************************************
// These types can be “ORed” together as needed.
#define EFI_MEMORY_UC 0x0000000000000001
#define EFI_MEMORY_WC 0x0000000000000002
#define EFI_MEMORY_WT 0x0000000000000004
#define EFI_MEMORY_WB 0x0000000000000008
#define EFI_MEMORY_UCE 0x0000000000000010
#define EFI_MEMORY_WP 0x0000000000001000
#define EFI_MEMORY_RP 0x0000000000002000
#define EFI_MEMORY_XP 0x0000000000004000
#define EFI_MEMORY_NV 0x0000000000008000
#define EFI_MEMORY_MORE_RELIABLE 0x0000000000010000
#define EFI_MEMORY_RO 0x0000000000020000
#define EFI_MEMORY_SP 0x0000000000040000
#define EFI_MEMORY_CPU_CRYPTO 0x0000000000080000
#define EFI_MEMORY_RUNTIME 0x8000000000000000
Full details about each of these attributes can be found in the UEFI Specification Section 7.2 under GetMemoryMap.
The only difference in attribute value between your two memory regions is EFI_MEMORY_UC, i.e. memory is not cacheable.
I am trying to put together and example of coding inline assembly code in a 'C' program. I have not had any success. I am using GCC 4.9.0. As near as I can tell my syntax is correct. However the build blows up with the following errors:
/tmp/ccqC2wtq.s:48: Error: syntax error; found `(', expected `,'
Makefile:51: recipe for target 'all' failed
/tmp/ccqC2wtq.s:48: Error: junk at end of line: `(31)'
/tmp/ccqC2wtq.s:49: Error: syntax error; found `(', expected `,'
/tmp/ccqC2wtq.s:49: Error: junk at end of line: `(9)'
These are related to the input/output/clobbers lines in the code. Anyone have an idea where I went wrong?
asm volatile("li 7, %0\n" // load destination address
"li 8, %1\n" // load source address
"li 9, 100\n" // load count
// save source address for return
"mr 3,7\n"
// prepare for loop
"subi 8,8,1\n"
"subi 9,9,1\n"
// perform copy
"1:\n"
"lbzu 10,2(8)\n"
"stbu 10,2(7)\n"
"subi 9,9,1\n" // Decrement the count
"bne 1b\n" // If zero, we've finished
"blr\n"
: // no outputs
: "m" (array), "m" (stringArray)
: "r7", "r8"
);
It's not clear what you are trying to do with the initial instructions:
li 7, %0
li 8, %1
Do you want to load the address of the variables into those registers? In general, this is not possible because the address is not representable in an immediate operand. The easiest way out is to avoid using r7 and r8, and instead use %0 and %1 directly as the register names. It seems that you want to use these registers as base addresses, so you should use the b constraint:
: "b" (array), "b" (stringArray)
Then GCC will take care of the details of materializing the address in a suitable fashion.
You cannot return using blr from inline assembler because it's not possible to tear down the stack frame GCC created. You also need to double-check the clobbers and make sure that you list all the things you clobber (including condition codes, memory, and overwritten input operands).
I was able to get this working by declaring a pair of pointers and initializing them with the addresses of the arrays. I didn't realize that the addresses wouldn't be available directly. I've used inline assembly very sparsely in the past, usually just
to raise or lower interrupt masks, not to do anything that references variables. I just
had some folks who wanted an example. And the "blr" was leftover when I copied a
snipet of a pure assembly routine to use as a starting point. Thanks for the responses.
The final code piece looks like this:
int main()
{
char * stringArrayPtr;
unsigned char * myArrayPtr;
unsigned char myArray[100];
stringArrayPtr = (char *)&stringArray;
myArrayPtr = myArray;
asm volatile(
"lwz 7,%[myArrayPtr]\n" // load destination address
"lwz 8, %[stringArrayPtr]\n" // load source address
"li 9, 100\n" // load count
"mr 3,7\n" // save source address for return
"subi 8,8,1\n" // prepare for loop
"subi 9,9,1\n"
"1:\n" // perform copy
"lbzu 10,1(8)\n"
"stbu 10,1(7)\n"
"subic. 9,9,1\n" // Decrement the count
"bne 1b\n" // If zero, we've finished
// The outputs / inputs / clobbered list
// No output variables are specified here
// See GCC documentation on extended assembly for details.
:
: [stringArrayPtr] "m" (stringArrayPtr), [myArrayPtr]"m"(myArrayPtr)
: "7","8","9","10"
);
}
I'm trying to understand the following symbol dump from the LLDB shell
(lldb) target create --no-dependents '9.0/Symbols/Library/Application Support/WatchKit/WK'
Current executable set to '9.0/Symbols/Library/Application Support/WatchKit/WK' (armv7k).
(lldb) image list
[ 0] 675ED1EB-BAA0-3453-B7B1-3E69310F40FD 0x00004000 9.0/Symbols/Library/Application Support/WatchKit/WK
(lldb) image dump symtab
Dumping symbol table for 1 modules.
Symtab, file = 9.0/Symbols/Library/Application Support/WatchKit/WK, num_symbols = 6:
Debug symbol
|Synthetic symbol
||Externally Visible
|||
Index UserID DSX Type File Address/Value Load Address Size Flags Name
------- ------ --- --------------- ------------------ ------------------ ------------------ ---------- ----------------------------------
[ 0] 0 Code 0x0000000000007fcc 0x0000000000000030 0x001e0000 stub helpers
[ 1] 1 X Data 0x0000000000004000 0x0000000000003fcc 0x000f0010 _mh_execute_header
[ 2] 2 X ReExported 0x000b0000 main -> /System/Library/PrivateFrameworks/SockPuppetGizmo.framework/SockPuppetGizmo`_SPApplicationMain
[ 3] 3 X Undefined 0x0000000000000000 0x0000000000000000 0x00010100 _SPApplicationMain
[ 4] 4 X Undefined 0x0000000000000000 0x0000000000000000 0x00010500 dyld_stub_binder
[ 5] 5 S Trampoline 0x0000000000007ffc 0x0000000000000004 0x00000000 main
Most of it I can kinda understand because there are addresses and sizes associated with the symbol but some of them I don't understand. In this case there are 2 "undefined" symbols with 0x00 for the address and 0x00 for the size. My question is what do those symbols mean? Does that mean they are resolved at runtime and I really shouldn't be concerned about them when trying to make sense of things in crash logs?
Your guess is correct, Undefined symbols are symbols that one binary wants to use from some other binary. They will get fixed up by the loader when your program runs.
So for instance, if you write the standard "hello world" program, the main binary will have an Undefined symbol for "printf". BTW, these are the same as the symbols of type U that you see in the output of nm.
What exactly do the BLOCK and ALIGN commands do in a linker script? The names seem to speak for themselves; but, I don't see exactly how they are affecting the resulting OS image.
The linker script below is based on the example given by the OSDev Bare Bones example (http://wiki.osdev.org/Bare_Bones).
(1) In the resulting image, the .rodata section begins at address 0x1400, and the .data section begins at 0x2400. Shouldn't the BLOCK(4K) command place .rodata at 0x1000 (or some other multiple of 4KB)?
(2) What does ALIGN(4K) do? The documentation (https://www.math.utah.edu/docs/info/ld_3.html) indicates that it is just a calculation that returns the current location adjusted to the nearest 4K boundary. However, the documentation for SECTION doesn't indicate a place for a parameter after the colon (other than an AT command, which isn't present here).
(3) In either case, why have both BLOCK and ALIGN?
SECTIONS
{
. = 0x7c00;
__start = .;
.text :
{
*(.boot)
/*
Magic bytes. 0x1FE == 510.
We could add this on each Gas file separately with `.word`,
but this is the perfect place to DRY that out.
*/
. = 0x1FE;
SHORT(0xAA55)
/*
This is only needed if we are going to use a 2 stage boot process,
e.g. by reading more disk than the default 512 bytes with BIOS `int 0x13`.
*/
*(.stage2)
*(.text)
}
/* Read-only data. */
.rodata BLOCK(4K) : ALIGN(4K)
{
LONG(0x11223344) /* just a marker so I can see where the linker places this section */
*(.rodata)
}
/* Read-write data (initialized) */
.data BLOCK(4K) : ALIGN(4K)
{
LONG(0x44332211)
*(.data)
}
I read in Windows Internals that when a thread is created, by default 1 MB of virtual memory is reserved for the user stack. Out of this 1 MB, only the first page (0x1000) will be committed.
I can see this when i dump the image header using dumpbin.exe. Here is what dumpbin shows:
However when i dump the address space of this exe in Windbg using !address command, I see a difference. Windbg shows me that the initial committed size is equal to 3 pages i.e 0x3000
Does anyone know why there is a difference between the initial stack commit size that the image header and debugger shows?
That's a nice question and the key to the answer is understanding what the initial breakpoint is. How initial is it, for starters?
TLDR: The initial breakpoint it too late. That stack has already grown.
You haven't shared the binary you're dealing with, so I chose a binary that exhibits the same behaviour - cacls.exe on 64-bit Windows 10 (file version: 10.0.14393.0).
During the initial breakpoint we observe:
CommandLine: "c:\Windows\System32\cacls.exe"
Symbol search path is: srv*
Executable search path is:
ModLoad: 00007ff6`83bd0000 00007ff6`83bdc000 cacls.exe
ModLoad: 00007ff8`29ce0000 00007ff8`29eb1000 ntdll.dll
ModLoad: 00007ff8`27500000 00007ff8`275ab000 C:\Windows\System32\KERNEL32.DLL
ModLoad: 00007ff8`26f30000 00007ff8`2714d000 C:\Windows\System32\KERNELBASE.dll
ModLoad: 00007ff8`280b0000 00007ff8`2814e000 C:\Windows\System32\msvcrt.dll
ModLoad: 00007ff8`29b10000 00007ff8`29bb2000 C:\Windows\System32\advapi32.dll
ModLoad: 00007ff8`273d0000 00007ff8`27429000 C:\Windows\System32\sechost.dll
ModLoad: 00007ff8`254f0000 00007ff8`25522000 c:\Windows\System32\NTMARTA.dll
ModLoad: 00007ff8`27150000 00007ff8`27245000 C:\Windows\System32\ucrtbase.dll
ModLoad: 00007ff8`277c0000 00007ff8`278e1000 C:\Windows\System32\RPCRT4.dll
(1310.17b0): Break instruction exception - code 80000003 (first chance)
ntdll!LdrpDoDebuggerBreak+0x30:
00007ff8`29db34e0 cc int 3
0:000> !dh -f cacls
File Type: EXECUTABLE IMAGE
FILE HEADER VALUES
8664 machine (X64)
6 number of sections
57899A04 time date stamp Sat Jul 16 05:20:52 2016
0 file pointer to symbol table
0 number of symbols
F0 size of optional header
22 characteristics
Executable
App can handle >2gb addresses
OPTIONAL HEADER VALUES
20B magic #
14.00 linker version
4C00 size of code
3600 size of initialized data
0 size of uninitialized data
52F0 address of entry point
1000 base of code
----- new -----
00007ff683bd0000 image base
1000 section alignment
200 file alignment
3 subsystem (Windows CUI)
10.00 operating system version
10.00 image version
10.00 subsystem version
C000 size of image
400 size of headers
AF10 checksum
0000000000080000 size of stack reserve
0000000000002000 size of stack commit
0000000000100000 size of heap reserve
0000000000001000 size of heap commit
C160 DLL characteristics
High entropy VA supported
Dynamic base
NX compatible
Guard
Terminal server aware
0 [ 0] address [size] of Export Directory
7010 [ 1CC] address [size] of Import Directory
A000 [ 7F0] address [size] of Resource Directory
9000 [ 2DC] address [size] of Exception Directory
0 [ 0] address [size] of Security Directory
B000 [ 54] address [size] of Base Relocation Directory
6A10 [ 38] address [size] of Debug Directory
0 [ 0] address [size] of Description Directory
0 [ 0] address [size] of Special Directory
0 [ 0] address [size] of Thread Storage Directory
60E0 [ D0] address [size] of Load Configuration Directory
0 [ 0] address [size] of Bound Import Directory
61B0 [ 3B8] address [size] of Import Address Table Directory
0 [ 0] address [size] of Delay Import Directory
0 [ 0] address [size] of COR20 Header Directory
0 [ 0] address [size] of Reserved Directory
0:000> !address #rsp
Mapping file section regions...
Mapping module regions...
Mapping PEB regions...
Mapping TEB and stack regions...
Mapping heap regions...
Mapping page heap regions...
Mapping other regions...
Mapping stack trace database regions...
Mapping activation context regions...
Usage: Stack
Base Address: 00000049`8fbbc000
End Address: 00000049`8fbc0000
Region Size: 00000000`00004000 ( 16.000 kB)
State: 00001000 MEM_COMMIT
Protect: 00000004 PAGE_READWRITE
Type: 00020000 MEM_PRIVATE
Allocation Base: 00000049`8fb40000
Allocation Protect: 00000004 PAGE_READWRITE
More info: ~0k
Content source: 1 (target), length: 180
We see the initial stack commit size is 0x2000, but 0x4000 is actually committed.
But that's already very late during the process initialization process (no pun intended). All the import DLL are already loaded, for example.
The so-called "initial break-point" is simply a (more or less1) hardcoded int 3 instruction called by the process initializtion code in NTDLL. If you look at the stack at this point you'll see the aptly named LdrpDoDebuggerBreak function which is called by LdrpInitializeProcess:
0:000> k
# Child-SP RetAddr Call Site
00 00000049`8fbbee80 00007ff8`29d72e22 ntdll!LdrpDoDebuggerBreak+0x30
01 00000049`8fbbeec0 00007ff8`29da8986 ntdll!LdrpInitializeProcess+0x1962
02 00000049`8fbbf2c0 00007ff8`29d59fae ntdll!_LdrpInitialize+0x4e982
03 00000049`8fbbf340 00000000`00000000 ntdll!LdrInitializeThunk+0xe
By the time that happened the stack has already been used (for example, to load statically linked DLLs and perform their initialization code), so it shouldn't be much surprise that the stack has grown already.
To examine the process when it has just been created we need to break on the process creation event rather than on the initial breakpoint (which isn't that initial as we now understand).
We can do that either using sxe cpr and .restarting like I did or running WinDbg/NTSD with -xe cpr. Doing that reveals something interesting2:
0:000> .restart
CommandLine: C:\Windows\System32\cacls.exe
************* Symbol Path validation summary **************
Response Time (ms) Location
Deferred srv*
Symbol search path is: srv*
Executable search path is:
ModLoad: 00007ff6`83bd0000 00007ff6`83bdc000 cacls.exe
00007ff8`29d470b0 4883ec48 sub rsp,48h
0:000> .imgscan /l
MZ at 00007ff6`83bd0000, prot 00000002, type 01000000 - size c000
Name: cacls.exe
Loaded cacls.exe module
MZ at 00007ff8`29ce0000, prot 00000002, type 01000000 - size 1d1000
Name: ntdll.dll
Loaded ntdll.dll module
0:000> !address #rsp
Mapping file section regions...
Mapping module regions...
Mapping PEB regions...
Mapping TEB and stack regions...
Mapping heap regions...
Mapping page heap regions...
Mapping other regions...
Mapping stack trace database regions...
Mapping activation context regions...
Usage: Stack
Base Address: 0000004a`5428e000
End Address: 0000004a`54290000
Region Size: 00000000`00002000 ( 8.000 kB)
State: 00001000 MEM_COMMIT
Protect: 00000004 PAGE_READWRITE
Type: 00020000 MEM_PRIVATE
Allocation Base: 0000004a`54210000
Allocation Protect: 00000004 PAGE_READWRITE
More info: ~0k
Content source: 1 (target), length: 478
The committed region size is 0x2000 - like the header says!
If we let it continue we'll eventually get to the initial breakpoint with more stack comitted.
1I said more or less hardcoded because the actual code of the function is
0:000> uf ntdll!LdrpDoDebuggerBreak
ntdll!LdrpDoDebuggerBreak:
00007ff8`29db34b0 4883ec38 sub rsp,38h
00007ff8`29db34b4 488364242000 and qword ptr [rsp+20h],0
00007ff8`29db34ba 41b901000000 mov r9d,1
00007ff8`29db34c0 4c8d442440 lea r8,[rsp+40h]
00007ff8`29db34c5 418d5110 lea edx,[r9+10h]
00007ff8`29db34c9 48c7c1feffffff mov rcx,0FFFFFFFFFFFFFFFEh
00007ff8`29db34d0 e88b30fdff call ntdll!NtQueryInformationThread (00007ff8`29d86560)
00007ff8`29db34d5 85c0 test eax,eax
00007ff8`29db34d7 780a js ntdll!LdrpDoDebuggerBreak+0x33 (00007ff8`29db34e3) Branch
ntdll!LdrpDoDebuggerBreak+0x29:
00007ff8`29db34d9 807c244000 cmp byte ptr [rsp+40h],0
00007ff8`29db34de 7503 jne ntdll!LdrpDoDebuggerBreak+0x33 (00007ff8`29db34e3) Branch
ntdll!LdrpDoDebuggerBreak+0x30:
00007ff8`29db34e0 cc int 3
00007ff8`29db34e1 eb00 jmp ntdll!LdrpDoDebuggerBreak+0x33 (00007ff8`29db34e3) Branch
ntdll!LdrpDoDebuggerBreak+0x33:
00007ff8`29db34e3 4883c438 add rsp,38h
00007ff8`29db34e7 c3 ret
It does stuff like checking whether or not this thread is to be "hidden from the debugger", but basically it just breaks into the debugger.
2The .imgscan /l is needed because without it we get:
0:000> !address #rsp
No symbols for ntdll. Cannot continue.