关闭掉新版Delphi的几个固定导出函数(__dbk_fcall_wrapper,dbkFCallWrapperAddr,TMethodImplementationIntercept)

不知道从什么时候起Delphi编译的PE文件总是三个固定的导出函数。

一方面有强迫症的同学们会不爽,另一方面其实是不安全的。

这三个函数是:__dbk_fcall_wrapper,dbkFCallWrapperAddr,TMethodImplementationIntercept

有两种方式可以去掉他们。

1.修改RTL源代码,注释掉这几处函数的exports代码行。重新编译。不过重新编译对小白或者比较懒的同学确实不方便。况且出了新版本Delphi又要重做一遍。

2.把编译后的EXE,DLL处理一下,去掉这几个函数。

做了个小工具,可以删除EXE,DLL的导出函数的,可以批量删除导出函数,函数名用逗号分隔。为了方便被批处理或脚本调用写成了命令行工具,返回值0表示成功,-1失败。经测试,可以使用。自动识别WIN32,WIN64的程序,分别处理。

使用方法如:RemoveExportProc.exe ContextMenu64.dll  __dbk_fcall_wrapper,dbkFCallWrapperAddr,TMethodImplementationIntercept  d:\test.dll’

另一方面,用XE10.2可以编译出59KB的小程序,自从Delphi2010加入RTTI信息以后,很少见到1MB以下的Delphi程序了:)。

下载链接:RemoveExportProc

代码也非常少,可以直接贴出来:


program RemoveExportProc;

{$IF CompilerVersion >= 21.0}
{$WEAKLINKRTTI ON}
{$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])}
{$ENDIF}
{$APPTYPE CONSOLE}
{$R *.res}

uses
Winapi.Windows;

{$POINTERMATH on}

type
TBytes = array of Byte;
TDynArrayString = array of string;

PIMAGE_EXPORT_DIRECTORY = ^IMAGE_EXPORT_DIRECTORY;

_IMAGE_EXPORT_DIRECTORY = record
Characteristics: DWORD;
TimeDateStamp: DWORD;
MajorVersion: Word;
MinorVersion: Word;
Name: DWORD;
Base: DWORD;
NumberOfFunctions: DWORD;
NumberOfNames: DWORD;
AddressOfFunctions: DWORD;
AddressOfNames: DWORD;
AddressOfNameOrdinals: DWORD;
end;

IMAGE_EXPORT_DIRECTORY = _IMAGE_EXPORT_DIRECTORY;

function StrIComp(const Str1, Str2: PAnsiChar): Integer;
var
P1, P2: PAnsiChar;
C1, C2: AnsiChar;
begin
P1 := Str1;
P2 := Str2;
while True do
begin
if P1^ in ['a' .. 'z'] then
C1 := AnsiChar(Byte(P1^) xor $20)
else
C1 := P1^;

if P2^ in ['a' .. 'z'] then
C2 := AnsiChar(Byte(P2^) xor $20)
else
C2 := P2^;

