|
|
#include "stdinc.h"
static const char File[] = __FILE__; #include "delayload_tool.h"
#include "fusionstring.h"
#include "setfilepointerex.c"
#include "getfilesizeex.c"
#include <assert.h>
#include "delayimp.h"
#include "imagehlp.h"
#define BITS_OF(x) (sizeof(x) * 8)
String_t GetErrorString(DWORD Error);
//
// delayimp.h doesn't work when tool bitness != image bitness
//
typedef ULONG32 PImgThunkData32; typedef ULONG32 PCImgThunkData32; typedef ULONG32 LPCSTR32; typedef ULONG32 PHMODULE32; typedef ULONG64 PImgThunkData64; typedef ULONG64 PCImgThunkData64; typedef ULONG64 LPCSTR64; typedef ULONG64 PHMODULE64;
typedef struct ImgDelayDescrV1_32 { DWORD grAttrs; // attributes
LPCSTR32 szName; // pointer to dll name
PHMODULE32 phmod; // address of module handle
PImgThunkData32 pIAT; // address of the IAT
PCImgThunkData32 pINT; // address of the INT
PCImgThunkData32 pBoundIAT; // address of the optional bound IAT
PCImgThunkData32 pUnloadIAT; // address of optional copy of original IAT
DWORD dwTimeStamp; // 0 if not bound,
// O.W. date/time stamp of DLL bound to (Old BIND)
} ImgDelayDescrV1_32, * PImgDelayDescrV1_32;
typedef struct ImgDelayDescrV1_64 { DWORD grAttrs; // attributes
LPCSTR64 szName; // pointer to dll name
PHMODULE64 phmod; // address of module handle
PImgThunkData64 pIAT; // address of the IAT
PCImgThunkData64 pINT; // address of the INT
PCImgThunkData64 pBoundIAT; // address of the optional bound IAT
PCImgThunkData64 pUnloadIAT; // address of optional copy of original IAT
DWORD dwTimeStamp; // 0 if not bound,
// O.W. date/time stamp of DLL bound to (Old BIND)
} ImgDelayDescrV1_64, * PImgDelayDescrV1_64;
//
// get msvcrt.dll wildcard processing on the command line
//
extern "C" { int _dowildcard = 1; }
void Spinner() { static char s[] = "-\\|/"; static unsigned i;
fprintf(stderr, "%c\r", s[i++ % (sizeof(s) - 1)]); }
void Throw(PCWSTR s) { if (::IsDebuggerPresent()) { DbgPrint("Throw(%ls)\n", s); DebugBreak(); } throw (s); }
void F::ThrowHresult(HRESULT hr) { if (::IsDebuggerPresent()) { DbgPrint("ThrowHresult:0x%lx|%ld|%ls\n", hr, (hr & 0xffff), GetErrorString(hr).c_str()); DebugBreak(); } throw (hr); }
void ThrowLastWin32Error() { DWORD dw = GetLastError(); if (::IsDebuggerPresent()) { DbgPrint("ThrowLastWin32Error:0x%lx|%ld|%ls\n", dw, dw, GetErrorString(dw).c_str()); DebugBreak(); } throw (dw); }
void CollectDirectoryPathsNonRecursively( const String_t& directory, StringVector_t& paths ) { WIN32_FIND_DATAW wfd; DFindFile FindFile; HRESULT hr = 0; String_t directory_slash_star = directory + L"\\*";
if (FAILED(hr = FindFile.HrCreate(directory_slash_star, &wfd))) { FindFirstFileError_t err; err.m_hresult = hr; err.m_dwLastError = GetLastError(); std::swap(err.m_strParameter, directory_slash_star); throw err; } directory_slash_star.clear(); do { if (FusionpIsDotOrDotDot(wfd.cFileName)) { continue; } if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { paths.insert(paths.end(), directory + L"\\" + wfd.cFileName); } } while (::FindNextFileW(FindFile, &wfd)); }
typedef BOOL (CALLBACK * PFN_COLLECTION_FILE_PATHS_RECURSIVELY_FILTER)(PVOID FilterContext, PCWSTR Directory, WIN32_FIND_DATAW * wfd);
void CollectFilePathsRecursivelyHelper( const String_t& directory, StringVector_t& paths, PFN_COLLECTION_FILE_PATHS_RECURSIVELY_FILTER Filter, PVOID FilterContext, WIN32_FIND_DATAW& wfd ) { DFindFile FindFile; HRESULT hr = 0; String_t directory_slash_star = directory + L"\\*";
if (FAILED(hr = FindFile.HrCreate(directory_slash_star, &wfd))) { FindFirstFileError_t err; err.m_hresult = hr; err.m_dwLastError = GetLastError(); std::swap(err.m_strParameter, directory_slash_star); throw err; } directory_slash_star.clear(); do { if (FusionpIsDotOrDotDot(wfd.cFileName)) { continue; } if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { if (Filter == NULL || (*Filter)(FilterContext, directory, &wfd)) { CollectFilePathsRecursivelyHelper(directory + L"\\" + wfd.cFileName, paths, Filter, FilterContext, wfd); } } else { if (Filter == NULL || (*Filter)(FilterContext, directory, &wfd)) { paths.insert(paths.end(), directory + L"\\" + wfd.cFileName); } } } while (::FindNextFileW(FindFile, &wfd)); }
void CollectFilePathsRecursively( const String_t& directory, StringVector_t& paths, PFN_COLLECTION_FILE_PATHS_RECURSIVELY_FILTER Filter, PVOID FilterContext ) { WIN32_FIND_DATAW wfd;
CollectFilePathsRecursivelyHelper(directory, paths, Filter, FilterContext, wfd); }
void DelayloadToolAssertFailed(const char* Expression, const char* File, unsigned long Line) { fprintf(stderr, "ASSERTION FAILURE: File %s, Line %lu, Expression %s\n", File, Line, Expression); abort(); }
void DelayloadToolInternalErrorCheckFailed(const char* Expression, const char* File, unsigned long Line) { fprintf(stderr, "INTERNAL ERROR: File %s, Line %lu, Expression %s\n", File, Line, Expression); abort(); }
String_t NumberToString(ULONG Number, PCWSTR Format) { // the size needed is really dependent on Format..
WCHAR NumberAsString[BITS_OF(Number) + 5];
_snwprintf(NumberAsString, NUMBER_OF(NumberAsString), Format, Number); NumberAsString[NUMBER_OF(NumberAsString) - 1] = 0;
return NumberAsString; }
String_t GetErrorString(DWORD Error) { PWSTR s = NULL; String_t ErrorString = NumberToString(Error, L"%lu"); PWSTR FormatMessageAllocatedBuffer = NULL;
if (!FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, Error, 0, reinterpret_cast<PWSTR>(&FormatMessageAllocatedBuffer), 100, NULL ) || FormatMessageAllocatedBuffer == NULL ) { goto Exit; } if (FormatMessageAllocatedBuffer[0] == 0) { goto Exit; }
//
// Error messages often end with vertical whitespce, remove it.
//
s = FormatMessageAllocatedBuffer + StringLength(FormatMessageAllocatedBuffer) - 1; while (s != FormatMessageAllocatedBuffer && (*s == '\n' || *s == '\r')) *s-- = 0; ErrorString = ErrorString + L" (" + FormatMessageAllocatedBuffer + L")"; Exit: LocalFree(FormatMessageAllocatedBuffer); return ErrorString; }
String_t GetLastErrorString() { return GetErrorString(GetLastError()); }
String_t RemoveOptionChar(const String_t& s) { if (s.Length() != 0) { if (s[0] == '-') return s.substr(1); else if (s[0] == '/') return s.substr(1); else if (s[0] == ':') // hacky..
return s.substr(1); else if (s[0] == '=') // hacky..
return s.substr(1); } return s; }
void __cdecl Error(const wchar_t* s, ...) { printf("%s\n", s); exit(EXIT_FAILURE); }
String_t GetEnv(PCWSTR Name) { DWORD LengthIn = 64; DWORD LengthOut = 0; std::vector<WCHAR> Buffer;
while (true) { Buffer.resize(LengthIn); Buffer[0] = 0; LengthOut = GetEnvironmentVariableW(Name, &Buffer[0], LengthIn); if (LengthOut < LengthIn) { break; } LengthIn = 1 + std::max(2 * LengthIn, LengthOut); } return &Buffer[0]; }
String_t FindLatestReleaseOnServer(const String_t& Server) { StringVector_t Releases; String_t ServerRelease;
ServerRelease += L"\\\\"; ServerRelease += Server; ServerRelease += L"\\release";
CollectDirectoryPathsNonRecursively(ServerRelease, Releases); std::sort(Releases.begin(), Releases.end()); return Releases.back(); }
BOOL DelayloadTool_Filter(PVOID FilterContext, PCWSTR Directory, WIN32_FIND_DATAW * wfd) { const static UNICODE_STRING directoriesToIgnore[] = { #define X(x) RTL_CONSTANT_STRING(x)
X(L"pro"), X(L"srv"), X(L"ads"), X(L"dtc"), X(L"bla"), X(L"per"), X(L"sbs"), X(L"proinf"), X(L"srvinf"), X(L"adsinf"), X(L"dtcinf"), X(L"blainf"), X(L"perinf"), X(L"procd1"), X(L"procd2"), X(L"ifs_cd"), X(L"symbols"), X(L"ifs_flat"), X(L"build_logs"), X(L"symbols.pri"), X(L"processor_cd"), X(L"processor_flat"), X(L"asmscab"), X(L"ddk_flat"), X(L"scp_wpa"), X(L"hu"), X(L"ara"), X(L"br"), X(L"chs"), X(L"cht"), X(L"cs"), X(L"da"), X(L"el"), X(L"es"), X(L"euq"), X(L"fi"), X(L"fr"), X(L"ger"), X(L"heb"), X(L"hun"), X(L"it"), X(L"jpn"), X(L"kor"), X(L"nl"), X(L"no"), X(L"pl"), X(L"pt"), X(L"ru"), X(L"sky"), X(L"slv"), X(L"sv"), X(L"tr"), X(L"usa"), X(L"congeal_scripts"), X(L"lanman"), X(L"dos"), X(L"lanman.os2"), X(L"tcp32wfw"), X(L"update.wfw"), X(L"msclient"), X(L"bootfloppy"), X(L"opk"), X(L"winpe"), X(L"presign"), X(L"prerebase"), }; const static UNICODE_STRING extensionsToIgnore[] = { X(L"txt"), X(L"htm"), X(L"gif"), X(L"bmp"), X(L"pdb"), X(L"inf"), X(L"sif"), X(L"pnf"), X(L"png"), X(L"sys"), X(L"ttf"), X(L"vbs"), X(L"hlp"), X(L"ini"), X(L"cat"), X(L"cab"), X(L"nls"), X(L"gpd"), X(L"chm"), X(L"cur"), X(L"jpg"), X(L"cer"), X(L"ani"), X(L"fon"), X(L"css"), X(L"hash"), X(L"lst"), X(L"icm"), X(L"msg"), X(L"386"), X(L"ico"), X(L"dos"), X(L"asp"), X(L"sld"), X(L"pif"), X(L"cnt"), X(L"mof"), X(L"man"), X(L"msm"), X(L"cdf"), X(L"img"), X(L"doc"), X(L"dns"), X(L"cpx"), X(L"mib"), X(L"ppd") X(L"map"), X(L"sym") #undef X
};
CUnicodeString cFileName(wfd->cFileName); SIZE_T i;
if ((wfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { Spinner(); //fprintf(stderr, "%wZ\n", &cFileName);
for (i = 0 ; i != RTL_NUMBER_OF(directoriesToIgnore) ; ++i) { if (FusionpEqualStringsI(&directoriesToIgnore[i], &cFileName)) return FALSE; } } else { PCWSTR dot; if (RTL_STRING_GET_LAST_CHAR(&cFileName) == L'_') return FALSE; if (RTL_STRING_GET_LAST_CHAR(&cFileName) == L'$') return FALSE; dot = wcsrchr(wfd->cFileName, '.'); if (dot != NULL && wcslen(dot + 1) == 3) { CUnicodeString dotString(dot + 1); for (i = 0 ; i != RTL_NUMBER_OF(extensionsToIgnore) ; ++i) { if (FusionpEqualStringsI(&extensionsToIgnore[i], &dotString)) return FALSE; } } } _wcslwr(wfd->cFileName); return TRUE; }
void SeekTo( HANDLE FileHandle, ULONG64 Offset ) { LARGE_INTEGER liOffset;
liOffset.QuadPart = Offset; if (!FusionpSetFilePointerEx(FileHandle, liOffset, NULL, FILE_BEGIN)) { DbgPrint("SeekTo:0x%I64x failing\n", Offset); ThrowLastWin32Error(); } }
void SeekBackward( HANDLE FileHandle, LONG64 Offset ) { LARGE_INTEGER liOffset;
liOffset.QuadPart = -Offset; if (!FusionpSetFilePointerEx(FileHandle, liOffset, NULL, FILE_CURRENT)) ThrowLastWin32Error(); }
ULONG64 GetCurrentSeekPointer( HANDLE FileHandle ) { LARGE_INTEGER li; LARGE_INTEGER li2;
li.QuadPart = 0; li2.QuadPart = 0;
if (!FusionpSetFilePointerEx(FileHandle, li, &li2, FILE_CURRENT)) ThrowLastWin32Error(); return li2.QuadPart; }
void SeekForward( HANDLE FileHandle, ULONG64 Offset ) { LARGE_INTEGER liOffset;
liOffset.QuadPart = Offset; if (!FusionpSetFilePointerEx(FileHandle, liOffset, NULL, FILE_CURRENT)) ThrowLastWin32Error(); }
PBYTE FindRunOfZeros( PBYTE pb, PBYTE pbEnd, SIZE_T elementSize ) { SIZE_T k = 0; SIZE_T mod = ((pbEnd - pb) % elementSize); assert(mod == 0); if (mod != 0) { return pbEnd; }
if (pb + elementSize >= pbEnd) return pbEnd;
for ( ; pb != pbEnd ; pb += elementSize) { for (k = 0 ; k != elementSize ; ++k) { if (pb[k] != 0) { break; } } if (k == elementSize) { break; } } return pb; }
void ReadImportFunctionNames( HANDLE File, SIZE_T SizeOfPointer, const std::vector<ULONG64>& IatRvas std::vector<String_t>& IatRvas ) { }
void ReadIatRvas( HANDLE File, SIZE_T SizeOfPointer, std::vector<ULONG64>& Iat ) //
// This leaves the seek pointer in an arbitrary location.
//
{ union { ULONG32 Iat32[64]; ULONG64 Iat64[32]; BYTE Bytes[64 * 4]; } u;
ULONG BytesRead; ULONG Mod; Iat.resize(0);
assert(SizeOfPointer == 4 || SizeOfPointer == 8);
while (true) { BytesRead = 0; if (!ReadFile(File, &u, sizeof(u), &BytesRead, NULL)) ThrowLastWin32Error(/*"ReadFile"*/); Mod = (BytesRead % SizeOfPointer); if (Mod != 0) { SeekBackward(File, Mod); BytesRead -= Mod; } if (BytesRead == 0) { Throw(L"end of file without nul terminal\n"); } PBYTE pb = FindRunOfZeros(u.Bytes, u.Bytes + BytesRead, SizeOfPointer); switch (SizeOfPointer) { case 4: std::copy(u.Iat32, reinterpret_cast<ULONG32*>(pb), std::inserter(Iat.end())); break; case 8: std::copy(u.Iat64, reinterpret_cast<ULONG64*>(pb), std::inserter(Iat.end())); break; default: Throw("unknown sizeof pointer"); break; } if (pb != u.Bytes + BytesRead) { break; } } }
String_t ReadDllName( HANDLE File ) //
// This leaves the seek pointer in an arbitrary location.
//
{ String_t Result; CHAR BufferA[65]; WCHAR BufferW[65]; DWORD BytesRead = 0;
BufferA[NUMBER_OF(BufferA) - 1] = 0; BufferW[NUMBER_OF(BufferW) - 1] = 0;
while (true) { BytesRead = 0; if (!ReadFile(File, &BufferA[0], (NUMBER_OF(BufferA) - 1) * sizeof(BufferA[0]), &BytesRead, NULL)) ThrowLastWin32Error(/*"ReadFile"*/); if (BytesRead == 0) { Throw(L"end of file without nul terminal\n"); } _strlwr(BufferA); for (ULONG i = 0 ; i != BytesRead ; ++i) { if ((BufferW[i] = BufferA[i]) == 0) { Result += BufferW; return Result; } } Result += BufferW; } }
void Read( HANDLE FileHandle, VOID * Buffer, ULONG BytesToRead ) { DWORD BytesRead;
if (!ReadFile(FileHandle, Buffer, BytesToRead, &BytesRead, NULL)) ThrowLastWin32Error(/*"ReadFile"*/); if (BytesToRead != BytesRead) { Throw(L"wrong number of bytes read"); } }
void DelayloadTool_t::ProcessBuild(const BuildFlavor_t& b) { FilePaths_t FilePaths;
CollectFilePathsRecursively(*b.ActualRoot, FilePaths, DelayloadTool_Filter); for (FilePaths_t::const_iterator i = FilePaths.begin() ; i != FilePaths.end() ; ++i) { ProcessFile(*b.ActualRoot, *i); Spinner(); } }
String_t DelayloadTool_t::ReadOneDelayload( HANDLE File ) { ImgDelayDescrV1_32 delay1_32 = { 0 }; ImgDelayDescrV1_64 delay1_64 = { 0 }; ImgDelayDescrV2 delay2 = { 0 }; LONG64 FileOffsetToDelayLoadedName = 0; DWORD dwDelayFlags = 0; Read(File, &dwDelayFlags, 4); SeekBackward(File, 4); bool rvaFlag = ((dwDelayFlags & dlattrRva) != 0); if (rvaFlag) { Read(File, &delay2, sizeof(delay2)); } else { if (m_OptionalHeader32 != NULL) { Read(File, &delay1_32, sizeof(delay1_32)); if (delay1_32.szName == 0) { delay2.rvaDLLName = 0; } else { delay2.rvaDLLName = static_cast<RVA>(delay1_32.szName - m_OptionalHeader32->ImageBase); } } else if (m_OptionalHeader64 != NULL) { Read(File, &delay1_64, sizeof(delay1_64)); if (delay1_64.szName == 0) { delay2.rvaDLLName = 0; } else { delay2.rvaDLLName = static_cast<RVA>(delay1_64.szName - m_OptionalHeader64->ImageBase); } } else { Throw(L"unknown image format"); } } if (delay2.rvaDLLName == 0) { FileOffsetToDelayLoadedName = 0; } else { PBYTE pb = reinterpret_cast<PBYTE>(ImageRvaToVa(GetNtHeaders(), GetMappedBase(), delay2.rvaDLLName, &m_HintSection)); FileOffsetToDelayLoadedName = (pb - &m_HeadersBuffer[0]); }
if (FileOffsetToDelayLoadedName == 0) { return L""; } ULONG64 CurrentOffset = GetCurrentSeekPointer(File); SeekTo(File, FileOffsetToDelayLoadedName); String_t DllName = ReadDllName(File); SeekTo(File, CurrentOffset);
return DllName; }
void DelayloadTool_t::ProcessFile(const FilePath_t & RootPath, const FilePath_t & FilePath) { DFile File; Image_t Image; LARGE_INTEGER FileSize = { 0 }; PIMAGE_FILE_HEADER FileHeader = 0; m_OptionalHeader32 = 0; m_OptionalHeader64 = 0; PIMAGE_SECTION_HEADER SectionHeaders = 0; PIMAGE_DATA_DIRECTORY DelayloadDataDirectory = 0; HRESULT hr = 0; m_OffsetToPe = 0; ULONG OffsetToFileHeader = 0; ULONG OffsetToOptionalHeader = 0; ULONG OffsetToSectionHeaders = 0; ULONG SizeOfOptionalHeader = 0; ULONG SizeofSectionHeaders = 0; ULONG NumberOfSections = 0; m_HintSection = 0; String_t DllName; struct { IMAGE_IMPORT_DESCRIPTOR RawDescriptor; String_t DllName; std::vector<ULONG64> Iat; std::vector<String_t> FunctionNames; } Import;
Image.m_FullPath = FilePath; if (RootPath.GetLength() != 0) { assert(RootPath.GetLength() > Image.m_FullPath.GetLength()); Image.m_RelativePath = Image.m_FullPath.substr(1 + RootPath.GetLength()); } else { Image.m_RelativePath = L""; } Image.m_LeafPath = Image.m_FullPath.substr(1 + Image.m_FullPath.find_last_of(L"\\/"));
//fprintf(stderr, "\n%ls", Image.m_RelativePath.c_str());
hr = File.HrCreate(FilePath, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING); if (FAILED(hr)) { goto Error; } if (!FusionpGetFileSizeEx(File, &FileSize)) { goto Error; } if (FileSize.QuadPart < 64) { goto NotAnImage; } m_HeadersBuffer.resize(64); Read(File, &m_HeadersBuffer[0], 2); if (memcmp(&m_HeadersBuffer[0], "MZ", 2) != 0) goto NotAnImage; SeekTo(File, 60); Read(File, &m_HeadersBuffer[60], 4); m_OffsetToPe = *reinterpret_cast<ULONG*>(&m_HeadersBuffer[60]); OffsetToFileHeader = m_OffsetToPe + 4; OffsetToOptionalHeader = OffsetToFileHeader + sizeof(IMAGE_FILE_HEADER); if (m_OffsetToPe > MAXULONG - 4) goto NotAnImage; if (m_OffsetToPe + 4 > FileSize.QuadPart) goto NotAnImage; SeekTo(File, m_OffsetToPe); m_HeadersBuffer.resize(m_OffsetToPe + 4 + sizeof(IMAGE_FILE_HEADER)); Read(File, &m_HeadersBuffer[m_OffsetToPe], 4); if (memcmp(&m_HeadersBuffer[m_OffsetToPe], "PE\0\0", 4) != 0) goto NotAnImage; Read(File, &m_HeadersBuffer[OffsetToFileHeader], sizeof(IMAGE_FILE_HEADER)); FileHeader = reinterpret_cast<PIMAGE_FILE_HEADER>(&m_HeadersBuffer[OffsetToFileHeader]); SizeOfOptionalHeader = FileHeader->SizeOfOptionalHeader; NumberOfSections = FileHeader->NumberOfSections; OffsetToSectionHeaders = OffsetToOptionalHeader + SizeOfOptionalHeader; SizeofSectionHeaders = NumberOfSections * sizeof(IMAGE_SECTION_HEADER); m_HeadersBuffer.resize(OffsetToOptionalHeader + SizeOfOptionalHeader + SizeofSectionHeaders); Read(File, &m_HeadersBuffer[OffsetToOptionalHeader], SizeOfOptionalHeader + SizeofSectionHeaders); FileHeader = reinterpret_cast<PIMAGE_FILE_HEADER>(&m_HeadersBuffer[OffsetToFileHeader]); m_OptionalHeader32 = reinterpret_cast<PIMAGE_OPTIONAL_HEADER32>(&m_HeadersBuffer[OffsetToOptionalHeader]); m_OptionalHeader64 = reinterpret_cast<PIMAGE_OPTIONAL_HEADER64>(&m_HeadersBuffer[OffsetToOptionalHeader]); SectionHeaders = reinterpret_cast<PIMAGE_SECTION_HEADER>(&m_HeadersBuffer[SizeofSectionHeaders]);
switch (m_OptionalHeader32->Magic) { case IMAGE_NT_OPTIONAL_HDR32_MAGIC: m_OptionalHeader64 = NULL; break; case IMAGE_NT_OPTIONAL_HDR64_MAGIC: m_OptionalHeader32 = NULL; break; case IMAGE_ROM_OPTIONAL_HDR_MAGIC: goto IgnoreRomImages; break; default: goto UnrecognizableImage; } if (GET_OPTIONAL_HEADER_FIELD(m_OptionalHeader32, m_OptionalHeader64, NumberOfRvaAndSizes) < IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT) { goto NoDelayloads; } DelayloadDataDirectory = &GET_OPTIONAL_HEADER_FIELD(m_OptionalHeader32, m_OptionalHeader64, DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT]); if (DelayloadDataDirectory->VirtualAddress == NULL) { goto NoDelayloads; } if (DelayloadDataDirectory->Size == NULL) { goto NoDelayloads; }
fprintf(stderr, "\r%ls\n", Image.m_RelativePath.c_str());
PBYTE pb; pb = reinterpret_cast<PBYTE>(ImageRvaToVa(GetNtHeaders(), GetMappedBase(), DelayloadDataDirectory->VirtualAddress, &m_HintSection)); LONG64 OffsetToDelayloads; OffsetToDelayloads = pb - &m_HeadersBuffer[0];
SeekTo(File, OffsetToDelayloads); DllName = ReadOneDelayload(File); if (DllName == L"") { goto NoDelayloads; }
if (GET_OPTIONAL_HEADER_FIELD(m_OptionalHeader32, m_OptionalHeader64, NumberOfRvaAndSizes) < IMAGE_DIRECTORY_ENTRY_IMPORT) { goto NoImports; } ImportDataDirectory = &GET_OPTIONAL_HEADER_FIELD(m_OptionalHeader32, m_OptionalHeader64, DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]); if (ImportDataDirectory->VirtualAddress == NULL) { goto NoImports; } if (ImportDataDirectory->Size == NULL) { goto NoImports; } pb = reinterpret_cast<PBYTE>(ImageRvaToVa(GetNtHeaders(), GetMappedBase(), ImportDataDirectory->VirtualAddress, &m_HintSection)); LONG64 OffsetToImport; OffsetToImport = pb - &m_HeadersBuffer[0]; SeekTo(File, OffsetToImport); Read(File, &Import.RawDescriptor, sizeof(Import.RawDescriptor)); OffsetToImport += sizeof(ImportDescriptor);
SeekTo(File, Import.RawDescriptor.Name); Import.DllName = ReadDllName(File); SeekTo(File, Import.RawDescriptor.OriginalFirstThunk); ReadIatRvas(File, GetSizeOfPointer(), Import.Iat); ReadImportFunctionNames(File, GetSizeOfPointer(), Import.Iat, Import.FunctionNames);
NoImports:
m_XmlWriter.startElement(L"file"); m_XmlWriter.startElement(L"type"); m_XmlWriter.characters(L"pe/coff image"); m_XmlWriter.endElement(L"type"); m_XmlWriter.startElement(L"full-path"); m_XmlWriter.characters(Image.m_FullPath); m_XmlWriter.endElement(L"full-path"); if (Image.m_RelativePath != L"") { m_XmlWriter.startElement(L"relative-path"); m_XmlWriter.characters(Image.m_RelativePath); m_XmlWriter.endElement(L"relative-path"); } m_XmlWriter.startElement(L"leaf-path"); m_XmlWriter.characters(Image.m_LeafPath); m_XmlWriter.endElement(L"leaf-path"); m_XmlWriter.startElement(L"delay-loads"); for ( ; DllName != L""; DllName = ReadOneDelayload(File) ) { m_XmlWriter.startElement(L"delay-load"); m_XmlWriter.characters(DllName); m_XmlWriter.endElement(L"delay-load"); } m_XmlWriter.endElement(L"delay-loads"); m_XmlWriter.endElement(L"file"); return; /*
BytesReadError; Image.m_Error = L"bad number of bytes read"; return; */ Error: Image.m_Error = GetLastErrorString(); fprintf(stderr, "%ls", Image.m_Error.c_str()); return; UnrecognizableImage: Image.m_Error = L" unrecognizable image"; fprintf(stderr, " unrecognizable image"); return; IgnoreRomImages: fprintf(stderr, " ignore rom image"); return; NoDelayloads: //fprintf(stderr, " no delayloads");
return; NotAnImage: //fprintf(stderr, " not an image");
return; }
void DelayloadTool_t::Main(const StringVector_t& args) { typedef std::vector<FilePath_t> Files_t; Files_t Files;
typedef std::vector<BuildFlavor_t> Builds_t; Builds_t Builds;
String_t Nttree = GetEnv(L"_Nttree"); BuildFlavor_t localBuild = { L"", L"", L"", L"" }; localBuild.ActualRoot = &Nttree;
BuildFlavor_t buildFlavors[] = { { L"x86fre", L"x86", L"fre", L"robsvbl11" }, { L"x86chk", L"x86", L"chk", L"robsvbl2" }, { L"ia64fre", L"ia64", L"fre", L"robsvbl3" }, { L"ia64chk", L"ia64", L"chk", L"robsvbl4" }, //{ L"amd64fre", "amd64", L"fre", L"robsvbl5" },
//{ L"amd64chk", "amd64", L"chk", L"robsvbl6" },
};
std::vector<String_t> ActualRoots; ActualRoots.reserve(NUMBER_OF(buildFlavors));
for (StringVector_t::const_iterator i = args.begin() ; i != args.end() ; ++i) { String_t arg = *i; if (arg == L"checkall") { SIZE_T j; for (j = 0 ; j != NUMBER_OF(buildFlavors); ++j) { if (buildFlavors[j].ActualRoot == NULL) { ActualRoots.insert(ActualRoots.end(), FindLatestReleaseOnServer(buildFlavors[j].ReleaseServer)); buildFlavors[j].ActualRoot = &ActualRoots.back(); Builds.insert(Builds.end(), buildFlavors[j]); } } } else if (arg == L"checklocal") { if (Nttree == L"") { Error(L"nttree not set\n"); } Builds.insert(Builds.end(), localBuild); } else if (arg == L"dlllist") { //
// feedback loop optimization..
//
} else { SIZE_T k; for (k = 0 ; k != NUMBER_OF(buildFlavors) ; ++k) { if (arg == buildFlavors[k].Name) { if (buildFlavors[k].ActualRoot == NULL) { ActualRoots.insert(ActualRoots.end(), FindLatestReleaseOnServer(buildFlavors[k].ReleaseServer)); buildFlavors[k].ActualRoot = &ActualRoots.back(); Builds.insert(Builds.end(), buildFlavors[k]); } break; } } if (k == NUMBER_OF(buildFlavors)) { DWORD dw = GetFileAttributesW(arg); if (dw != 0xFFFFFFFF && (dw & FILE_ATTRIBUTE_DIRECTORY) == 0) { Files.insert(Files.end(), arg); } } } } this->m_XmlWriter.encoding = L"ISO-8859-1"; this->m_XmlWriter.output = static_cast<IStream*>(&this->m_OutFileStream); this->m_XmlWriter.indent = VARIANT_TRUE;
if (!m_OutFileStream.OpenForWrite( L"c:\\delayload_out.xml", FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL )) { ThrowLastWin32Error(); }
this->m_XmlWriter.startDocument(); this->m_XmlWriter.startElement(L"files");
for (Builds_t::const_iterator m = Builds.begin() ; m != Builds.end() ; ++m) { ProcessBuild(*m); } for (Files_t::const_iterator n = Files.begin() ; n != Files.end() ; ++n) { ProcessFile(L"", *n); } this->m_XmlWriter.endElement(L"files"); this->m_XmlWriter.endDocument(); //Exit:
return; }
extern "C" { void __cdecl mainCRTStartup(void); void __cdecl wmainCRTStartup(void); }
int __cdecl main(int argc, char** argv) { wmainCRTStartup(); return 0; }
extern "C" int __cdecl wmain(int argc, wchar_t** argv) { CoInitialize(NULL); FusionpInitializeHeap(GetModuleHandleW(NULL)); DelayloadTool_t tool; StringVector_t args; args.reserve(argc); std::copy(argv + 1, argv + argc, std::back_inserter(args)); tool.Main(args); return 0; }
|