HanDs
管理员

[Delphi文章] delphi编写驱动注入dll 



unit DelphiApcInjectDll;
{$HINTS OFF}
{$WARNINGS OFF}
interface

uses
  nt_status, ntoskrnl, native, winioctl, fcall, macros;

const
  DeviceName = '\Device\ApcInject'; ///设备名
  DosDeviceName = '\??\ApcInject'; ///符号链接名
  NtKernel = 'ntoskrnl.exe';
  SystemProcessesAndThreadsInformation = 05;
  PS_CROSS_THREAD_FLAGS_SYSTEM = $10;
  MAX_PID = 65535;

type
  KAPC_ENVIRONMENT = (OriginalApcEnvironment, AttachedApcEnvironment, CurrentApcEnvironment);
  MODE = (KernelMode, UserMode, MaximumMode);
  KPRIORITY = LONG;
  PKAPC_STATE = ^KAPC_STATE;
  KAPC_STATE = packed record
    ApcListHead: array[0..1] of TListEntry;
    Process: PVOID;
    KernelApcInProgress: boolean;
    KernelApcPending: boolean;
    UserApcPending: boolean;
  end;

  PAnsiString = ^TAnsiString;
  TAnsiString = packed record
    Length: Word;
    MaximumLength: Word;
    Buffer: PChar;
  end;
  PKNORMAL_ROUTINE = procedure(NormalContext, SystemArgument1, SystemArgument2: PVOID); stdcall;
  PKRUNDOWN_ROUTINE = procedure(Apc: PKAPC); stdcall;
  PKKERNEL_ROUTINE = procedure(Apc: PKAPC; NormalRoutine: PKNORMAL_ROUTINE; NormalContext, SystemArgument1, SystemArgument2: PVOID); stdcall;

function _DriverEntry(pDriverObject: PDRIVER_OBJECT; pusRegistryPath: PUNICODE_STRING): NTSTATUS; stdcall;

function KeStackAttachProcess(Process: PVOID; ApcState: PKAPC_STATE): NTSTATUS; stdcall; external NtKernel name '_KeStackAttachProcess';
function KeUnstackDetachProcess(ApcState: PKAPC_STATE): NTSTATUS; stdcall; external NtKernel name '_KeUnstackDetachProcess';
function PsGetProcessImageFileName(Process: PVOID): PUCHAR; stdcall; external NtKernel name '_PsGetProcessImageFileName';
function KeGetCurrentThread(): PKThread; stdcall; external NtKernel name '_KeGetCurrentThread';
function PsGetCurrentThread(): PEThread; stdcall; external NtKernel name '_PsGetCurrentThread';
function PsGetCurrentProcessId(): HANDLE; stdcall; external NtKernel name '_PsGetCurrentProcessId';
procedure ObDereferenceObject(MyObject: PVOID); stdcall; external NtKernel name '_ObDereferenceObject';
function PsTerminateSystemThread(ExitStatus: NTSTATUS): NTSTATUS; external NtKernel name '_PsTerminateSystemThread';

type
  TPSGETNEXTPROCESSTHREAD = function(Process: pvoid; Thread: PETHREAD): PETHREAD; stdcall;


function KeInitializeApc(
  Apc: PKAPC;
  Thread: PVOID;
  Environment: KAPC_ENVIRONMENT;
  KernelRoutine: PKKERNEL_ROUTINE;
  RundownRoutine: PKRUNDOWN_ROUTINE;
  NormalRoutine: PKNORMAL_ROUTINE;
  ProcessorMode: KPROCESSOR_MODE;
  NormalContext: PVOID
  ): NTSTATUS; stdcall; external NtKernel name '_KeInitializeApc';

function KeInsertQueueApc(
  Apc: PKAPC;
  SystemArgument1: PVOID;
  SystemArgument2: PVOID;
  Increment: KPRIORITY
  ): NTSTATUS; stdcall; external NtKernel name '_KeInsertQueueApc';

var
  g_usDeviceName, g_usSymbolicLinkName: UNICODE_STRING;
  Mdl: PMDL;


implementation


procedure ApcCreateProcess(NormalContext: PVOID; SystemArgument1: PVOID; SystemArgument2: PVOID); stdcall;
begin
  asm
    //我的机器的loadlibrary的地址
   mov eax,$7C801d77
     nop//-------sysnap注:这些nop是保证前面 memset ((unsigned char*)pMappedAddress + 0x14, 0, 300);之类的正常:
     //如果改成执行其他函数,注意这些NOP与前面的0x14之类的是否对应
   nop
   nop
   push $abcd //因为用户程序无法访问内核空间,所以路径不能直接引用lpProcess
   call eax
  jmp @@label

  nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
