吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1212|回复: 11
收起左侧

[已解决] dll自定义入口的问题

[复制链接]
朱朱你堕落了 发表于 2023-8-10 23:49
300吾爱币
看到某CSDN文章如下:

================================================================================================
关于重新指定Dll入口的问题

大家都明白,在进行Dll开发过程当中,VS将默认指定DllMain为Dll的入口。一般情况下我们需要定义自己的入口,如何让我们的程序在加载Dll时直接
执行的是我们自定义的入口函数呢?我想很多初学者都不是很了解,本人也曾经为此迷惑了许久,为了方便大家的学习,在这里将其贴出来,供大家参考。

其实方法很简单,只需要我们在Project --〉Setting下面的Link标签中的Project Options里面加入/Entry:"MyEntry"即可,其中MyEntry就是我们要指
定的入口方法名称。为此,我们再次编译工程,Dll将以MyEntry为程序入口执行。
================================================================================================

文章就这么多文字,还是不明白指定DLL入口,或是说自定义DLL函数入口,有啥好处。

1
文章中说:如何让我们的程序在加载Dll时直接执行的是我们自定义的入口函数呢?这是啥意思?请写个demo例子说明一下

2
另外,不使用dllmain做入口而使用自定义入口还没有其他别的用处?也请写demo说明一下。

最佳答案

查看完整内容

以vs举例,其他的可能也大差不差。 你写一个动态库,一般来说入口点就是DllMain,编译器会自动链接SDK中的crtdll.c文件(或类似的),里面是真正的入口点_DllMainCRTStartup,如果是DLL_PROCESS_ATTACH的话就__security_init_cookie,接着调用__DllMainCRTStartup(与前面的_DllMainCRTStartup有区别,这个函数是两个下划线开头),在__DllMainCRTStartup中会做一些_CRT_INIT之类的初始化工作,然后才会去调用DllMain。 如果你没 ...

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

yes2 发表于 2023-8-10 23:49
以vs举例,其他的可能也大差不差。
你写一个动态库,一般来说入口点就是DllMain,编译器会自动链接SDK中的crtdll.c文件(或类似的),里面是真正的入口点_DllMainCRTStartup,如果是DLL_PROCESS_ATTACH的话就__security_init_cookie,接着调用__DllMainCRTStartup(与前面的_DllMainCRTStartup有区别,这个函数是两个下划线开头),在__DllMainCRTStartup中会做一些_CRT_INIT之类的初始化工作,然后才会去调用DllMain。
如果你没有实现DllMain,那么链接就会错误。这个就是默认情况下,非自定义入口点的编译和执行情况。

自定义入口点的意思就是,你编译器不要给我链接crtdll.c了,我自己指定一个函数作为入口点。
比如还是DllMain作为自定义入口点,_DllMainCRTStartup和__DllMainCRTStartup以及_CRT_INIT之类的都不会被调用到,你需要自己去做这些初始化工作。
如果不想以DllMain为入口点也可以,无非是改个名字。函数协议也可以有变化,如果你对参数毫不关心的话,甚至可以用void main()来作为Dll的入口点函数,不过链接的时候会给你警告,你的入口点函数不符合DllMain函数协议可能会出错。

自定义入口点的好处是可以极大降低生成的dll的体积。比如我用MT方式编译的无功能dll是68K,自定义入口点之后是4K。
坏处是不能用运行库的函数,因为没有初始化,没有链接进来。

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
董督秀 + 1 + 1 我很赞同!

查看全部评分

0Ling0 发表于 2023-8-11 05:18
only998 发表于 2023-8-11 08:29
能想到的用处就是定义不同的入口对应不同的功能,方便不同版本做功能切换,不过用define宏控制也是一样,不太理解这个功能有什么好处。
对于编译完成的dll来说,入口就是入口,没有什么意义。
sunsjw 发表于 2023-8-11 09:36
yes2 发表于 2023-8-11 09:28
以vs举例,其他的可能也大差不差。
你写一个动态库,一般来说入口点就是DllMain,编译器会自动链接SDK中的 ...

回答的不错,受教了。
seeyou_shj 发表于 2023-8-11 10:16
本帖最后由 seeyou_shj 于 2023-8-11 10:20 编辑

以前写过一片关于dll文件的内容,很简单,不过似乎可以解答你的问题。去看看吧。用的是mingw编译器。

https://user.qzone.qq.com/37505515/infocenter

主要内容如下:

写一个简单的dll文件,内容如下(main.cpp):

extern "C" int sub(int a,int b){
    return a-b;
}
extern "C" int add(int a,int b, int c){
    return sub(a,b)+c;
}

编译:g++ -shared main.cpp -o main.dll,ok,得到main.dll文件了。


在python环境中测试一下,结果正常:

>>> import ctypes
>>> m = ctypes.cdll.LoadLibrary("d:/temp/main.dll")
>>> m.add(5,3,8)
10

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
朱朱你堕落了 + 1 + 1 哎,不认真审题,答非所问!

查看全部评分