if (C1 <> C2) or (C1 = #0) then
begin
Result := (Ord(C1) - Ord(C2));
Exit;
end;
Inc(P1);
Inc(P2);
end;
end;

function RVA2RAWInSection(Base: PByte; RVA: UInt64;
const psection: PImageSectionHeader): Pointer; overload;
begin
Result := @Base[psection^.PointerToRawData +
(RVA - psection^.VirtualAddress)];
end;

function RVA2RAW32(Base: PByte; pHeader: PImageNtHeaders32; RVA: UInt64;
var psection: PImageSectionHeader): Pointer; overload;
var
i: Integer;
SectionAlign: DWORD;
startAddr, EndAddr: UInt64;
begin
Result := Pointer(RVA);
SectionAlign := pHeader^.OptionalHeader.SectionAlignment;
psection := IMAGE_FIRST_SECTION(pHeader^);
for i := 0 to pHeader^.FileHeader.NumberOfSections - 1 do
begin
startAddr := psection^.VirtualAddress;
EndAddr := psection^.VirtualAddress + psection^.VirtualAddress;
if (RVA >= startAddr) and (RVA <= EndAddr) and
((RVA - psection^.VirtualAddress) < psection^.SizeOfRawData) then
begin
Result := @Base[psection^.PointerToRawData + (RVA - startAddr)];
Break;
end;
Inc(psection);
end;
end;

function RVA2RAW64(Base: PByte; pHeader: PImageNtHeaders64; RVA: UInt64;
var psection: PImageSectionHeader): Pointer; overload;
var
i: Integer;
SectionAlign: DWORD;
startAddr, EndAddr: UInt64;
begin
Result := Pointer(RVA);
SectionAlign := pHeader^.OptionalHeader.SectionAlignment;
psection := IMAGE_FIRST_SECTION(pHeader^);
for i := 0 to pHeader^.FileHeader.NumberOfSections - 1 do
begin
startAddr := psection^.VirtualAddress;
EndAddr := psection^.VirtualAddress + psection^.VirtualAddress;
if (RVA >= startAddr) and (RVA <= EndAddr) and
((RVA - psection^.VirtualAddress) < psection^.SizeOfRawData) then
begin
Result := @Base[psection^.PointerToRawData + (RVA - startAddr)];
Break;
end;
Inc(psection);
end;
end;

function RAW2RVA(Base: PByte; RAW: UInt64;
const psection: PImageSectionHeader): UInt64;
begin
Result := RAW + psection.VirtualAddress - psection.PointerToRawData -
UInt64(Base);
end;

function RemoveExportProc64(Base: PByte; pHeader: PImageNtHeaders64;
const lpProcName: LPCSTR): boolean;
var
i, idx: Integer;
dir: PImageDataDirectory;
Ordinal: PWORD;
nameRef: PDWORD;
functions: PDWORD;
exps: PIMAGE_EXPORT_DIRECTORY;
func: DWORD;
pdos: PImageDosHeader ABSOLUTE Base;
diff: Integer;
lpFuncNameInExports: PAnsiChar;

var
psection: PImageSectionHeader;
j: Integer;
begin
Result := False;
idx := -1;

// Exit(FindMyResFunc(pm^.codeBase, lpProcName));
dir := PImageDataDirectory(@pHeader^.OptionalHeader.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT]);

if (dir^.VirtualAddress = 0) or (dir^.Size = 0) then
Exit;

exps := PIMAGE_EXPORT_DIRECTORY(RVA2RAW64(Base, pHeader, dir.VirtualAddress,
psection));
RVA2RAWInSection(Base, exps^.Name, psection);

if (exps^.NumberOfFunctions = 0) then
Exit;
// 16位以上是0,那么就是用索引查找函数.
if ((NativeUInt(lpProcName)) <= $FFFF) then
begin
idx := NativeUInt(lpProcName) - exps^.Base;
end
else // 否则按照函数名称查找
begin
if (exps^.NumberOfNames = 0) then
Exit;
nameRef := PDWORD(RVA2RAWInSection(Base, exps^.AddressOfNames, psection));
Ordinal := PWORD(RVA2RAWInSection(Base, exps^.AddressOfNameOrdinals,
psection));
functions := PDWORD(RVA2RAWInSection(Base, exps^.AddressOfFunctions,
psection));
for i := 0 to exps^.NumberOfNames - 1 do
begin
lpFuncNameInExports := LPCSTR(RVA2RAWInSection(Base, nameRef[i],
psection));
if StrIComp(lpProcName, lpFuncNameInExports) = 0 then
begin
// idx函数的序号,func函数的地址
idx := exps^.Base + Ordinal[i];
func := functions[Ordinal[i]];
//
// Ordinal[0] := Ordinal[1];
{ Move(Ordinal[i + 1], Ordinal[i],
SizeOf(Word) * exps^.NumberOfFunctions - 1 - i);
}
{
Move(nameRef[i + 1], nameRef[i],
SizeOf(DWORD) * exps^.NumberOfNames - 1 - i);
nameRef[exps^.NumberOfNames - 1] := 0;
}
for j := i to exps^.NumberOfFunctions - 1 do
begin
if j = (exps^.NumberOfFunctions - 1) then
Ordinal[j] := 0
else
Ordinal[j] := Ordinal[j + 1];
end;
for j := i to exps^.NumberOfNames - 1 do
begin
if j = (exps^.NumberOfNames - 1) then
nameRef[j] := 0
else
nameRef[j] := nameRef[j + 1];
end;