@@label:
   nop
ret $0c
  end;

end;

procedure ApcCreateProcessEnd; stdcall;
begin
end;


function ApcKernelRoutine(
  Apc: PKAPC;
  NormalRoutine: PKNORMAL_ROUTINE;
  NormalContext: PVOID;
  SystemArgument1: PVOID;
  SystemArgument2: PVOID
  ): Ulong; stdcall;
begin
  ExFreePool(Apc);
  if (Mdl <> nil) then
  begin
    MmUnlockPages(Mdl);
    IoFreeMdl(Mdl);
    Mdl := nil;
  end;
  DbgPrint('ApcKernelRoutine called. Memory freed.');
end;


function InstallUserModeApc(DllFullPath: pchar; pTargetThread: ULONG; pTargetProcess: ULONG): NTSTATUS;
var
  Apc: PKAPC;
  pMappedAddress: pvoid;
  dwSize: ulong;
  ApcState: KAPC_STATE;
  dwMappedAddress: ulong;
  Status: NTSTATUS;
  data_addr: pulong;
begin
  Status := STATUS_UNSUCCESSFUL;
  Apc := nil;
  pMappedAddress := nil;
  dwSize := 0;
  dwMappedAddress := 0;
  if (pTargetThread = 0) or (pTargetProcess = 0) then result := STATUS_UNSUCCESSFUL;
  Apc := ExAllocatePool(NonPagedPool, sizeof(KAPC));
  dwSize := DWORD(@ApcCreateProcessEnd) - DWORD(@ApcCreateProcess);
  //之所以加3,是因为delphi会自动在过程前加push ebp ,mov esp,ebp三个字节
  Mdl := IoAllocateMdl(pvoid(DWORD(@ApcCreateProcess)+3), dwSize, FALSE, FALSE, nil);
  if Mdl = nil then
  begin
    DbgPrint(' Failed to allocate MDL');
    ExFreePool(Apc);
    result := STATUS_INSUFFICIENT_RESOURCES;
  end;

  MmProbeAndLockPages(Mdl, 0, IoWriteAccess);

  KeStackAttachProcess(pulong(pTargetProcess), @ApcState);
  pMappedAddress := MmMapLockedPagesSpecifyCache(Mdl, 1, MmCached, nil, 0, NormalPagePriority);

  if (pMappedAddress = nil) then
  begin
    DbgPrint('Cannot map address');
    KeUnstackDetachProcess(@ApcState);
    IoFreeMdl(Mdl);
    ExFreePool(Apc);
    result := STATUS_UNSUCCESSFUL;
  end
  else
    DbgPrint('UserMode memory at address: 0x%p', pMappedAddress);
  dwMappedAddress := ULONG(pMappedAddress);
  memset(pchar(pMappedAddress) + $14, 0, 100); //zero everything out ecxept our assembler code
  memcpy(pchar(pMappedAddress) + $14, DllFullPath, strlen(DllFullPath)); //copy the path to the executable

  PULONG(ulong(pchar(pMappedAddress) + $9))^ := dwMappedAddress + $14;
  DbgPrint('pTargetThread iiis:%x', pTargetThread);

  KeUnstackDetachProcess(@ApcState);
  KeInitializeApc(Apc, pulong(pTargetThread), OriginalApcEnvironment, @ApcKernelRoutine, nil, pMappedAddress, KPROCESSOR_MODE(UserMode), nil);
  if not (BOOLEAN(KeInsertQueueApc(Apc, PVOID(0), PVOID(0), 0))) then
  begin
    DbgPrint('KernelExec -> Failed to insert APC');
    MmUnlockPages(Mdl);
    IoFreeMdl(Mdl);
    ExFreePool(Apc);
    result := STATUS_UNSUCCESSFUL;
  end else
    DbgPrint('APC delivered');


  if (pbyte(ulong(pTargetThread + $4A))^ = 0) then
    pbyte(ulong(pTargetThread + $4A))^ := 1;


end;


procedure InjectDll(DllFullPath: pchar; ProcessName: pchar);
var
  pTargetProcess: ULONG;
  pTargetThread: ULONG;
  pNotAlertableThread: ULONG;
  pSystemProcess: ULONG;
  pTempThread: ULONG;
  pNextEntry, pListHead, pThNextEntry, pThListHead: ULONG;
  pid: ULONG;
  EProcess: pvoid;
  status: NTSTATUS;