冥界3大法王 发表于 2023-8-11 10:39
only998 发表于 2023-8-11 08:29
能想到的用处就是定义不同的入口对应不同的功能,方便不同版本做功能切换,不过用define宏控制也是一样,不 ...

@only998
正好老兄在场,借机问个同类型的问题吧!

我的设计是这样的:
通过DLL(x64dbg的*.dp64)连接上之后,我外部*.exe能不能执行 DbgCmdExec(PAnsiChar(AnsiString('StepOver')));

我那个是*.dpr (生成x64dbg的*.dp64 【其实就是特种形态的DLL】)
我写把过程弄好之后,弄了一个导出函数。

[Delphi] 纯文本查看 复制代码
library MoreTool;
 {$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])}
 {$WEAKLINKRTTI ON}

uses
  Windows,
  Messages,
  vcl.Forms,
  bridgemain in 'plugin\bridgemain.pas',
  _plugins in 'plugin\_plugins.pas';

{$ALIGN 1}
	{$WARN UNSAFE_CODE OFF}
	{$WARN UNSAFE_TYPE OFF}
	{$WARN UNSAFE_CAST OFF}
  {$IFDEF WIN64}
  {$E dp64}
  {$ELSE}
  {$E dp32}
  {$ENDIF}

var
  SaveDLLProc: TDLLProc;
  g_pluginHandle: THandle = 0;
  g_hMenu: Cardinal = 0;
  g_hMenuDisasm: Cardinal = 0;
  g_Inst: Cardinal = 0;
  g_hWnD: Cardinal = 0;
  g_loadedname: array[0..8] of PAnsiChar;

function ShellExecuteA(hWnd: hWnd; Operation, FileName, Parameters, Directory: PAnsiChar; ShowCmd: Integer): HINST; stdcall; external 'shell32.dll' name 'ShellExecuteA';

const
  PLUGIN_NAME: PAChar = 'MoreTool';
  PLUGIN_AUTH: PAChar = 'remek002';
  PLUGIN_VERS: Integer = 01;
  MENU_CALC = 1;
  MENU_NOTEPAD = 2;
  MENU_DISASM_CALC = 3;
  MENU_DISASM_NOTEPAD = 4;

{$R MoreTool.res}

procedure RegisterInitProc(cbType: cbType; callbackInfo: Pointer); cdecl;
var
  info: PPLUG_CB_INITDEBUG;
begin
  ZeroMemory(@g_loadedname, SizeOf(g_loadedname));
  info := PPLUG_CB_INITDEBUG(callbackInfo);
  g_loadedname[0] := info^.szFileName;
  BridgeSettingSet('Last File', 'Last', g_loadedname[0]);
end;

procedure RegisterMenuProc(cbType: cbType; callbackinfo: Pointer); cdecl;
var
  info: PPLUG_CB_MENUENTRY;
begin
  info := PPLUG_CB_MENUENTRY(callbackinfo);
  case (info^.hEntry) of
    MENU_CALC:
      begin
        ShellExecuteA(GuiGetWindowHandle, 'OPEN', 'calc.exe', '', 'C:\Windows\system32', SW_SHOWNORMAL);
      end;
    MENU_NOTEPAD:
      begin
        ShellExecuteA(GuiGetWindowHandle, 'OPEN', 'notepad.exe', '', 'C:\Windows\system32', SW_SHOWNORMAL);
      end;
    MENU_DISASM_CALC:
      begin
        ShellExecuteA(GuiGetWindowHandle, 'OPEN', 'calc.exe', '', 'C:\Windows\system32', SW_SHOWNORMAL);
      end;
    MENU_DISASM_NOTEPAD:
      begin
        ShellExecuteA(GuiGetWindowHandle, 'OPEN', 'notepad.exe', '', 'C:\Windows\system32', SW_SHOWNORMAL);
      end;
  end;
end;

function calc(argc: Integer; argv: PPAnsiChar): Boolean; cdecl;
begin
  ShellExecuteA(GuiGetWindowHandle, 'OPEN', 'calc.exe', '', 'C:\Windows\system32', SW_SHOWNORMAL);
end;

function notepad(argc: Integer; argv: PPAnsiChar): Boolean; cdecl;
begin
  ShellExecuteA(GuiGetWindowHandle, 'OPEN', 'notepad.exe', '', 'C:\Windows\system32', SW_SHOWNORMAL);
end;

function x_dbg_Plugininit(PlugInitInfo: PPLUG_INITSTRUCT): Boolean; cdecl;
begin
  g_pluginHandle := PlugInitInfo^.pluginHandle;               //Address: 0043E7DC
  PlugInitInfo^.sdkVersion := PLUG_SDKVERSION;
  PlugInitInfo^.PluginVersion := PLUGIN_VERS;
  lstrcpyA(PlugInitInfo^.pluginName, PLUGIN_NAME);
  _plugin_registercallback(g_pluginHandle, CB_MENUENTRY, RegisterMenuProc);
  _plugin_registercallback(g_pluginHandle, CB_INITDEBUG, RegisterInitProc);
  Result := True;