// functions[Ordinal[i]] := 0;

Dec(exps^.NumberOfNames);
Dec(exps^.NumberOfFunctions);
//
Result := True;
Break;
end;
end;
end;

end;

function RemoveExportProc32(Base: PByte; pHeader: PImageNtHeaders32;
const lpProcName: LPCSTR): boolean;

var
i, idx: Integer;
dir: PImageDataDirectory;
Ordinal: PWORD;
nameRef: PDWORD;
functions: PDWORD;
exps: PIMAGE_EXPORT_DIRECTORY;
func: DWORD;
pBuf: PByte;
pdos: PImageDosHeader absolute Base;
diff: Integer;
lpFuncNameInExports: PAnsiChar;

var
psection: PImageSectionHeader;
j: Integer;
begin
Result := False;
idx := -1;

// Exit(FindMyResFunc(pm^.codeBase, lpProcName));
dir := PImageDataDirectory(@pHeader^.OptionalHeader.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT]);

if (dir^.VirtualAddress = 0) or (dir^.Size = 0) then
Exit;

exps := PIMAGE_EXPORT_DIRECTORY(RVA2RAW32(Base, pHeader, dir.VirtualAddress,
psection));
RVA2RAWInSection(Base, exps^.Name, psection);

if (exps^.NumberOfFunctions = 0) then
Exit;
// 16位以上是0,那么就是用索引查找函数.
if ((NativeUInt(lpProcName)) <= $FFFF) then
begin
idx := NativeUInt(lpProcName) - exps^.Base;
end
else // 否则按照函数名称查找
begin
if (exps^.NumberOfNames = 0) then
Exit;
nameRef := PDWORD(RVA2RAWInSection(Base, exps^.AddressOfNames, psection));
Ordinal := PWORD(RVA2RAWInSection(Base, exps^.AddressOfNameOrdinals,
psection));
functions := PDWORD(RVA2RAWInSection(Base, exps^.AddressOfFunctions,
psection));
for i := 0 to exps^.NumberOfNames - 1 do
begin
lpFuncNameInExports := LPCSTR(RVA2RAWInSection(Base, nameRef[i],
psection));
if StrIComp(lpProcName, lpFuncNameInExports) = 0 then
begin
// idx函数的序号,func函数的地址
idx := exps^.Base + Ordinal[i];
func := functions[Ordinal[i]];
//
// Ordinal[0] := Ordinal[1];
{ Move(Ordinal[i + 1], Ordinal[i],
SizeOf(Word) * exps^.NumberOfFunctions - 1 - i);
}
{
Move(nameRef[i + 1], nameRef[i],
SizeOf(DWORD) * exps^.NumberOfNames - 1 - i);
nameRef[exps^.NumberOfNames - 1] := 0;
}
for j := i to exps^.NumberOfFunctions - 1 do
begin
if j = (exps^.NumberOfFunctions - 1) then
Ordinal[j] := 0
else
Ordinal[j] := Ordinal[j + 1];
end;
for j := i to exps^.NumberOfNames - 1 do
begin
if j = (exps^.NumberOfNames - 1) then
nameRef[j] := 0
else
nameRef[j] := nameRef[j + 1];
end;

// functions[Ordinal[i]] := 0;

Dec(exps^.NumberOfNames);
Dec(exps^.NumberOfFunctions);
//
Result := True;
Break;
end;
end;
end;

end;

function SpliteStr(Delimiter, Value: String; var strs: TDynArrayString)
: Integer; overload;
var
P: Integer;
Item: String;
begin
SetLength(strs, 0);