begin
  pid := 0;
  while pid <= MAX_PID do
  begin
    status := PsLookupProcessByProcessId(pid, EProcess);
    if (NT_SUCCESS(status)) then
    begin
      if (_stricmp(pchar(PsGetProcessImageFileName(EProcess)), ProcessName) = 0) then
      begin
       //DbgPrint('pid is:%x', pid);
        pSystemProcess := ULONG(EProcess);
        pTargetProcess := pSystemProcess;
        //DbgPrint('pSystemProcess is:%x', pSystemProcess);
        pTargetThread := 0;
        pNotAlertableThread := 0;
        pThListHead := pSystemProcess + $50;
        pThNextEntry := PULONG(ulong(pThListHead))^;
        //DbgPrint('pThNextEntry is:%x', pThNextEntry);
        while (pThNextEntry <> pThListHead) do
        begin
          pTempThread := pThNextEntry - $1B0; //ETHREAD
          //DbgPrint('pTempThread is:%x', pTempThread);
          //DbgPrint('(pTempThread + $164) is:%x', PULONG(ULONG(pTempThread + $164))^);
          //以下寻找受信进程
          if ULONG(PULONG(ULONG(pTempThread + $164))^) = $10001 then
          begin
            pTargetThread := pTempThread;
            break;
          end else
            pNotAlertableThread := pTempThread;

          pThNextEntry := PULONG(ulong(pThNextEntry))^;
        end;
        break;
      end;
    end;
    pid := pid + 4;
  end;
  DbgPrint('pTargetThread issssssssssssssss:%x', pTargetThread);
  if (pTargetThread <> 0) then
  begin
    InstallUserModeApc(DllFullPath, pTargetThread, pTargetProcess);
  end else
    DbgPrint(' No thread found!');
end;


function DispatchCreateClose(p_DeviceObject: PDEVICE_OBJECT; p_Irp: PIRP): NTSTATUS; stdcall; ///对打开或关闭请求的响应 ,这里就是简单的返回一个成功
begin
  p_Irp^.IoStatus.Status := STATUS_SUCCESS; ///设置状态为STATUS_SUCCESS 即成功
  p_Irp^.IoStatus.Information := 0;
  IofCompleteRequest(p_Irp, IO_NO_INCREMENT); ///调用IoCompleteRequest完成IRP
  Result := STATUS_SUCCESS;
end;

procedure DriverUnload(p_DriverObject: PDRIVER_OBJECT); stdcall;
begin
  DbgPrint('Driver Unload!'); ///输出调试字符串
  IoDeleteSymbolicLink(@g_usSymbolicLinkName); ///删除我们创建的符号链接
  IoDeleteDevice(p_DriverObject^.DeviceObject); ///删除我们创建的设备
end;

///驱动入口点

function _DriverEntry(pDriverObject: PDRIVER_OBJECT; pusRegistryPath: PUNICODE_STRING): NTSTATUS;
var
  status: NTSTATUS;
  mypid: ulong;
  DeviceObject: TDeviceObject;
begin
  status := STATUS_DEVICE_CONFIGURATION_ERROR;
  ///初始化UNICODE_STRING结构
  RtlInitUnicodeString(g_usDeviceName, DeviceName);
  RtlInitUnicodeString(g_usSymbolicLinkName, DosDeviceName);

  if (IoCreateDevice(pDriverObject, 0, @g_usDeviceName,
    FILE_DEVICE_UNKNOWN, 0, FALSE,
    DeviceObject) = STATUS_SUCCESS) then
  begin
    ///如果创建成功
    DbgPrint('Create Device Success'); ///输出调试字符串
    ///创建符号链接
    if (IoCreateSymbolicLink(@g_usSymbolicLinkName,
      @g_usDeviceName) = STATUS_SUCCESS) then
    begin
      ///如果创建符号链接成功执行下面的代码
      DbgPrint('Create SymbolicLink Success'); ///输出调试字符串
      ///开始设置我们自己的分发函数
      pDriverObject^.MajorFunction[IRP_MJ_CREATE] := @DispatchCreateClose; ///这里把IRP_MJ_CREATE IRP_MJ_CLOSE设置到一个函数上
      pDriverObject^.MajorFunction[IRP_MJ_CLOSE] := @DispatchCreateClose;
      pDriverObject^.DriverUnload := @DriverUnload; ///当驱动动态卸载时执行DriverUnload
      status := STATUS_SUCCESS; ///返回STATUS_SUCCESS;
    end else ///如果创建符号链接不成功
    begin
      DbgPrint('Create SymbolicLink Failed'); ///输出调试字符串
      IoDeleteDevice(@DeviceObject); ///删除设备
    end;
  end;
  InjectDll('c:\sysnap.dll', 'explorer.exe');
  Result := status;
end;

end.


学习中请遵守法律法规,本网站内容均来自于互联网,本网站不负担法律责任
delphi 编写驱动注入 dll
#1楼
发帖时间:2016-7-9   |   查看数:0   |   回复数:0
游客组
快速回复