吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

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

[其他转载] 实现Win10下Delphi 10.3.1 inline hook 修改Mac网卡地址之GetAdaptersAddresses

[复制链接]
bester 发表于 2019-8-9 15:01
首先感谢@wujiakang 帮我解决在C++中GetAdaptersAddresses的调用问题,否则的话我在Delphi中也是没办法使用的,断断续续用Delphi进行inline hook写了一个星期之久,今天才得以全部修改完毕,然后昨晚用E去调用api又出现各种问题,幸好有前辈写了E的hook,借鉴了前辈调用api的方法,修改之。
不禁感慨,易语言局限性还是很大,写这类结构体的函数hook,更是头疼,类型需要自定义,还需要内存覆盖,无法直接输出unicode等等,但是也从中学到了很多手法,这样能在其他编程语言中如鱼得水。

易语言未HOOK调用:
QQ截图20190809145711.jpg

易语言HOOK调用后:
QQ截图20190809150022.jpg

Delphi源码:
[Delphi] 纯文本查看 复制代码
library Project1;
{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }

uses
  System.SysUtils,
  System.Classes,
  iphlpapi,         //加载iphlpapi库,不然无法调用GetAdaptersAddresses这个API
  Winapi.Windows,  //加载常用API库,不然无法调用读写内存等等之类的api
  Winapi.IpTypes; //加载IpTypes库,不然无法声明PIP_ADAPTER_ADDRESSES这个结构体的类型


function MyMoveMemo(old: Pointer; New: Pointer; size: Integer): integer; stdcall; external 'kernel32.dll' name 'RtlMoveMemory';     //内存移动复制函数,让我们自定义的MAC地址覆盖掉程序取的MAC地址

{$R *.res}
var
  read: array[0..4] of Byte;  //保存的API的头部5个字节,方便还原
  rd: NativeUInt;   //读内存API函数的最后一个参数
  apiaddr: Integer;       //API首地址
  mac1: array[0..7] of Byte = (1, 2, 3, 4, 5, 6, 7, 8);  //这里我定义MAC地址为12345678,刚好8个长度,然而我们真实的MAC是6个长度,末尾是两个0,我不排除有8个长度的MAC,只是在我这是6个


// 参数:权限名称 ,返回: 成功返回TRUE
Function AdjustProcessPrivilege(Token_Name: Pchar): Boolean;
var
  Token: THandle;
  TokenPri: TOKEN_PRIVILEGES;
  ProcessDest: int64;
  PreSta: DWORD;
begin
  Result := False;
  if OpenProcessToken(GetCurrentProcess,TOKEN_ADJUST_PRIVILEGES,Token) then
    begin
      if LookupPrivilegeValue(nil,Token_Name,ProcessDest) then
        begin
          TokenPri.PrivilegeCount := 1;
          TokenPri.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
          TokenPri.Privileges[0].Luid := ProcessDest;
          PreSta := 0;
          if AdjustTokenPrivileges(Token,False,TokenPri,sizeof(TokenPri),nil,PreSta) then
            begin
              Result := True;
            end;
        end;
    end;
end;


function MyGet(Family: ULONG; Flags: DWORD; Reserved: PVOID;pAdapterAddresses: PIP_ADAPTER_ADDRESSES; pOutBufLen: PULONG):DWORD;stdcall;      //我们构造的函数,从API头跳到我们这个函数当中,方便我们做事
var
  I: Integer;     //循环次数变量,每次都要写入1个字节,还原API头
  reads: byte;   //取出我们保存的5个字节,然后循环写入
begin
  for I := 1 to 5 do
  begin
    reads := read[I - 1];   //因为数组下标从0开始,I是从1开始,则用I-1
    WriteProcessMemory(GetCurrentProcess, Pointer(apiaddr + I - 1), Pointer(@reads), 1, rd);
  end;
  GetAdaptersAddresses(Family, Flags, nil, pAdapterAddresses, pOutBufLen);          //调用原函数,让pAdapterAddresses里面有内容,如果不调用,pAdapterAddresses里面是空的,是没有任何东西的
  MyMoveMemo(@pAdapterAddresses.PhysicalAddress, @mac1, 8)  //然后我们用我们自定义的内容,去覆盖掉原先里面的MAC地址