P := Pos(Delimiter, Value);
while P > 0 do
begin
Item := Copy(Value, 1, P - 1);
SetLength(strs, Length(strs) + 1);
strs[Length(strs) - 1] := Item;
Value := Copy(Value, P + Length(Delimiter), Length(Value));
P := Pos(Delimiter, Value);
end;
SetLength(strs, Length(strs) + 1);
strs[Length(strs) - 1] := Value;
end;

function _RemoveExportProc(Module: TBytes; const lpProcName: string)
: boolean; overload;
var
Base: PByte;
dos: PImageDosHeader absolute Base;
header32: PImageNtHeaders32;
header64: PImageNtHeaders64 ABSOLUTE header32;
procNames: TDynArrayString;
i: Integer;
begin
Result := False;
Base := @Module[0];
SpliteStr(',', lpProcName, procNames);
if dos.e_magic = IMAGE_DOS_SIGNATURE then
begin
header32 := PImageNtHeaders32(@Base[dos._lfanew]);
case header32.FileHeader.Machine of
IMAGE_FILE_MACHINE_I386:
begin
for i := Low(procNames) to High(procNames) do
Result := RemoveExportProc32(Base, header32,
PAnsiChar(AnsiString(procNames[i])));
end;
IMAGE_FILE_MACHINE_AMD64:
begin
for i := Low(procNames) to High(procNames) do
Result := RemoveExportProc64(Base, header64,
PAnsiChar(AnsiString(procNames[i])));
end;
end;
end;
end;

function FileOpen(const FileName: string; ReadOnly: boolean): THandle;
var
g, s: DWORD;
begin
Result := INVALID_HANDLE_VALUE;
if ReadOnly then
begin
g := GENERIC_READ;
s := FILE_SHARE_WRITE;
end
else
begin
g := GENERIC_READ or GENERIC_WRITE;
s := FILE_SHARE_WRITE or FILE_SHARE_READ;
end;
Result := CreateFile(PChar(FileName), g, FILE_SHARE_WRITE, nil, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, 0);
end;

