Guest User

Untitled

a guest
Nov 9th, 2014
262
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 13.74 KB | None | 0 0
  1. program DOP;
  2. Uses
  3.  Windows;
  4. Const
  5.  FileName = 'c:\tmp\test.exe';     //Путь и имя проги к которой добавляем.
  6.  RAZMER = $400;                    //Размер добавляемой секции (1Кб).
  7. Type
  8.  TSect = packed record
  9.    Name: Array [0..7] of Char;     //Имя секции.
  10.    S_VSiz: DWORD;                  //Виртуальный размер.
  11.    S_RVA: DWORD;                   //Виртувльное смещение.
  12.    S_FSiz: DWORD;                  //Размер в файле.
  13.    S_FOfs: DWORD;                  //Смещение в файле.
  14.    S_Res: Array [0..11] of Byte;   //Не используем.
  15.    S_Flag: DWORD;                  //Флаг секции.
  16.  end;
  17.  TStrTI = packed record
  18.    ImpLookUp: DWORD;               //Указатель на таблицу указателей.
  19.    DateStamp: DWORD;               //Время добавления.
  20.    Chain: DWORD;                   //Не используем = FFFFFFFFh.
  21.    NameDll: DWORD;                 //RVA указатель на имя файла DLL.
  22.    AddrTabl: DWORD;                //Указатель на вторую таблицу указателей (IAT).
  23.  end;
  24. Var
  25.  F: THandle;               //Хендл файла.
  26.  Sect, NewSect: TSect;     //Структуры секций.
  27.  StrTI: Array of TStrTI;   //Структурa строк табл. импорта.
  28.  DStrTI: TStrTI;           //Структура добавляемой строки в табл.импорта.
  29.  AdrPE, EP, ImBase, S_Align, F_Align, ImSize, RVA_TI, br: DWORD; //Нужные параметры заголовка.
  30.  minS_FOfs: DWORD;           //Мин. смещение секции в файле (для проверки).
  31.  maxS_RVA, maxS_VSiz: DWORD; //Параметры секции с макс. виртуал. смещ.
  32.  TIS_RVA, TIS_FOfs: DWORD;   //Пароаметры секции с табл. импорта.
  33.  NewS_RVA, NewS_FOfs: DWORD; //Пароаметры добавляемой секции.
  34.  RVA_FUN, RVA_Dll, RVA_IAT: DWORD;  //Виртуальный адрес функции, модуля и таблицы IAT.
  35.  CloseIAT: DWORD = $00000000; //Для закрытия IAT.
  36.  Zero: Byte = $00; //Данные пустой секции (0).
  37.  N_Sect: WORD;     //К-во секций.
  38.  FS: DWORD;        //Размер файла.
  39.  i, k : Integer;   //Счётчик секций и строк т.и.
  40.  Kernel: Array [0..12] of Byte = ($4B,$65,$72,$6E,$65,$6C,$33,$32,$2E,$64,$6C,$6C,$00);  //Kernel32.dll#
  41.  BEEP: Array [0..6] of Byte = ($00,$00,$42,$65,$65,$70,$00); //##Beep# (ф-нц пикалка находиться в кернеле).
  42.  OfSet_TI: DWORD;  //Смещение табл. импорта в файле.
  43.  Atr: DWORD = $E0000020; //Атрибут: cекция является кодовой, имеет разрешения на исполнение, чтение и запись.
  44.  //Опкоды берём в любом дизасме.
  45.  PushOpCod: Byte = $68;              //Опкод машинной команды Push #;
  46.  CallOpCod: WORD = $15FF;            //Опкод машинной команды Call DwordPtr [#];
  47.  Mov_EAX_OpCod: Byte = $B8;          //Опкод машинной команды Mov EAX, #;
  48.  Jmp_EAX_OpCod: WORD = $E0FF;        //Опкод машинной команды Jmp EAX;
  49.  Frec: DWORD = $00000200;            //Частота звука = 512 Гц.
  50.  Time: DWORD = $000003E8;            //Длительность звучания = 1000 мc.
  51. Begin
  52.  AdrPE:= 0; maxS_VSiz:= 0; TIS_RVA:= 0; TIS_FOfs:= 0;   //Инициализация переменных.
  53.  F:= CreateFile(FileName, GENERIC_READ or GENERIC_WRITE,
  54.                 FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
  55.                 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,0);
  56.  if F = INVALID_HANDLE_VALUE Then Exit; //При ошибке выход.
  57.  SetFilePointer(F, $3C, nil, FILE_BEGIN); //Ставим указатель на адрес смещения РЕ заголовка.
  58.  ReadFile(F, AdrPE, 4, br, nil);    //Узнаём смещение РЕ.
  59.  SetFilePointer(F, AdrPE + $06, nil, FILE_BEGIN);
  60.  ReadFile(F, N_Sect, 2, br, nil);   //К-во секций.
  61.  SetFilePointer(F, AdrPE + $28, nil, FILE_BEGIN);
  62.  ReadFile(F, EP, 4, br, nil);       //Точка входа.
  63.  SetFilePointer(F, AdrPE + $34, nil, FILE_BEGIN);
  64.  ReadFile(F, ImBase, 4, br, nil);   //Базовый адрес загрузки.
  65.  SetFilePointer(F, AdrPE + $38, nil, FILE_BEGIN);
  66.  ReadFile(F, S_Align, 4, br, nil);  //Выравнивание секций в памяти.
  67.  ReadFile(F, F_Align, 4, br, nil);  //Выравнивание секций на диске.
  68.  SetFilePointer(F, AdrPE + $80, nil, FILE_BEGIN);
  69.  ReadFile(F, RVA_TI, 4, br, nil);   //RVA таблицы импорта.
  70.  SetFilePointer(F, AdrPE + $F8, nil, FILE_BEGIN);
  71.  minS_FOfs:= $FFFFFFFF;           //Начальные значения поиска.
  72.  maxS_RVA:=  $00000000;
  73. For i:= 1 To N_Sect Do
  74.  begin      //Читаем секции по очереди.
  75.   ReadFile(F, Sect, SizeOf(Sect), br, nil);
  76.             //Находим секцию с мин. смещением в файле.
  77.   if (Sect.S_FOfs > 0) and (Sect.S_FOfs <= minS_FOfs) Then
  78.    minS_FOfs:= Sect.S_FOfs; //Сохраняем мин. смещение (нужно для проверки добав. секции).
  79.   if (Sect.S_RVA > 0) and (Sect.S_RVA >= maxS_RVA) Then
  80.    begin    //Находим секцию с макс виртуальным смещением.
  81.    maxS_RVA:= Sect.S_RVA;   //Сохраняем её параметры
  82.    maxS_VSiz:= Sect.S_VSiz; //(нужны для добавления новой секции).
  83.    end;     //Находим секцию в которой расположена табл. импорта.
  84.   if (Sect.S_RVA <= RVA_TI) and (RVA_TI <= (Sect.S_RVA + Sect.S_VSiz)) Then
  85.    begin
  86.    TIS_RVA:= Sect.S_RVA;    //Сохраняем её параметры
  87.    TIS_FOfs:= Sect.S_FOfs;  //(нужны для копирования табл. импорта).
  88.    end;
  89.  end;                   //Проверяем: можно добавить секцию или нет.
  90. //(мин.смещ.секции-(смещ.РЕ+Размер_РЕ+(К-во_секций*Размер_одной_секции)))>=размер_добав.секции.
  91. if (minS_FOfs - (AdrPE + $F8 + (N_Sect * $28))) >= $28 Then
  92.  begin                  //если да то новая секция влезет в табл. секций, если нет - выход.
  93.   FS:= GetFileSize(F, nil); //Узнаём размер файла.
  94.   //Выравневаем новую секцию в памяти по значеию S_Align.
  95.   if ((maxS_RVA + maxS_VSiz) mod S_Align) = 0 Then NewS_RVA:= maxS_RVA + maxS_VSiz
  96.   Else NewS_RVA:= (((maxS_RVA + maxS_VSiz) div S_Align) + 1) * S_Align;
  97.   //Выравневаем новую секцию в файле по значеию F_Align.
  98.   if (FS mod F_Align) = 0 Then NewS_FOfs:= FS
  99.   Else NewS_FOfs:= ((FS div F_Align) + 1) * F_Align;
  100.   //Добавляем секцию.
  101.   NewSect.Name[0]:= '.';
  102.   NewSect.Name[1]:= 'N';
  103.   NewSect.Name[2]:= 'e';
  104.   NewSect.Name[3]:= 'w';      //Имя секции (произвольное).
  105.   NewSect.Name[4]:= 'S';
  106.   NewSect.Name[5]:= 'e';
  107.   NewSect.Name[6]:= 'c';
  108.   NewSect.Name[7]:= 't';
  109.   NewSect.S_RVA:= NewS_RVA;   //Начало новой секции в памяти.
  110.   NewSect.S_VSiz:= RAZMER;    //Размер новой секции в памяти.
  111.   NewSect.S_FOfs:= NewS_FOfs; //Смещение новой секции в файле.
  112.   NewSect.S_FSiz:= RAZMER;    //Размер новой секции в файле.
  113.   NewSect.S_Flag:= Atr;       //Атрибут секции.
  114.   //Запишим нашу созданную секцию в табл. секций в файле.
  115.              //Смещение_РЕ + Его_размер + (к-во_секций * размер_одной).
  116.   SetFilePointer(F, (AdrPE + $F8 + (N_Sect * $28)), nil, FILE_BEGIN);
  117.   WriteFile(F, NewSect, SizeOf(NewSect), br, nil); //Записали.
  118.   //Заполним нашу секцию в файле нулями.
  119.   //Ставим указатель на предпоследний байт в файле и пишем 0.
  120.   //До указателя всё автоматически заполняеться нулями.
  121.   SetFilePointer(F, (NewS_FOfs + RAZMER)-1, nil, FILE_BEGIN);
  122.   WriteFile(F, Zero, 1, br, nil);
  123.   //Корректируем к-во секций в заголовке.
  124.   SetFilePointer(F, AdrPE + $06, nil, FILE_BEGIN);
  125.   N_Sect:= N_Sect + 1;        //К-во секций + ещё одна.
  126.   WriteFile(F, N_Sect, 2, br, nil);
  127.   //Корректируем размер загружаемого образа в заголовке.
  128.   SetFilePointer(F, AdrPE + $50, nil, FILE_BEGIN);
  129.   ImSize:= NewS_RVA + RAZMER;   //Общий объём виртуальной памяти.
  130.   WriteFile(F, ImSize, 4, br, nil);
  131.   //Далее записываем мини программу в нашу секцию.
  132.   //Добавляем в начало нашей секции имя модуля (dll), имя функции, таблицу IAT, переносим в неё
  133.   //(табл. импорта + наша ф-нц), код вызова функции и код передачи управл. проге к которой дописались.
  134.   SetFilePointer(F, NewS_FOfs, nil, FILE_BEGIN);//Указатель на нашу секцию.
  135.   WriteFile(F, Kernel, 13, br, nil); //Записали имя модуля (dll) с которой импортируем ф-нц.
  136.   RVA_Dll:= NewS_RVA;                //Запомним RVA нашего модуля = RVA секции.
  137.   WriteFile(F, BEEP, 7, br, nil);    //Записали имя функции.
  138.   RVA_FUN:= NewS_RVA + 13;           //Запомним RVA функции.
  139.   WriteFile(F, RVA_FUN, 4, br, nil); //Записали в IAT RVA функции.
  140.   WriteFile(F, CloseIAT, 4, br, nil);//Закрыли IAT 0000 0000.
  141.   RVA_IAT:= NewS_RVA + 13 + 7;       //Запомним RVA IAT.
  142.   //Создаём добавочную строку табл. импорта. (заполняем структуру).
  143.   DStrTI.ImpLookUp:= RVA_IAT;       //RVA таблицы указателей 1.
  144.   DStrTI.DateStamp:= $FFFFFFFF;     //Макс. время создания.
  145.   DStrTI.Chain:= $FFFFFFFF;         //Просто ФФФФФФФФ.
  146.   DStrTI.NameDll:= RVA_Dll;         //RVA строки с именем файла DLL.
  147.   DStrTI.AddrTabl:= RVA_IAT;        //RVA таблицы указателей 2.
  148.   WriteFile(F, DStrTI, SizeOf(DStrTI), br, nil); //Записали добавочную строку т.и.
  149.   //Далее копируем в свою секцию табл. импорта.
  150.   OfSet_TI:= RVA_TI - TIS_RVA + TIS_FOfs;     //Смещение т.и в файле.
  151.   SetFilePointer(F, OfSet_TI, nil, FILE_BEGIN); //Указатель на т.и. в файле.
  152.   k:= -1;
  153.   Repeat //Считуем т.и построчно пока не нарвёмся на строку с нулями (конец т.и).
  154.   begin
  155.   Inc(k);//Счётчик строк в т.и.
  156.   SetLength(StrTI, k + 1);  //Установка размера масива строк т.и.
  157.   ReadFile(F, StrTI[k], SizeOf(StrTI[k]), br, nil);   //Считуем строку в масив.
  158.   end;
  159.   Until (StrTI[k].NameDll = 0) and (StrTI[k].AddrTabl = 0); //Проверка на строки с нулями.
  160.             //Смещение_секции + размер_Kernel + размер_BEEP + размер_IAT + размер_нашей_строки_в_т.и.
  161.   SetFilePointer(F, NewS_FOfs + 13 + 7 + 8 + 20, nil, FILE_BEGIN);
  162.   For i:= 0 To k - 1 Do WriteFile(F, StrTI[i], SizeOf(StrTI[i]), br, nil); //Комируем т.и.
  163.   RVA_TI:= NewS_RVA + 13 + 7 + 8; //Виртуальное_смещение_секции + размер_Kernel + размер_BEEP + размер_IAT.
  164.   //Корректируем смещение т.и. в заголовке.
  165.   SetFilePointer(F, AdrPE + $80, nil, FILE_BEGIN);
  166.   WriteFile(F, RVA_TI, 4, br, nil);
  167.   RVA_IAT:= RVA_IAT + ImBase; //Узнаём виртуальный адрес IAT при загрузке в память.
  168.   EP:= EP + ImBase;           //Узнаём адрес точкивхода при загрузке в память.
  169.   //Записуем код после т.и.
  170. //Смещение_секции + размер_Kernel + размер_BEEP + размер_IAT + размер_нашей_строки_в_т.и. + ((к-во_строк_т.и + одна_с_нулями) * размер строки).
  171.   SetFilePointer(F, NewS_FOfs + 13 + 7 + 8 + 20 + ((k+1) * 20), nil, FILE_BEGIN);
  172.   //Опкоды машинных команд и операнды.
  173.   WriteFile(F, PushOpCod, 1, br, nil); WriteFile(F, Time, 4, br, nil);    //Push Time;            //Помещаем в стек Time.
  174.   WriteFile(F, PushOpCod, 1, br, nil); WriteFile(F, Frec, 4, br, nil);    //Push Frec;            //Помещаем в стек Frec.
  175.   WriteFile(F, CallOpCod, 2, br, nil); WriteFile(F, RVA_IAT, 4, br, nil); //Call Dword Ptr [IAT]; //Вызываем ф-нц Beep.
  176.   WriteFile(F, Mov_EAX_OpCod, 1, br, nil); WriteFile(F, EP, 4, br, nil);  //Mov EAX, EP;          //Помещаем в регистр EAX старую точку входа.
  177.   WriteFile(F, Jmp_EAX_OpCod, 2, br, nil);                                //Jmp EAX;              //Прыгаем на неё.
  178.   //Меняем точку входа на наш код.
  179.   EP:= NewS_RVA + 13 + 7 + 8 + 20 + ((k+1) * 20);
  180.   //Корректируем точку входа в заголовке.
  181.   SetFilePointer(F, AdrPE + $28, nil, FILE_BEGIN);
  182.   WriteFile(F, EP, 4, br, nil);
  183.  end;
  184.  CloseHandle(F);   //Закрыли файл.
  185. End.
Advertisement
Add Comment
Please, Sign In to add comment