end;

procedure x_dbg_Pluginsetup(PlugSetupInfo: PPLUG_SETUPSTRUCT); cdecl;
begin
  g_hMenu := PlugSetupInfo^.hMenu;
  g_hMenuDisasm := PlugSetupInfo^.hMenuDisasm;

  _plugin_menuaddentry(g_hMenuDisasm, MENU_DISASM_CALC, 'Open Calc');
  _plugin_menuaddseparator(g_hMenuDisasm);
  _plugin_menuaddentry(g_hMenuDisasm, MENU_DISASM_NOTEPAD, 'Open Notepad');

  _plugin_menuaddentry(g_hMenu, MENU_CALC, 'Open Calc');
  _plugin_menuaddseparator(g_hMenu);
  _plugin_menuaddentry(g_hMenu, MENU_NOTEPAD, 'Open Notepad');

  if not (_plugin_registercommand(g_pluginHandle, 'Calc', calc, false)) then
    _plugin_logputs('[MapMaster] ErroR Registering The "Calc" command! ');
  if not (_plugin_registercommand(g_pluginHandle, 'Notepad', notepad, false)) then
    _plugin_logputs('[MapMaster] ErroR Registering The "Notepad" command! ');
  // Add Plugin info
  _plugin_logprintf('[***] %s Plugin v%i by %s '#10, PLUGIN_NAME, PLUGIN_VERS, PLUGIN_AUTH);
end;

function x_dbg_plugstop(): Boolean; cdecl;
begin
  //
  _plugin_unregistercallback(g_pluginHandle, CB_MENUENTRY);
  _plugin_unregistercallback(g_pluginHandle, CB_INITDEBUG);
  Result := True;
end;

procedure Super; stdcall;
begin
  Application.MessageBox(PWideChar('我被调用啦!!!'), PWideChar('你好'), 0);     ===>这句没问题被执行了!
  DbgCmdExec(PAnsiChar(AnsiString('StepOver')));                                           ========》这句死活没动静!
end;

exports
  Super,                                                    ============>导出了!
  x_dbg_Plugininit name 'pluginit',
  x_dbg_Pluginsetup name 'plugsetup',
  x_dbg_plugstop name 'plugstop';

procedure DLLEntryPoint(dwReason: DWORD);
var
  szPluginName: array[0..MAX_PATH - 1] of ACHAR;
begin
  if (dwReason = DLL_PROCESS_DETACH) then
  begin
    lstrcatA(szPluginName, PLUGIN_NAME);
    lstrcatA(szPluginName, ' Unloaded By DLL_PROCESS_DETACH');
    OutputDebugStringA(szPluginName);
  end;
  if Assigned(SaveDLLProc) then
    SaveDLLProc(dwReason);
end;

begin
  g_Inst := HInstance;
  SaveDLLProc := @DLLProc;
  DLLProc := @DLLEntryPoint;
  Application.MessageBox(PWideChar('执行成功'), PWideChar('你好'), 0);
end.




主程序 Project.exe中调用DLL的代码是:

[Delphi] 纯文本查看 复制代码
unit Unit2;
interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  Vcl.StdCtrls;

type
  TForm2 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

uses
  bridgemain, _plugins;

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);   {下面是调用的关键代码}
var
  My: procedure; stdcall;
var
  Hand: Cardinal;
begin
  Hand := LoadLibrary('C:\Users\Administrator\Desktop\Mdebug32\x64dbg_2023-08-01\x64\plugins\MoreTool.dp64');
  if Hand <> 0 then
  begin
    ShowMessage(Hand.ToString);
    My := GetProcAddress(Hand, 'Super');
//    DbgCmdExec(PAnsiChar(AnsiString('StepOver')));    直接调用肯定完犊子!!!
  end;

end;

end.


为什么呢? 不解?
only998 发表于 2023-8-11 10:52
冥界3大法王 发表于 2023-8-11 10:39
@only998
正好老兄在场,借机问个同类型的问题吧!

dp64依赖的是 x64dbg里的实现,我没深入研究过,崩溃的原因无非两点,一是dp64需要exe里的某些实现,你没有程序就崩溃。二是dp64依赖于其他x64dbg目录下的dll,你没有,也崩溃。注意你自己加载的话,工作目录跟x64dbg是不一样的。
我认为.dp64不可能脱离x64dbg的,如果想要单exe实现某些操作,直接调用系统函数更好一点。
seeyou_shj 发表于 2023-8-11 10:53
seeyou_shj 发表于 2023-8-11 10:16
以前写过一片关于dll文件的内容,很简单,不过似乎可以解答你的问题。去看看吧。用的是mingw编译器。

ht ...

https://learn.microsoft.com/zh-cn/windows/win32/dlls/dllmain?redirectedfrom=MSDN
看看这个
aonima 发表于 2023-8-11 10:55
感觉没什么用,dll加载卸载由系统调用的
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 19:27

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表