function FileCreate(const FileName: string): THandle;
begin
Result := INVALID_HANDLE_VALUE;
Result := CreateFile(PChar(FileName), GENERIC_READ or GENERIC_WRITE, 0, nil,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
end;

function FileRead(Handle: THandle; var Buffer; Count: LongWord): Integer;
begin
if not ReadFile(Handle, Buffer, Count, LongWord(Result), nil) then
Result := -1;
end;

function FileWrite(Handle: THandle; const Buffer; Count: LongWord): Integer;
begin
if not WriteFile(Handle, Buffer, Count, LongWord(Result), nil) then
Result := -1;
end;

procedure FileClose(Handle: THandle); inline;
begin
CloseHandle(Handle);
end;

function ReadAllBytes(const AFileName: string; var AData: TBytes): boolean;
var
hFile: THandle;
fSize: Int64;
begin
Result := False;
hFile := FileOpen(PChar(AFileName), True);
if hFile <> INVALID_HANDLE_VALUE then
begin
if GetFileSizeEx(hFile, fSize) and (fSize <> 0) then
begin
SetLength(AData, fSize);
Result := FileRead(hFile, AData[0], fSize) = fSize;
end;
FileClose(hFile);
end;
end;

function WriteAllBytes(const AFileName: string; AData: TBytes): boolean;
var
hFile: THandle;
fSize: Int64;
begin
Result := False;
hFile := FileCreate(PChar(AFileName));
if hFile <> INVALID_HANDLE_VALUE then
begin
if Length(AData) > 0 then
begin
Result := FileWrite(hFile, AData[0], Length(AData)) = Length(AData);
end;
FileClose(hFile);
end;
end;

function _RemoveExportProc(DLLName, NewDLLName: string;
const lpProcName: string): boolean; overload;
var
bs: TBytes;
begin
if ReadAllBytes(DLLName, bs) then
begin
_RemoveExportProc(bs, lpProcName);
WriteAllBytes(NewDLLName, bs);
end;
end;

var
DLLName, NewDLLName, ProcName: string;

begin
if not(ParamCount in [2, 3]) then
begin
Writeln('RemoveExportProc.exe DLLName ProcName,ProcName [NewDLLName]');
Writeln('eg:RemoveExportProc.exe ContextMenu64.dll  __dbk_fcall_wrapper,dbkFCallWrapperAddr,TMethodImplementationIntercept  d:\test.dll');
Readln(DLLName);
end
else
begin
DLLName := ParamStr(1);
ProcName := ParamStr(2);
if ParamCount = 3 then
NewDLLName := ParamStr(3)
else
NewDLLName := DLLName;
if not _RemoveExportProc(DLLName, NewDLLName, ProcName) then
ExitCode := -1;
end;

end.

 

此条目发表在Delphi, 未分类分类目录,贴了, , , , 标签。将固定链接加入收藏夹。

关闭掉新版Delphi的几个固定导出函数(__dbk_fcall_wrapper,dbkFCallWrapperAddr,TMethodImplementationIntercept)》有59条回应

  1. waleson说:

    发现delphi 10.3.1编译的ocx,使用该工具后会出现 ID:0 ID:1 ID:2 ID3 等函数,怎么办

  2. Pingback引用通告: psixolog

  3. Pingback引用通告: psyhelp_on_line

  4. Pingback引用通告: Coronavirus real-time updates

  5. Pingback引用通告: PSYCHOSOCIAL

  6. Pingback引用通告: Cherekasi

  7. Pingback引用通告: film doktor_liza

  8. Pingback引用通告: djoker film

  9. Pingback引用通告: viagra

  10. Pingback引用通告: Îíëàéí Ïñèõîëîã

  11. Pingback引用通告: viagra 100mg

  12. Pingback引用通告: viagra price

  13. Pingback引用通告: viagra generic

  14. Pingback引用通告: viagra coupon

  15. Pingback引用通告: otc viagra

  16. Pingback引用通告: generic cialis

  17. Pingback引用通告: cialis online

  18. Pingback引用通告: cialis price

  19. Pingback引用通告: cialis 5mg

  20. Pingback引用通告: bitly.com

  21. Pingback引用通告: bitly

  22. Pingback引用通告: movies-tekstmovies-tekst

  23. Pingback引用通告: Zemlyane 2005 smotret onlajn

  24. Pingback引用通告: smotret onlajn v horoshem kachestve hd

  25. Pingback引用通告: dom 2

  26. Pingback引用通告: Vratar Galaktiki Film, 2020

  27. Pingback引用通告: Cherkassy

  28. Pingback引用通告: chernobyl-hbo-2020-1-sezon-2-sezon

  29. Pingback引用通告: batmanapollo.ru

  30. Pingback引用通告: 525

  31. Pingback引用通告: dom2 ru

  32. Pingback引用通告: psy psy psy psy

  33. Pingback引用通告: krsmi.ru

  34. Pingback引用通告: like-v.ru

  35. Pingback引用通告: CFOSPUK

  36. Pingback引用通告: MAMprEj

  37. Pingback引用通告: batmanapollo

  38. Pingback引用通告: HD

  39. Pingback引用通告: bitly.com/3zaklyatie3

  40. Pingback引用通告: Human design

  41. Pingback引用通告: 1445

  42. Pingback引用通告: cleantalkorg2.ru

  43. Pingback引用通告: vk login

  44. Pingback引用通告: svaty—7—sezon

  45. Pingback引用通告: svaty 7 sezon

  46. Pingback引用通告: svaty 7

  47. Pingback引用通告: tik tok

  48. Pingback引用通告: 666

  49. Pingback引用通告: The Revenant 2021

  50. Pingback引用通告: Human Design 2021

  51. Pingback引用通告: psy

  52. Pingback引用通告: psy2022

  53. Pingback引用通告: projectio freid

  54. Pingback引用通告: kinoteatrzarya.ru

  55. Pingback引用通告: video

  56. Pingback引用通告: Ukrainskie-serialy

  57. Pingback引用通告: site

  58. Pingback引用通告: top

  59. Pingback引用通告: soderzhanki-3-sezon-2021.online

评论已关闭。