end;

function lens(x, y: Integer): Integer;              //取跳转长度
begin
  Result := x - y - 5;
end;
procedure MyMian();                               //将HOOK操作封装成一个过程,我称为MyMain
var
  paddr: PIP_ADAPTER_ADDRESSES;
  jmps: Integer;
  lengths: Integer;
  outbuf:Integer;
begin
  AdjustProcessPrivilege('SeDebugPrivilege');      //提权函数,不用管 ,可以不写,但是如果写入内存失败,就要用提权,我这边测试可以不用提权也能写入
  apiaddr := Integer(GetProcAddress(LoadLibrary('iphlpapi.dll'), 'GetAdaptersAddresses'));  //获取API地址
  ReadProcessMemory(GetCurrentProcess, Pointer(apiaddr), Pointer(@read), 5, rd);           //读前5个字节
  jmps := 233;                                                                             //这里是jmp的10进制,16进制的E9
  lengths := lens(Integer(@MyGet), apiaddr);                                               //计算长度
  WriteProcessMemory(GetCurrentProcess, Pointer(apiaddr), Pointer(@jmps), 1, rd);          //开始写入jmp
  WriteProcessMemory(GetCurrentProcess, Pointer(apiaddr + 1), Pointer(@lengths), 4, rd);   //开始写入长度
//  paddr := AllocMem(SizeOf(PIP_ADAPTER_ADDRESSES));
//  outbuf := 15000;
//  GetAdaptersAddresses(0, 16 or 128, nil, paddr, @outbuf)                                //这里我将调用API的方法注释掉,因为我们是DLL,是不需要调用的,是由EXE调用
                                                                                           //首先说一下他的5个参,具体可MS文档搜索,这里只是大致通俗说一下
                                                                                           //第一个参数是0,第二个参数是16和128,如果我们写16 or 128实际上写入的数值是144,也就是两者之和,所以我为了能看懂,就没有写144,而是分开
                                                                                           //第三个是保留段,直接留空
                                                                                           //第四个就是我们重点,是一个结构体,也就是自定义数据类型PIP_ADAPTER_ADDRESSES, 我们要首先申请一段内存,然后进行0填充初始化,如果不申请内存就无法写入
                                                                                           //第五个是实际写入的大小,是一个指针类型,他的值MS文档定义成15000,所以我们为第四个参数申请的大小也要为15000
end;
begin
   MyMian;                                                                                 //这里是DLLmain,会首先调用这里,所以我们这里直接将HOOK封装成一个过程,然后直接调用这个过程
end.

免费评分

参与人数 3吾爱币 +6 热心值 +3 收起 理由
cosct + 1 + 1 用心讨论,共获提升!
苏紫方璇 + 5 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
wz_2000 + 1 谢谢@Thanks!

查看全部评分

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

 楼主| bester 发表于 2019-8-9 15:05
易语言调用与HOOK.rar (349.22 KB, 下载次数: 498)
saomu007 发表于 2019-8-9 15:24
Titanic 发表于 2019-8-9 15:38
ps122 发表于 2019-8-9 16:00
谢谢分享,支持win7吗?
yingwl 发表于 2019-8-10 09:09
谢谢分享
asong 发表于 2019-8-17 11:30
DELPHI的资源好奇缺.感谢分享!
我是流氓 发表于 2020-3-23 18:46
谢谢楼主
wdyichen 发表于 2020-12-2 17:29
感谢楼主无私分享
望尘莫及 发表于 2020-12-23 16:52
谢谢大佬分享。正好用得上。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-25 19:39

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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