📄 wdmfixer.dpr
字号:
program WDMFixer;
{$APPTYPE CONSOLE}
uses
Windows, SysUtils, Classes;
const
FT_ANY = 0;
FT_DLL = IMAGE_FILE_DLL;
FT_ROM = IMAGE_ROM_OPTIONAL_HDR_MAGIC;
FT_EXE = IMAGE_FILE_EXECUTABLE_IMAGE;
{ type defined in Jedi Api Project, JwaWinNT.pas }
type
TIIDUnion = record
case Integer of
0: (Characteristics: DWORD); // 0 for terminating null import descriptor
1: (OriginalFirstThunk: DWORD); // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
end;
PIMAGE_IMPORT_DESCRIPTOR = ^IMAGE_IMPORT_DESCRIPTOR;
{$EXTERNALSYM PIMAGE_IMPORT_DESCRIPTOR}
_IMAGE_IMPORT_DESCRIPTOR = record
Union: TIIDUnion;
TimeDateStamp: DWORD; // 0 if not bound,
// -1 if bound, and real date\time stamp
// in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
// O.W. date/time stamp of DLL bound to (Old BIND)
ForwarderChain: DWORD; // -1 if no forwarders
Name: DWORD;
FirstThunk: DWORD; // RVA to IAT (if bound this IAT has actual addresses)
end;
{$EXTERNALSYM _IMAGE_IMPORT_DESCRIPTOR}
IMAGE_IMPORT_DESCRIPTOR = _IMAGE_IMPORT_DESCRIPTOR;
{$EXTERNALSYM IMAGE_IMPORT_DESCRIPTOR}
TImageImportDecriptor = IMAGE_IMPORT_DESCRIPTOR;
PImageImportDecriptor = PIMAGE_IMPORT_DESCRIPTOR;
type
TCheckCallback = procedure (FN : String);
function isPE(F:TStream; FType:WORD) : Boolean;
var
Size : DWORD;
Tag : WORD;
NTHead : DWORD;
begin
Result := False;
Size := F.Size;
if Size <= SizeOf(TImageDosHeader) + 4 + SizeOf(TImageFileHeader) then
Exit;
F.Seek(0,soFromBeginning);
F.Read(Tag, 2);
F.Seek(2, soFromCurrent);
if Tag <> IMAGE_DOS_SIGNATURE then
Exit;
F.Seek(SizeOf(TImageDosHeader)-8, soFromCurrent);
F.Read(NTHead, 4); // _lfanew
if Size <= NTHead + 4 + SizeOf(TImageFileHeader) then
Exit;
F.Seek(NTHead, soFromBeginning);
F.Read(NTHead, 4);
Result := NTHead = IMAGE_NT_SIGNATURE;
end;
const
IMAGE_SIZEOF_OPTIONAL_HEADER_NONEDIRECTOR = 96;
function PosToTableEntry(F: TStream; Section: SmallInt; out VABase, VASize, RawAddr: DWORD): Boolean;
var
tempPos : Int64;
tempSize : DWORD;
NumberOfRvaAndSizes : DWORD;
i : Integer;
SectionHeader : TImageSectionHeader;
SizeOfOptionalHeader : DWORD;
begin
Result := False;
if (F.Position <> 0) or isPE(F, FT_ANY) then
begin
tempSize := 0;
F.Seek(2, soFromCurrent); // 跳2个字节: TImageFileHeader.Machine
F.Read(tempSize, 2); // 取TImageFileHeader.NumberOfSections
F.Seek(SizeOf(TImageFileHeader) - 4 - 4 , soFromCurrent); // 定位到TImageFileHeader.SizeOfOptionalHeader
F.Read(SizeOfOptionalHeader, 4);
SizeOfOptionalHeader := SizeOfOptionalHeader and $0000FFFF; // 去除掉高位的TImageFileHeader.Characteristics
tempPos := F.Position; // 可选头部
F.Seek(IMAGE_SIZEOF_OPTIONAL_HEADER_NONEDIRECTOR-4, soFromCurrent); //定位到NumberOfRvaAndSizes
F.Read(NumberOfRvaAndSizes, 4);
// 定位到DataDirectory[]
F.Seek(SizeOf(TImageDataDirectory)*Section, soFromCurrent); // 跳过目录;
F.Read(VABase, 4); // 读指定目录的VABase
F.Read(VASize, 4); // 读指定目录的VASize
if VABase <> 0 then
begin
// 定位到节表
inc(tempPos, SizeOfOptionalHeader);
F.Seek(tempPos, soFromBeginning);
// 取RawAddr
for i := 0 to tempSize - 1 do
begin
F.Read(SectionHeader, SizeOf(TImageSectionHeader));
with SectionHeader do
// 如果虚地址相等或者VABase落在节的内部
if (VABase = VirtualAddress) or
((VABase > VirtualAddress) and (VABase < VirtualAddress + Misc.VirtualSize)) then
begin
RawAddr := PointerToRawData + (VABase - VirtualAddress);
F.Seek(RawAddr, soFromBeginning);
Result := True;
Exit;
end;
end;
end;
// 如果返回False, 则定位到PE头
F.Position := tempPos - SizeOf(TImageFileHeader);
end;
end;
procedure DoFix(callback:TCheckCallback; Dir : String = ''; FN : String = '*.*');
var
Sr : TSearchRec;
begin
if FindFirst(Dir+FN, faAnyFile-faVolumeID, Sr) = 0 then
repeat
if (Sr.Attr and faDirectory)=0 then //is File
callback(Dir+Sr.Name)
else //is Directory
if Sr.Name[1] <> '.' then
DoFix(callback, Dir+Sr.name+'\', FN);
until FindNext(Sr) <> 0;
end;
procedure FixImport(FN : String);
var
VABase, VASize, RawAddr: DWORD;
F : TMemoryStream;
ImportItem : TImageImportDecriptor;
begin
try
F := TMemoryStream.Create();
F.LoadFromFile(FN);
except
exit;
end;
if PosToTableEntry(F, IMAGE_DIRECTORY_ENTRY_IMPORT, VABase, VASize, RawAddr) then
begin
while true do
begin
F.Read(ImportItem, SizeOf(TImageImportDecriptor));
if ImportItem.name = 0 then
Break;
// 修正WDM文件导入表的中的 OriginalFirstThunk 值
ImportItem.Union.OriginalFirstThunk := ImportItem.FirstThunk;
F.Seek(-SizeOf(TImageImportDecriptor), soFromCurrent);
F.Write(ImportItem, SizeOf(TImageImportDecriptor));
end;
end;
F.SaveToFile(FN);
F.Free;
end;
const SoftWareName = 'WDM Fixer for Delphi Apps. Ver1.0,';
CompanyName = 'copyright(c) 1999,2004 aurora software';
Width = 80 - Length(SoftWareName);
begin
if ParamCount > 0 then
DoFix(FixImport, '', ParamStr(1))
else
begin
Write(SoftWareName,CompanyName:Width);
Writeln('By Mr. Aimingoo.'); Writeln;
writeln('Usage : WDMFixer FileName');
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -