Ошибки заданий hex

  • #1

Доброго времени суток, одно из заданий резервного копирования в symantec backup exec 2014 без конца вываливается в ошибку —

Код:

    0xe00084af - Каталог или файл не найден или недоступен.
    Окончательная категория ошибки: Ошибки заданий HEX"

При этом 880 гигабайт он уже записал на ленту. Помогите решить, что ему нужно?
ps ПРобовал переустанавливать агента, перезагружать сервер. Но это не спасает.

  • #2

Я не знаю в чем проблема, но предлагаю посмотреть ссылку которую там же симантек выдает в качестве решения проблемы.

  • #3

Может у человека устройство не совсем совместимое с BE2014. Нужно искать актуальный Hardware Compatibility List (HCL)
Поищи свой девайс и посмотри чо там с совместимостью

Surf_rider


  • #4

за какое время он у тебя эти 800 гигов писал? может у тебя бэкап идет через lan а не через san? посмотри содержимое журнала задания. там написано какой протокол использовался, и вываливай сюда на обсуждение.

  • #5

да в журнале задания написано что данные идут по lan, по этому идет так долго. 800 гигов писалось где-то часов 6-8. а почему они у меня не по san бегут?

Surf_rider


  • #6

Почему сказать сложно. Как вариант попробуй скачать пробную версию какого нибудь другого бэкапного софта veeam например, с этого же сервера. Попробуй снять бэкап им и посмотреть какая скорость будет. Может быть не верно развернуто решение от Symantec. Может зонирование в свитчах не верно настроено. Много чего может быть.

  • #7

Остановил все службы симантека, скачал veeam backup & replication, установил. Ленточная библиотека увиделась, попробовал забэкапить эту же виртуальную машину, все равно скорость низкую выдает — около 60 mb/sec . Пичаль..
Понял что в симантеке нет опции для бэкапа через SAN. Она у меня не куплена оказалась. Опция если чо называется —

Код:

Enterprise server option.

Но тогда вопрос — почему veeam тоже бэкапит медленно?

  • #8

Остановил все службы симантека, скачал veeam backup & replication, установил. Ленточная библиотека увиделась, попробовал забэкапить эту же виртуальную машину, все равно скорость низкую выдает — около 60 mb/sec . Пичаль..
Понял что в симантеке нет опции для бэкапа через SAN. Она у меня не куплена оказалась. Опция если чо называется —

Код:

Enterprise server option.

Но тогда вопрос — почему veeam тоже бэкапит медленно?

Чушь полная. Никакая опция не нужна, у меня и без нее все бэкапит нормально.

Скорее всего сервер у тебя физический с симантеком. Да? В veeam тебе надо использовать так называемый backup proxy, для того что бы ты смог использовать технологию hotadd.
Посмотри вебинар veeam по настройке производительности резервного копирования в veeam:

  • #9

Хм.. что то я не понимаю. Но все равно спасибо больше за ликбез. Видимо у меня симантек не верно развернут.

  • #10

Вот как должно быть вкратце, но это про veeam.
Можно даже любую имеющуюся виртуальную машину превратить в backup proxy. И вот тогда надо проверить.

image_244.jpg

Surf_rider


  • #11

Если ТС уверен что он правильно настроил зоны на fc свитчах или нексусах или что там у вас, то остается только то что он забыл презентовать lun ы серверу бэкапов. Как же он тогда через vsan достучится до лунов? Это сделано?

  • #12

Нет, не сделал, вот походу и решение проблемы.

Symantec Backup Exec 2010 (версия 13 выпуск 2896), стриммер HP Ultium 920 SAS,

Перестал создваться полный бэкап на ленту HP LTO3 Ultrium WORM 800G (C7973W). Процесс сразу заканчивается и в журнал пишутся сообщения:

Запрошено монтирование диска и носителя: 19.08.2010 17:07:07

Не удалось смонтировать носители с возможностью добавления.

V-79-57344-33037 — Ошибка — монтирование не выполнено.

Не найден носитель библиотеки физических томов.

Состояние выполнения задания

Задание завершено: 19 августа 2010 г. в 17:07:08

Состояние выполнения: Сбой

Окончательная ошибка: 0xe0000f16 — Операции не удалось получить минимальное необходимое число накопителей и носителей.

Окончательная категория ошибки: Ошибки заданий HEX

Для получения подробных сведений об этой ошибке перейдите по ссылке V-79-57344-3862

Ошибки

Щелкните на сообщении об ошибке, чтобы найти его в журнале задания

Не удалось смонтировать носители с возможностью добавления.

V-79-57344-33037 — Ошибка — монтирование не выполнено.

Не найден носитель библиотеки физических томов.

По ссылка ходили, читали, выполняли рекомендации. Картриджи меняли на новые из другой коробки. Всё тоже. В чем засада? Может кто сталкивался с таким?

0

27.09.2012 — 13:54


Есть тут те, кто имеет общения с данным продуктом?
есть ленточка с backup-ом машины ( назовем её old_server), который уже не существует. хочу восстановить пару каталогов оттуда. вставил кассету в стример, провел инвентаризацию носителя, затем каталогизацию. запускаю мастер восстановления данных. нахожу и отмечаю необходимые для восстановления каталоги, нажимаю «запустить», после чего получаю сообщение: «восстановление—ошибка при выполнении задания: недопустимый идентификатор носителя библиотеки физических томов». Есть идеи?

Подробности ошибки:
Состояние выполнения: Сбой Ошибки
Развернуть всеСвернуть все

Сведения о задании
Сервер задания: WINSRV
Имя задания: Восстановление 00026
Задание начато: 24 сентября 2012 г. в 19:09:20
Тип задания: Восстановление
Журнал задания: BEX_WINSRV_00027.xml

Выполнение задания — Восстановление
Сервер — old_server
V-79-57344-3844 — Серверу резервного копирования не удалось подключиться к удаленному агенту в системе old_server
Для выполнения операции сервер резервного копирования будет применять локальный агент.
Предупреждение: Серверам резервного копирования не удается полностью защитить удаленные серверы или рабочие станции на базе Windows, если удаленный агент Backup Exec не установлен и не выполняется на каждом удаленном сервере или на рабочей станции Windows, которые следует защитить. В отсутствие удаленного агента восстановление удаленных компьютеров Windows может приводить к потере данных.

За дополнительной информацией обратитесь к документации или электронной справке.

Запрошено монтирование диска и носителя: 24.09.2012 19:09:25
V-79-57344-33029 — Ошибка — монтирование не выполнено.
Недопустимый идентификатор носителя библиотеки физических томов.

GUID носителя: {99EA5B96-7432-443E-A63A-456EEDACCC01**
V-79-57344-33029 — Не удается получить устройство для указанного пула и носителя.
Недопустимый идентификатор носителя библиотеки физических томов.

Состояние выполнения задания
Задание завершено: 24 сентября 2012 г. в 19:09:25
Состояние выполнения: Сбой
Окончательная ошибка: 0xe0008105 — Недопустимый идентификатор носителя библиотеки физических томов.
Окончательная категория ошибки: Ошибки заданий HEX

Для получения подробных сведений об этой ошибке перейдите по ссылке V-79-57344-33029

Ошибки
Щелкните на сообщении об ошибке, чтобы найти его в журнале задания
Восстановление- old_serverV-79-57344-33029 — Ошибка — монтирование не выполнено.
Недопустимый идентификатор носителя библиотеки физических томов.
V-79-57344-33029 — Не удается получить устройство для указанного пула и носителя.

Исключения
Щелкните на сообщении об исключительной ситуации, чтобы найти его в
журнале задания
Восстановление- old_serverV-79-57344-3844 — Серверу резервного копирования не удалось подключиться к удаленному агенту в системе old_server.
Для выполнения операции сервер резервного копирования будет применять локальный агент.

1

27.09.2012 — 15:02

File redirection?

2

27.09.2012 — 15:23

«перенаправлять наборы файлов» в состоянии enable. Указан каталог на диске, куда должно производиться восстановление. толку нет

3

27.09.2012 — 17:09

Машина с BE — та же самая, с которой лента и писалась или это вообще свежеустановленный BE?
Другие ленты (если есть) как себя ведут?
Инвентори и каталожка точно успешно прошли?
Драйв/библиотека правильный выбран? (_http://www.symantec.com/business/support/library/BUSINESS/ATLAS/images_v1/190877/figure4.jpg)

Переустановить драйв/библиотеку пробовал? *Ребут реквайрд

Текст главного модуля управляющей программы высокого уровня на языке Delphi приведен ниже.

В начале своей работы программа пытается последовательно открыть первые четыре COM-порта компьютера. Через каждый порт, дескриптор которого удалось получить, устройству посылается запрос на передачу строки подтверждения “ATmega8”. Если строка была получена, то программа продолжает свое продолжение. В противном случае приложение закрывается.

Основная программа

Когда связь успешно установлена, появляется окно основной формы, вид которой изображен выше. Пользователю доступно два действия: стирание и программирование FLAS-памяти. В последнем случае данные из HEX-файла переносятся в буфер для записи и по страницам передаются в микроконтроллер. После завершения записи производится верификация памяти программ. При этом данные считываются из устройства в буфер для чтения. Результатом удачной операции программирования будет являться равенство содержимого обоих буферов.

Размер файла не должен превышать 4096–128=3968 слов, иначе во время записи произойдет повреждение загрузчика. По этой же причине стиранию подлежат только первые 124 из 128 страниц памяти программ. Перед записью HEX-файла ведется проверки диапазона адресов и контрольной суммы каждой из строк. Файл должен быть 8-ричным файлом формата Intel Hex и, кроме этого, не должен содержать команд смещения адресов. Присутствие, например строки :020000020100FB (смещение начального адреса записи на 0x0100 б) приведет к ошибки.

unit MainUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ComCtrls, ExtCtrls, AppEvnts, CheckLst;
type
TMainForm = class(TForm)
PbProgressBar: TProgressBar;
LbInfo: TLabel;
CbLowFuse: TCheckListBox;
CbHighFuse: TCheckListBox;
CbLockBits: TCheckListBox;
BtFilePath: TButton;
EdFilePath: TEdit;
BtProgramFlash: TBitBtn;
BtEraseFlash: TBitBtn;
DlOpenDialog: TOpenDialog;
function  StrToHex(const Sim: char): byte;
function  CheckHexFile: boolean;
function  PrepareFlashBuffer: boolean;
function  ProgramFlash: boolean;
procedure ReadFuseBits;
function  ReadFlash: boolean;
function  EraseFlash: boolean;
procedure OnFormCreate(Sender: TObject);
procedure OnFormDestroy(Sender: TObject);
procedure BtFilePathClick(Sender: TObject);
procedure BtProgramFlashClick(Sender: TObject);
procedure BtEraseFlashClick(Sender: TObject);
end;
var
MainForm: TMainForm;
PortHandle: THandle; //дескриптор COM-порта
FlashWriteBuffer: array of word;//массивы данных для записи во FLASH-памяти
FlashReadBuffer: array of word;//массивы прочитанных из FLASH-памяти данных
const
FLASH_SIZE = 4096;//число слов FLASH-памяти программ (4096 слова для ATmega8)
PAGE_SIZE = 32;//число слов в странице (32 слова для ATmega8)
implementation
{$R *.dfm}
//  Функция открытия COM-порта. В качестве параметра принимает номер порта 
//ComNumber в интервале 0…9. В случае удачного завершения возвращает 0.
function OpenPort(const ComNumber: cardinal): boolean;
var ComName:string;
begin
ComName:=Format('.COM%-d',[ComNumber]);
//  API-функция CreateFile производит открытие COM-порта по имени, в режиме
//чтения/записи. Установка флага FILE_FLAG_OVERLAPPED позволяет использовать
//асинхронные операции чтения/записи. При удачном завершении функция
//возвращает дескриптор устройства; в случае ошибки - INVALID_HANDLE_VALUE.
PortHandle:=CreateFile(PChar(ComName),GENERIC_READ or GENERIC_WRITE,0,
nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED,0);
Result:=PortHandle<>INVALID_HANDLE_VALUE;
end;
//  Процедура закрытия COM-порта. 
procedure ClosePort;
begin
//  API-функция CloseHandle закрывает дескриптор, полученный вызовом
//CreateFile.
CloseHandle(PortHandle);
end;
//  Процедура задания настроек COM-порта. В качестве параметров принимает:
//скорость обмена BaudRate, тип контроля четность Parity, количество стоп-бит
//StopBits и разрядность данных ByteSize.
//  Скорость обмена BaudRate в бит/с задается одной из констант: 
//CBR_110  =    110, CBR_300   =   300, CBR_600   =   600, CBR_1200  =  1200,
//CBR_2400 =   2400, CBR_4800  =  4800, CBR_4800  =  9600, CBR_4800  = 14400,
//CBR_19200 = 19200, CBR_19200 = 19200, CBR_38400 = 38400, CBR_56000 = 56000,
//CBR_57600 = 57600, CBR_115200 = 115200.
//  Контроль четности Parity задается одной из констант:
//NOPARITY    = 0 – контроль четности отсутствует(бит четности отсутствует),  
//ODDPARITY   = 1 – проверка на нечетность(бит четности дополняет сумму 
//                                единиц в слове данных до нечетного числа),    
//EVENPARITY  = 2 – проверка на четность(бит четности дополняет сумму
//                                  единиц в слове данных до четного числа),
//MARKPARITY  = 3 – проверка бита четности на 1,
//SPACEPARITY = 4 – проверка бита четности на 0.
//  Количество стоп-бит StopBits задается одной из констант:
//ONESTOPBIT    = 0 – 1 стоп-бит,
//ONE5STOPBITS  = 1 – 1.5 стоп-бит,
//TWOSTOPBITS   = 2 – 2 стоп-бит(только для 6…8-битовых данных).
//  Разрядность данных ByteSize может быть 5…8 бит.
procedure SetComProperty (const BaudRate,Parity,StopBits,ByteSize: cardinal);
var DCB:TDCB;
begin
//  Основные настройки COM-порта содержит структура DCB.   
FillChar(DCB,SizeOf(DCB),0);
DCB.DCBLength:=SizeOf(DCB);
DCB.Flags:=1;
DCB.BaudRate:=BaudRate;
DCB.Parity:=Parity;
DCB.StopBits:=StopBits;
DCB.ByteSize:=ByteSize;
//  API-функция SetCommState переписывает структуру DCB порта.
SetCommState(PortHandle,DCB);
end;
//  Функция чтения буфера данных из COM-порта. В качестве параметров
//принимает: указатель на буфер памяти Buffer и размер буфера BufSize. В
//случае удачного завершения функция возвращает 0.
function ReadBuffer(var Buffer:Pointer;const BufSize:cardinal): boolean;
var BytesRead:cardinal;
ReadOL:TOverlapped;
ReadDone:cardinal;
begin
FillChar(ReadOL,SizeOf(ReadOL),0);
//  API-функция Функция CreateEvent создает событие ReadOL.hEvent (дескриптор
//события ReadOL.hEvent размещен в структуре асинхронного доступа ReadOL типа
//TOverlapped), которое будет переведено в сигнальное состояние после
//завершения операции асинхронного чтения.
ReadOL.hEvent:=CreateEvent(nil,true,true,nil);
try
//  API-функция Функция ReadFile производит чтение данных из COM-порта. В
//случае удачного завершения функция возвращает 0. В данном случае чтение
//происходит в асинхронном режиме. После вызова ReadFile поток не блокируется
//до окончания операции, а продолжает свое выполнение. О завершении операции
//чтения можно судить по состоянию объекта ReadOL.hEvent, который должен
//перейти в сигнальное состояние.
ReadFile(PortHandle,Buffer^,BufSize,BytesRead,@ReadOL);
//  API-функция Функция WaitForSingleObject ожидает перевода в сигнальное
//состояние объекта синхронизации определенный период времени. В нашем случае
//объектом служит событие ReadOL.hEvent, интервал времени 100 мс. При
//успешном завершении (если объект перешел в сигнальное состояние раньше,
//чем истек период ожидания) функция возвратит код WAIT_OBJECT_0.
ReadDone:=WaitForSingleObject(ReadOL.hEvent,100);
finally
Result:= ReadDone = WAIT_OBJECT_0;
//  API-функция Функция CloseHandle закрывает дескриптор события
//ReadOL.hEvent, полученный с помощью CreateEvent.
CloseHandle(ReadOL.hEvent);
end;
end;
//  Функция записи буфера данных в COM-порт. В качестве параметров
//принимает: указатель на буфер памяти Buffer и размер буфера BufSize. В
//случае удачного завершения функция возвращает 0.
function WriteBuffer (var Buffer:Pointer; const BufSize:cardinal): boolean;
var BytesWritten:cardinal;
WriteOL:TOverlapped;
WriteDone:cardinal;
begin
FillChar(WriteOL,SizeOf(WriteOL),0);
//  API-функция Функция CreateEvent создает событие WriteOL.hEvent (дескриптор
//события WriteOL.hEvent размещен в структуре асинхронного доступа WriteOL типа
//TOverlapped), которое будет переведено в сигнальное состояние после
//завершения операции асинхронной записи.
WriteOL.hEvent:=CreateEvent(nil,true,true,nil);
try
//  API-функция Функция WriteFile производит запись данных в COM-порт. В
//случае удачного завершения функция возвращает 0. В данном случае запись
//происходит в асинхронном режиме. После вызова WriteFile поток не
//блокируется до окончания операции, а продолжает свое выполнение.
//О завершении операции чтения можно судить по состоянию объекта.
WriteFile(PortHandle,Buffer^,BufSize,BytesWritten,@WriteOL);
//  API-функция Функция WaitForSingleObject ожидает перевода в сигнальное
//состояние объекта синхронизации определенный период времени. В нашем случае
//объектом служит событие WriteOL.hEvent, интервал времени 100 мс. При
//успешном завершении (если объект перешел в сигнальное состояние раньше,
//чем истек период ожидания) функция возвратит код WAIT_OBJECT_0.
WriteDone:=WaitForSingleObject(WriteOL.hEvent,100);
finally
Result:= WriteDone = WAIT_OBJECT_0;
//  API-функция Функция CloseHandle закрывает дескриптор события
//WriteOL.hEvent, полученный с помощью CreateEvent.
CloseHandle(WriteOL.hEvent);
end;
end;
//  Функция чтения байта данных из COM-порта. Возвращает прочитанный байт. 
function ReadByte: byte;
var Ptr:Pointer;
begin
Ptr:=@Result;
ReadBuffer(Ptr,1);
end;
//  Процедура записи байта данных в COM-порт. В качестве параметров принимает
//байт данных для записи.
procedure WriteByte(const TX:byte);
var Ptr:Pointer;
begin
Ptr:=@TX;
WriteBuffer(Ptr,1);
end;
//  Функция преобразования символов ACSII (“0”…“9”, “A”…“F”) в число. В
//качестве параметров принимает символ, подлежащий преобразованию Sim.
//Возвращает преобразованное число.
function TMainForm.StrToHex(const Sim: char): byte;
begin
if ((Byte(Sim)>=$30) and (Byte(Sim)<=$39)) then Result:= Byte(Sim)-$30
else Result:= Byte(Sim)-$37;
end;
//  Функция проверки HEX-файла на ошибки. В случае удачного завершения
//возвращает 0.
function TMainForm.CheckHexFile: boolean;
var F:TStringList;
Str: string;
Size,Sum: Byte;
I,J: integer;
begin
Result:= false;
F:= TStringList.Create;
F.LoadFromFile(EdFilePath.Text);
Str:= F.Strings[F.Count-1];
//  Если 4 последних символа последней строки отличны от “01FF” (признак
//конца файла), то HEX-файл поврежден.
if Copy(Str,Length(Str)-3,4)<>'01FF' then begin
F.Free;
Exit;
end;
//  Если в начале хотя бы одной из строк отсутствует символ “:” (признак
//начала строки), то HEX-файл поврежден.
for I:= 0 to F.Count-1 do begin
Str:= F.Strings[I];
if Str[1]<>':' then begin
F.Free;
Exit;
end;
Size:= 16*StrToHex(Str[2])+StrToHex(Str[3])+4;
Sum:=0;
//  Если в хотя бы одной из строк не сходится контрольная сумма (сумма всех
//байтов в строке без учета переполнения должна равняться 0), то HEX-файл
//поврежден.
for J:= 0 to Size do Sum:= Byte(Sum+16*StrToHex(Str[2*J+2])+
StrToHex(Str[2*J+3]));
if Sum <> 0 then begin
F.Free;
Exit;
end;
end;
F.Free;
Result:=true;
end;
//  Функция подготовки данных для записи. В случае удачного завершения
//возвращает 0.
function TMainForm.PrepareFlashBuffer: boolean;
var F: TStringList;
Str: string;
W,Size,MaxFlashSize,Offset: word;
I,J,K: integer;
begin
Result:= false;
F:=TStringList.Create;
F.LoadFromFile(EdFilePath.Text);
Str:=F.Strings[F.Count-2];
Size:=0;
for I:=0 to 3 do Size:= 16*Size+StrToHex(Str[4+I]);
MaxFlashSize:= (Size+16*StrToHex(Str[2])+StrToHex(Str[3])) div 2;
// Если максимальный размер HEX-файла превышает размер доступной памяти
//программ (загрузчик boot-loader размещен в Boot Loader Section размером 128
//слов), то запись не возможна.
if MaxFlashSize > (FLASH_SIZE-128) then begin
F.Free;
Exit;
end;
//  Выделение под буфер памяти в MaxFlashSize 16-разрядных слов, чистка и
//заполнение его данными из HEX-файла.
SetLength(FlashWriteBuffer,MaxFlashSize);
SetLength(FlashReadBuffer,MaxFlashSize);
for I:=0 to MaxFlashSize-1 do FlashWriteBuffer[I]:= $FFFF;
for I:=0 to F.Count-2 do begin
Str:= F.Strings[I];
if Copy(Str,8,2)<>'00' then Continue;
Size:= (16*StrToHex(Str[2])+StrToHex(Str[3])) div 2;
Offset:= 0;
for J:=0 to 3 do Offset:=16*Offset+StrToHex(Str[4+J]);
for J:=0 to Size-1 do begin
W:=0;
for K:=0 to 3 do W:=16*W+StrToHex(Str[4*J+K+10]);
FlashWriteBuffer[Offset div 2 +J]:= W;
end;
end;
F.Free;
Result:= true;
end;
//  Процедура чтения байтов конфигурации и содержимого ячеек защиты.
procedure TMainForm.ReadFuseBits;
var LowFuseBit,HighFuseBit,LockBits: byte;
I: integer;
begin
//  Передача команды чтения (символ “F”).
WriteByte(Byte('F'));
//  Чтение младшего байта конфигурации.
LowFuseBit:=ReadByte;
//  Чтение ячеек защиты.
LockBits:=ReadByte;
//  Чтение старшего байта конфигурации.
HighFuseBit:=ReadByte;
for I:=0 to 7 do CbLowFuse.Checked[I]:=((LowFuseBit shl I) and $80)<>$80;
for I:=0 to 7 do CbHighFuse.Checked[I]:=((HighFuseBit shl I) and $80)<>$80;
LockBits:=LockBits shl 2;
for I:=0 to 3 do CbLockBits.Checked[I]:=((LockBits shl I) and $80)<>$80;
end;
//  Функция программирования FLASH-памяти. В случае удачного завершения
//возвращает 0.
function TMainForm.ProgramFlash: boolean;
var Adress,Data,Page: word;
I,J: integer;
begin
Result:= false;
PbProgressBar.Visible:= true;
PbProgressBar.Position:=0;
PbProgressBar.Min:=0;
PbProgressBar.Max:=Length(FlashWriteBuffer);
Page:= Length(FlashWriteBuffer) div PAGE_SIZE + 1;
Adress:=0;
//  Программирование FLASH-памяти из буфера FlashWriteBuffer. Сначала
//передается команда программирования (символ “P”). Затем передаются номер
//страницы и 32 слова для записи.
for I:=0 to Page-1 do begin
WriteByte(Byte('P'));
WriteByte(Byte(Adress and $00FF));
WriteByte(Byte((Adress and $FF00) shr 8));
for J:=0 to PAGE_SIZE-1 do begin
if (PAGE_SIZE*I+J) >= Length(FlashReadBuffer) then Data:= $FFFF else
Data:= FlashWriteBuffer[PAGE_SIZE*I+J];
WriteByte(Byte((Data and $FF00) shr 8));
WriteByte(Byte(Data and $00FF));
//  Небольшая задержка времени и принудительный запуск цикла обработки ообщений.
Sleep(10);
Application.ProcessMessages;
end;
//  Если после завершения операции микроконтроллер не выдал символ
//подтверждения “!”, то произошла ошибка записи.
if ReadByte <> Byte('!') then begin
PbProgressBar.Visible:= false;
Exit;
end;
Adress:= Adress + 2*PAGE_SIZE;
PbProgressBar.Position:= PbProgressBar.Position+PAGE_SIZE;
end;
PbProgressBar.Visible:= false;
Result:= true;
end;
//  Функция верификации данных FLASH-памяти. В случае удачного завершения
//возвращает 0.
function TMainForm.ReadFlash: boolean;
var Adress,Data,Page: word;
I,J: integer;
begin
Result:= false;
PbProgressBar.Visible:= true;
PbProgressBar.Position:=0;
PbProgressBar.Min:=0;
PbProgressBar.Max:=Length(FlashReadBuffer);
Page:= Length(FlashReadBuffer) div PAGE_SIZE + 1;
Adress:=0;
//  Считывание FLASH-памяти в буфер FlashReadBuffer. Сначала передается
//команда верификации (символ “R”). Затем передается номер страницы и
//считываются 32 слова.
for I:=0 to Page-1 do begin
WriteByte(Byte('R'));
WriteByte(Byte(Adress and $00FF));
WriteByte(Byte((Adress and $FF00) shr 8));
for J:=0 to PAGE_SIZE-1 do begin
Data:=ReadByte;
Data:=(Data shl 8)+ReadByte;
if (PAGE_SIZE*I+J) < Length(FlashReadBuffer) then
FlashReadBuffer[PAGE_SIZE*I+J]:= Data;
Application.ProcessMessages;
end;
//  Если после завершения операции микроконтроллер не выдал символ
//подтверждения “!”, то произошла ошибка чтения.
if ReadByte <> Byte('!') then begin
PbProgressBar.Visible:= false;
Exit;
end;
Adress:= Adress + 2*PAGE_SIZE;
PbProgressBar.Position:= PbProgressBar.Position+PAGE_SIZE;
end;
PbProgressBar.Visible:= false;
Result:= true;
end;
//  Функция стирания данных FLASH-памяти. В случае удачного завершения
//возвращает 0.
function TMainForm.EraseFlash: boolean;
var Adress,Page: word;
I: integer;
begin
Result:= false;
PbProgressBar.Visible:=true;
PbProgressBar.Position:=0;
PbProgressBar.Min:=0;
PbProgressBar.Max:=FLASH_SIZE-128;
Page:=(FLASH_SIZE-128) div PAGE_SIZE;
Adress:=0;
//  Стирание FLASH-памяти программ. Сначала передается команда стирания
//(символ “E”). Затем передается номер страницы.
for I:=0 to Page-1 do begin
WriteByte(Byte('E'));
WriteByte(Byte(Adress and $00FF));
WriteByte(Byte((Adress and $FF00) shr 8));
//  Небольшая задержка времени и принудительный запуск цикла обработки
//сообщений.
Sleep(10);
Application.ProcessMessages;
//  Если после завершения операции микроконтроллер не выдал символ
//подтверждения “!”, то произошла ошибка стирания.
if ReadByte <> Byte('!') then begin
PbProgressBar.Visible:= false;
Exit;
end;
Adress:= Adress + 2*PAGE_SIZE;
PbProgressBar.Position:= PbProgressBar.Position+PAGE_SIZE;
end;
PbProgressBar.Visible:= false;
Result:= true;
end;
//  Обработчик события создания формы.
procedure TMainForm.OnFormCreate(Sender: TObject);
var Str: string;
Found: boolean;
I: integer;
begin
Found:= false;
SetLength(Str,7);
//  Попытка последовательно открыть первые 4 COM-порта.  
for I:=1 to 4 do begin
if not OpenPort(I) then Continue;
//  Если порт успешно открыт, то устанавливаем параметры связи (в данном
//случае 115200, 8-N-2).
SetComProperty(CBR_115200,NOPARITY,TWOSTOPBITS,8);
//  Посылка микроконтроллеру запроса (символ “D”) выдать информацию о
//присутствии на линии.
WriteByte(Byte('D'));
//  Если не получена строка из семи символов, то устройство не найдено.
if not ReadBuffer(Pointer(Str),7) then begin
ClosePort;
Continue;
end;
//  Если была получена строка подтверждения “ATmega8”, то устройство найдено
//и можно продолжать дальнейшую работу.
Found:= Str = 'ATmega8';
if Found then Break
else ClosePort;
end;
//  Если микроконтроллер не обнаружен, то приложение прекращает свою работу.
if not Found then begin
ShowMessage('Не удалось связаться с устройством!');
Application.Terminate;
end;
LbInfo.Caption:= 'ATmega8 подключен к ' + Format('COM-%d.',[I]);
ReadFuseBits;
end;
//  Обработчик события уничтожения формы.
procedure TMainForm.OnFormDestroy(Sender: TObject);
begin
//  Посылка микроконтроллеру команды завершения связи (символ “O”).
WriteByte(Byte('O'));
if PortHandle <> INVALID_HANDLE_VALUE then ClosePort;
end;
//  Обработчик нажатия кнопки выбора пути к HEX-файлу.
procedure TMainForm.BtFilePathClick(Sender: TObject);
begin
DlOpenDialog.Execute;
EdFilePath.Text:= DlOpenDialog.FileName;
end;
//  Обработчик нажатия кнопки программирования FLASH-памяти.
procedure TMainForm.BtProgramFlashClick(Sender: TObject);
var Str: string;
I: integer;
Begin
//  Если выбранный файл имеет расширение отличное от HEX, то 
//программирование не возможно. 
Str:= Copy(EdFilePath.Text,Length(EdFilePath.Text)-3,4);
if (Str <> '.hex') and (Str <> '.HEX') then begin
ShowMessage('Файл должен иметь расширение .hex !');
Exit;
end;
//  Если путь, указанный к файлу не верный, то программирование не возможно. 
if not FileExists(EdFilePath.Text) then begin
ShowMessage('Файл не найден !');
Exit;
end;
//  Если в файле содержаться ошибки, то программирование не возможно. 
if not CheckHexFile then begin
ShowMessage('Файл поврежден !');
Exit;
end;
//  Если при подготовки данных оказалось, что размер HEX-файла превышает
//размер доступной памяти то программирование не возможно.
if not PrepareFlashBuffer then begin
ShowMessage('Слишком большой размер файла !');
Exit;
end;
BtProgramFlash.Enabled:= false;
BtEraseFlash.Enabled:= false;
LbInfo.Caption:= 'Программирование...';
//  Запись данных из буфера FlashWriteBuffer.
if not ProgramFlash then begin
LbInfo.Caption:= 'Ошибка программирования !';
BtProgramFlash.Enabled:= true;
BtEraseFlash.Enabled:= true;
Exit;
end;
//  Чтение данных в буфер FlashReadBuffer.
LbInfo.Caption:= 'Программирование... Верификация...';
if not ReadFlash then begin
LbInfo.Caption:= 'Ошибка чтения !';
BtProgramFlash.Enabled:= true;
BtEraseFlash.Enabled:= true;
Exit;
end;
//  Сравнение записанных и считанных данных. 
for I:= 0 to Length(FlashWriteBuffer)-1 do begin
if FlashReadBuffer[I] = FlashWriteBuffer[I] then Continue;
ShowMessage(Format('Ошибка записи по адресу 0x%x : 0x%x вместо 0x%x !',
[I,FlashReadBuffer[I],FlashWriteBuffer[I]]));
LbInfo.Caption:= 'Ошибка верификации !';
BtProgramFlash.Enabled:= true;
BtEraseFlash.Enabled:= true;
Exit;
end;
LbInfo.Caption:= 'Программирование успешно завершено.';
BtProgramFlash.Enabled:= true;
BtEraseFlash.Enabled:= true;
end;
//  Обработчик нажатия кнопки стирания FLASH-памяти.
procedure TMainForm.BtEraseFlashClick(Sender: TObject);
begin
BtProgramFlash.Enabled:= false;
BtEraseFlash.Enabled:= false;
LbInfo.Caption:= 'Стирание...';
if not EraseFlash then LbInfo.Caption:= 'Ошибка при стирании !' else
LbInfo.Caption:= 'Стирание успешно завершено.';
BtProgramFlash.Enabled:= true;
BtEraseFlash.Enabled:= true;
end;
end. 

Скачать исходник проекта

Перейти к следующей части: Самоуничтожение программы

Теги:

Hex-редактор (англ. hex-editor ), шестнадцатеричный редактор — приложение для редактирования данных, в котором данные представлены в «сыром виде» — как последовательность байтов. Он может быть как отдельным самостоятельным приложением, так и компонентом другого, более сложного приложения, такого как дизассемблер, отладчик, интегрированная среда разработки и т. п.

Для представления значения байтов используется шестнадцатеричная (англ. hexadecimal ) система счисления, что и отражено в названии редактора. Выбор шестнадцатеричной системы счисления обусловлен следующими факторами:

  • Наибольшую популярность получили платформы с 8-битным байтом. В таких платформах байт может принимать 2 8 =256 значений в диапазоне от 0 до 255. Число 25610, записанное в шестнадцатеричной системе, является круглым трёхзначным числом — 10016.
  • То, что это число является трёхзначным, означает, что для представления любого числа в диапазоне 0—255 требуется не более 2 разрядов.
  • То, что это число является круглым, означает, что для представления будут использованы все возможные комбинации цифр, и не останется неиспользованных (например, в случае использования десятичной системы, неиспользованными остаются комбинации, соответствующие числам от 256 до 999).
  • При использовании шестнадцатеричной системы получается, что правая цифра соответствует младшим четырём битам байта, а левая цифра в записи — старшим 4 битам. Поэтому любые операций над 4-битными блоками, выровненными по границе байта, можно упрощённо производить как операции над соответствующими цифрами.
  • 16 — минимальное основание системы счисления, при котором для записи достаточно двух разрядов. Системы с меньшим основанием потребовали бы уже три (и более) разряда, а возможность уложиться в один разряд обеспечила бы только система счисления с основанием 256, которая совершенно неприменима на практике из-за большого числа цифр в ней.
  • Очевидно, что, например, для платформ с 9-битовым байтом использовались бы трёхзначные восьмеричные числа, а аналогичное по функциональности приложение называлось бы Oct-редактором.

    Данные, которые отображает и позволяет редактировать Hex-редактор, могут быть:

    Содержание

    Интерфейс [ править | править код ]

    Hex-редактор отображает данные в виде матрицы, каждая ячейка которой соответствует одному байту, записанному в шестнадцатеричной системе счисления в виде двухзначного числа (с ведущим нулём, если он требуется). Количество столбцов матрицы является степенью двойки, чаще всего используются 16 или 8 колонок, иногда 4. Число строк зависит от количества байтов, которые требуется отобразить/отредактировать. В случае использования 16 колонок одна строка соответствует одному параграфу.

    Кроме этого, часто используются дополнительные элементы:

    • Слева от матрицы отображается линейка (на рисунке показана синим цветом) из чисел: каждой строчке соответствует число, означающее адрес/смещение первого байта этой строчки. Шаг адресов при этом равен количеству колонок.
    • Сверху от матрицы отображается другая линейка (на рисунке показана зелёным цветом) из чисел: над каждой колонкой отображается смещение байта, стоящего в этой колонке, относительно первого байта соответствующей строчки. Сумма числа, соответствующего i -той строке, и числа, соответствующего j -той колонке является адресом/смещением байта (i;j) , стоящего на пересечении взятой строки и взятого столбца.
    • Справа от матрицы могут отображаться те же данные, но в другой интерпретации. Наиболее часто используется альтернативное отображение данных как текста в кодировке ASCII (на рисунке показаны цветом фуксия), при этом байты, значения которых соответствуют непечатным символам, отображаются как точки ( · ). Многие редакторы позволяют выбрать произвольную кодировку для режима отображения текста. Вариант с отображением данных как текста встречается в Hex-редакторах общего назначения. В редакторах же, являющихся частью какой-либо специальной программы, например отладчика, обычно доступны другие режимы, такие как листинга дизассемблирования, подсказок об адресах, и другие специфичные для приложения режимы.

    Большинство редакторов позволяют совершать редактирование как в левой половине, так и в правой (при её наличии). При этом совершаемые изменения когерентны [1] .

    Простые редакторы позволяют только менять значение выбранных байтов по отдельности. Продвинутые — редактировать совокупности байтов как цельные блоки [2] , выполнять поиск по последовательностям или шаблонам последовательностей.

    Hex-редакторы для редактирования образов дисков могут включать в себя функции по восстановлению повреждённой файловой системы или случайно удалённых файлов.

    Использование [ править | править код ]

    Hex-редакторы используются для редактирования не-текстовых данных, когда специализированной программы для редактирования имеющихся данных либо нет, либо её применение неоправданно или нежелательно. Примером может служить внесение изменений в скомпилированную программу без перекомпиляции последней. Так, с помощью Hex-редактора можно изменить значения жестко вшитых в код программы строковых и числовых констант, если правильно определить их расположение.

    Если Hex-редактор имеет функции дизассемблера или дизассемблирование целевой программы уже было проведено с помощью другого инструмента заранее, и известно смещение, можно внести изменение непосредственно в код программы и изменить её поведение. Этим пользуются при исправлении ошибок, взломе, читерстве, ручном твикинге.

    Поскольку Hex-редактор является достаточно универсальным инструментом, описать все варианты его применения не представляется возможным.

    Галерея [ править | править код ]

    Свободный hex-редактор KHexEdit входящий в состав KDE (kdeutils)

    $ echo 1234567890ABCDEF > test.bin

    Теперь посмотрим, что записалось внутрь файла:

    $ hexdump -C test.bin
    00000000 31 32 33 34 35 36 37 38 39 30 41 42 43 44 45 46 |1234567890ABCDEF|
    00000010 0a |.|
    00000011
    $

    Здесь три колонки: первая — смещения внутри файла, вторая — шестнадцатеричные коды символов, третья — сами символы (обычно непечатаемые символы в третьей колонке заменяются точками) .

    В данной статье будет рассказано о работе в бесплатном hex-редакторе Free Hex Editor Neo, на примере правки файла BkEnd.dll из поставки 1С:Предприятие 7.7 для корректной работы этой системы с Microsoft SQL Server 2008 R2.

    0. Оглавление

    1. Немного о hex-редакторах и файлах

    Как известно, любой файл, хранясь на жестком диске компьютера, представляет собой последовательность машинных слов — байтов. Байт, в свою очередь, состоит из 8 битов, каждый из которых может принимать значение «0» или «1» , а это означает, что один байт может принимать 2 8 =256 значений в диапазоне от 0 до 255. Число 25610, записанное в шестнадцатеричной системе, является круглым трёхзначным числом — 10016, т. е. для представления любого числа из диапазона 0—255 потребуется не более 2 разрядов. А это значит, что значение каждого байта очень удобно записать двузначным числом в шестнадцатеричной системе счисления.

    Hex-редактор (англ. hex-editor) показывает нам файл, так, как его «видит» машина, а именно, последовательностью байтов. Например, открыв файл в редакторе, мы увидим матрицу, состоящую из 16 колонок и числа строк зависящего от размера файла. Каждое значение матрицы соответствует одному байту, записанному двузначным шестнадцатеричным числом. Изменяя значение нужного байта, мы можем, соответственно, изменить сам файл.

    Кроме того, рядом с таблицей можем увидеть:

    • Слева от матрицы отображается линейка из чисел: каждой строчке соответствует число, означающее адрес/смещение первого байта этой строчки. Шаг адресов при этом равен количеству колонок.
    • Сверху от матрицы отображается другая линейка: над каждой колонкой отображается смещение байта, стоящего в этой колонке, относительно первого байта соответствующей строчки. Сумма числа, соответствующего i -той строке, и числа, соответствующего j -той колонке является адресом/смещением байта (i;j) , стоящего на пересечении взятой строки и взятого столбца.
    • Справа от матрицы отображаются те же данные, но в другой интерпретации. Чаще всего используется альтернативное отображение данных как текста в кодировке ASCII , при этом байты, значения которых соответствуют непечатным символам, отображаются как точки ( · ). Редактировать значения можно и в этой области.

    Подробнее о Hex-редакторах можно прочитать здесь.

    2. Установка Free Hex Editor Neo

    Скачиваем Free Hex Editor Neo с официального сайта. Программа бесплатна, на момент написания статьи последней была версия 5.14. Устанавливаем, следуя инструкциям инсталлятора, не меняя настроек по умолчанию. При первом запуске программа предложит выбрать режим интерфейса. Выбираем «Novice user» , этого более чем достаточно.

    3. Работа с файлом hex-редакторе

    Теперь откроем файл, который нам необходимо «подправить» выбрав «File» — «Open» — «Open File» в меню Free Hex Editor Neo. В моем случае это файл BkEnd.dll, находящийся в папке с установленной 1С:Предприятие 7.7 (По умолчанию «C:Program Files1Cv77BIN» ) для статьи Установка 1С:Предприятие 7.7 на Microsoft SQL Server 2008 R2.

    Например, мне нужно в байт со смещением 000d9cca записать значение eb. Для этого я нахожу строку «000d9cco» и столбец «0a», кликаю два раза по нужной ячейке и забиваю новое значение.

    Действуя аналогично, я вношу следующие изменения:

    1. Для исправления ошибки «Требуется MS SQL Server 6.5 + Service Pack 5a или более старшая версия!» изменяем поля:
      по смещению 000d9cca значение 83 меняем на eb
      по смещению 000d9ccb значение e8 меняем на 15
      по смещению 000db130 значение 83 меняем на eb
      по смещению 000db131 значение e8 меняем на 10
    2. Для исправления ошибки «Порядок сортировки, установленный для базы, отличается от системного!»:
      по смещению 0018a79d значение 75 меняем на eb
    3. Для исправления ошибки «Неправильный синтаксис около ключевого слова «TRANSACTION»
      Фразу DUMP TRANSACTION %s WITH TRUNCATE_ONLY , которая находится по смещению 002856B0 заменяем на фразу ALTER DATABASE %s SET RECOVERY SIMPLE
    4. Для исправления ошибки «База данных не может быть открыта в однопользовательском режиме», изменяем поля:
      по смещению 0028549c значение 64 меняем на 6b
      по смещению 0028549d значение 62 меняем на 70

    После того, как все изменения сделаны, сохраним файл, нажав «File» — «Save» .

    Смотрите также:

    В данном вебинаре я расскажу о применяемых в нашей компании правилах и приемах доработки типовых конфигураций 1С для облегчения их дальнейшей поддержки и обновления. В видео использованы материалы…

    Официально, платформа 1С:Предприятие 7.7 работает только с MS SQL Server 2000. Но с помощью небольших манипуляций можно организовать стабильную работу и с последней, на момент написания статьи, версий Microsoft SQL…

    Небольшая зарисовка на тему, какие были бы сливные трубы, если бы их делали 1С-ники.

    Виноваты ошибки, допущенные при ручном вводе в компьютер НЕХ-файла программы по его “распечатке” на страницах печатного издания. Значительно реже бывают сбои при копировании файлов с дискет или “скачивании” их из Интернета. Как проверить НЕХ-файл? Ответ на этот вопрос — в публикуемой статье.

    При вводе НЕХ-файлов вручную (с клавиатуры) или их электронных версий, полученных сканированием, чаще всего случается следующее:

    Самый безобидный из этих дефектов — последний. В отличие от других, он не сказывается на работоспособности программы. То же самое в большинстве случаев можно сказать и о нарушении порядка следования строк. Однако программаторы, в которых предусмотрен строгий контроль правильности вводимых данных, могут файл с такими ошибками все-таки забраковать.

    Рис.1.

    Нужно сказать, что контроль правильности структуры НЕХ-файла в процессе его чтения с диска выполняет программное обеспечение очень многих программаторов. Определенные возможности для этого заложены в самой структуре подобного файла, о которой можно прочитать [1]. Беда в том, что программатор зачастую сообщает лишь о факте обнаружения ошибки без каких-либо подробностей, предоставляя пользователю разбираться самому.

    При этом дефектный файл нередко оказывается полностью или частично загруженным в программатор и, если неосторожно подать команду “Программирование”, ошибочные данные будут перенесены в память МК. После этого будет успешно выполнена верификация (сверка содержимого памяти МК и программатора) и у пользователя создастся впечатление, что все в порядке.

    Рис.2.

    В этом отношении очень опасно ведет себя программа PonyProg (версии 2.05 и более ранних). Кроме HEX, здесь предусмотрено несколько других форматов входных файлов, и при загрузке она пытается самостоятельно выбрать нужный.

    Не распознав правильно формат файла с ошибками, она все-таки вводит его как двоичный. На рис. 1 показан вид окна программатора PonyProg после такого ввода.

    В памяти находятся не машинные коды команд, а ASCI-коды букв и цифр, из которых состоит текстовый НЕХ-файл. Естественно, по такой “программе” МК работать не будет. Вид того же окна после ввода идентичного первому безошибочного файла представлен на рис. 2. Заметим, что никаких сообщений об ошибках или об автоматически определенном формате файла программатор в обоих случаях не давал.

    Помочь найти и исправить ошибки в НЕХ-файле до ввода его в программатор сможет программа CheckHEX, которую можно скачать [2]. С ее же помощью можно создать новый НЕХ-файл, набрав его содержимое на клавиатуре компьютера. В последнем случае проверка идет одновременно с вводом данных.

    Рис.3.

    Окно данных программы CheckHEX после ввода НЕХ-файла, содержащего несколько ошибок, изображено на рис. 3. В его верхней части слева выведены текущие координаты курсора, показывающего, куда будет введен символ при нажатии клавиши.

    Справа имеется окошко, щелкнув по которому “мышью”, можно в любой момент отменить или вновь разрешить проверку ошибок. Заблокировать контроль бывает полезно на время ручного ввода данных, иначе каждую незавершенную строку сопровождает множество сообщений, только отвлекающих внимание. Окно предупреждений и сообщений об ошибках (рис. 4) находится ниже основного.

    Сообщения, начинающиеся словом “Информация”, лишь свидетельствуют об особом статусе тех или иных строк НЕХ-файла. В данном случае таких строк две. Первая из них необязательна, так как и в ее отсутствие, отсчет адресов начнется с нуля.

    Подобные строки (их может быть несколько в разных местах файла) позволяют адресовать более 64 Кбайт (32 Кслов) памяти. Именно их присутствие отличает НЕХ-файлы формата INX32 от аналогичных формата INX8M.

    Строка 25 служит признаком конца НЕХ-файяа. Если какие-нибудь данные находятся после нее (строка 26), они не будут восприняты программатором. Этим можно воспользоваться, например, чтобы поместить в НЕХ-файл текстовый комментарий. В примере сюда была просто перемещена строка 20 исходного файла, оставшаяся пустой.

    В принципе, наличие пустых строк в НЕХ-файле допустимо, но некоторые программаторы все-таки могут счесть их ошибками. Программа CheckHEX, на всякий случай, предупреждает об этом. Обратите внимание на сообщение об ошибке контрольной суммы в строке 3. Она может быть результатом неправильного ввода любого (кроме двоеточия) символа строки, которую следует проверить особенно внимательно.

    Приведенная в скобках “правильная” контрольная сумма полезна, если один или несколько символов строки изменены преднамеренно (например, чтобы исправить действительно имевшую место ошибку в программе). В рассматриваемом случае ошибка — результат ввода цифры 8 вместо буквы В.

    Рис.4.

    Характер ошибки, допущенной в пятом символе четвертой строки, понятен. Заметим лишь, что для облегчения визуального поиска ошибок шрифт текста в основном окне не содержит символов кириллицы, их место занимают символы, не имеющие ничего общего с правильными.

    Однако в сообщениях об ошибках русские буквы представлены. Справа от окна данных расположено окно, отображающее картину заполнения памяти МК кодами из анализируемого файла. Фрагмент этого окна — на рис. 5. Белый цвет соответствует свободным ячейкам, синий или красный — занятым.

    Имеющиеся на рисунке пояснительные надписи (в реальном окне их нет) относятся к типовому для Р1С-контроллеров распределению памяти, для других МК и РПЗУ оно может быть совершенно иным. Перемещая курсор “мыши” внутри окна, можно определить адрес любой из отображенных там ячеек. В данном случае курсор (перекрестие в правой верхней части окна) указывает на байт по адресу 00С0Н — младший в двухбайтном слове по адресу 0060Н.

    Рис.5.

    Конечно, пользователь, не разрабатывавший загружаемую программу и внимательно не анализировавший ее, как правило, не знает, какие ячейки должны быть заняты, а какие — нет.

    Тем не менее, есть смысл обратить внимание на разрывы в сплошной последовательности занятых ячеек и лишний раз убедиться, что они появились не в результате ошибок, как в рассматриваемом случае. Отрезок красного цвета говорит о том, что коды, заносимые по этим адресам, встретились в файле неоднократно.

    В примере (см. рис. 3) идентичны седьмая и восьмая строки. Если дублирующая строка — результат невнимательности при ручном вводе данных, ее можно удалить.

    Но чаще виновата ошибка, допущенная в адресной части строки (символы с четвертого по седьмой). В подобном случае не только коды по ошибочным адресам будут искажены, но и останется неопределенной область памяти, к которой данная строка относилась исходно.

    Все это необходимо еще и еще раз проверить.

    В заключение отметим, что в окне программы CheckHEX имеются три управляющие кнопки:

     — сохранить созданный или отредактированный файл.

    При попытке загрузить или создать еще один файл, предварительно не сохранив измененный вариант старого, программа всегда напоминает о необходимости это сделать. То же самое происходит перед завершением работы программы.

    Интересная статья с хакера, посвященная статическому анализу:Малварь на просвет. Учимся быстро искать признаки вредоносного кода.

    В целом, если говорить про анализ исполняемых файлов, можно выделить два подхода — это статический анализ и динамический анализ.

    Виды анализа исполняемых файлов

    Виды анализа исполняемых файлов

    Статический анализ предполагает анализ файла без его запуска на выполнение. Он может быть базовым — в этом случае мы не анализируем непосредственно инструкции процессора в файле, а производим поиск нетипичных для обычных файлов артефактов (например, таких как строки или названия и последовательности API-функций), либо расширенным — в этом случае файл дизассемблируется и производится исследование инструкций, поиск их характерных для вредоносных программ последовательностей и определение того, что именно делала программа.

    Динамический анализ заключается в исследовании файла с его запуском в системе. Он тоже может быть базовым и расширенным. Базовый динамический анализ — это исследование файла с его запуском без использования средств отладки, он заключается в отслеживании событий, связанных с этим файлом (например, обращение к реестру, дисковые операции, взаимодействие с сетью и т. п.). Расширенный динамический анализ заключается в исследовании поведения запущенного файла с применением средств отладки.

    В этой статье я расскажу о базовых техниках статического анализа. Его преимущества:

    • позволяет получить результат достаточно быстро;
    • безопасен для системы при соблюдении минимальных мер предосторожности;
    • не требует подготовки специальной среды.

    Основной недостаток базового статического анализа — это его низкая эффективность при анализе и распознавании сложных вредоносных программ, например упакованных неизвестным упаковщиком или использующих полное либо частичное шифрование файла с применением продвинутых алгоритмов.

    Инструментарий

    HEX-редакторы

    Один из основных инструментов статического базового анализа — это HEX-редактор. Их много, но в первую очередь необходимо отметить Hiew. Это безусловный лидер и бестселлер. Помимо непосредственно функций HEX-редактора, в нем реализовано еще много дополнительных возможностей, связанных с анализом файла: это и дизассемблер, и просмотрщик секций импорта и экспорта, и анализатор заголовка исполняемых файлов. Главный недостаток — все это не бесплатно (хотя и весьма недорого — от 555 рублей).

    HEX-редактор Hiew

    HEX-редактор Hiew

    Если не хочется тратить деньги, то можно обратить внимание, например, на Hex Editor Neo (есть бесплатный вариант) или на HxD Hex Editor.

    Детекторы упаковщиков

    Если есть подозрение, что файл упакован, то с помощью детектора упаковщиков можно попытаться определить, какой упаковщик при этом использовался, и попробовать распаковать исследуемый файл. Долгое время безусловным лидером здесь была программа PEiD, и в принципе можно пользоваться и ей, однако поддержка давно прекращена и новых сигнатур для определения типов упаковщика уже никто не выпускает. Альтернатива — Exeinfo PE.

    Exeinfo PE

    Exeinfo PE

    Эта программа, помимо детекта упаковщиков, имеет еще много других функций для анализа исполняемых файлов Windows, и во многих случаях можно обойтись ей одной.

    Специализированные утилиты для исследования исполняемых файлов Windows

    Программа CFF Explorer из пакета Explorer Suite — это настоящий швейцарский нож для исследователя PE-файлов. Позволяет получить огромное количество разнообразной информации обо всех компонентах структуры PE-файла и, помимо прочего, может служить HEX-редактором.

    CFF Explorer

    CFF Explorer

    Так что настоятельно рекомендую CFF Explorer, тем более что программа бесплатная.

    Python-модуль pefile

    Python-модуль pefile позволит обойтись при анализе PE-файлов исключительно интерпретатором Python. С ним практически все операции по базовому статическому анализу можно реализовать путем написания небольших скриптов. Прелесть всего этого в том, что заниматься исследованием PE-файлов можно в Linux.

    Модуль присутствует в PyPi, и установить его можно через pip:

    Yara

    Ну и в завершение всего списка весьма популярный и востребованный инструмент, ставший своеобразным стандартом в среде антивирусной индустрии, — проект Yara. Разработчики позиционируют его как инструмент, который помогает исследователям малвари идентифицировать и классифицировать вредоносные сэмплы. Исследователь может создать описания для разного типа малвари в виде так называемых правил, используя текстовые или бинарные паттерны.

    WWW

    • Актуальная версия Yara
    • Англоязычная справка по написанию правил
    • Перевод справки на русский (обрати внимание — он слегка устарел)

    Меры предосторожности

    Чтобы обезопасить систему при проведении базового статического анализа подозрительных файлов, необходимо:

    • установить запрет на операцию чтения и выполнения анализируемого файла (вкладка «Безопасность» в контекстном меню «Свойства»);
    • сменить разрешение файла с .exe на какое-нибудь другое (или вообще убрать расширение анализируемого файла);
    • не пытаться открыть файл текстовыми процессорами и браузерами.

    Можно обойтись этими мерами и не использовать виртуальную среду, хотя для полной безопасности можешь установить, например, Virtual Box и проводить анализ в нем (тем более что для динамического анализа без виртуалки, как правило, не обойтись).

    Определение типа файла

    Я думаю тебе известно, что признак PE-файла в Windows — это не только расширение .exe, .dll, .drv или .sys. Внутри него содержатся и другие отличительные черты. Первая из них — это сигнатура из байт вида «MZ» (или 0x4d, 0x5a в шестнадцатеричном представлении) в самом начале файла. Вторая — сигнатура также из двух байт PE и двух нулевых байтов следом (или 0x50, 0x45, 0x00, 0x00 в шестнадцатеричном представлении).

    Смещение этой сигнатуры относительно начала файла записано в так называемом DOS-заголовке в поле e_lfanew, которое находится по смещению 0x3c от начала файла.

    По большому счету наличие этих двух сигнатур в файле и подходящее расширение свидетельствует о том, что перед нами именно PE-файл, однако при желании можно посмотреть еще значение поля Magic опционального заголовка (Optional Header). Это значение находится по смещению 0x18 относительно начала сигнатуры PE. Значение этого поля определяет разрядность исполняемого файла:

    • значение 0x010b говорит о том, что файл 32-разрядный (помни, что в памяти числа располагаются с обратной последовательностью байт, сначала младший байт и далее старшие байты, то есть число 0x010b будет представлено последовательностью 0x0b, 0x01);
    • значение 0x020b говорит о том, что файл 64-разрядный.

    Посмотреть это все можно несколькими способами. Первый — с помощью HEX-редактора.

    Признаки PE-файла в HEX-редакторе Hiew

    Признаки PE-файла в HEX-редакторе Hiew

    Второй — используя CFF Explorer или Exeinfo PE. Они наглядно показывают значения указанных сигнатур.

    Третий способ — использовать возможности Python, запустив такой скрипт:

    with open(<путь к файлу>, 'rb') as file:
    # прочитаем первые 1000 байт файла (больше и не надо)
    buffer = file.read(1000)
    e_ifanew = int.from_bytes(buffer[0x3c:0x40], byteorder='little')
    mz_signature = buffer[0x0:0x2]
    pe_signature = buffer[e_ifanew:e_ifanew + 0x4]
    magic = buffer[e_ifanew + 0x18:e_ifanew + 0x1a]
    if mz_signature == b'MZ' and pe_signature == b'PEx00x00':
    if magic == b'x0bx01':
    print('Файл', sys.argv[1], 'является исполнимым PE32 файлом Windows.')
    elif magic == b'x0bx02':
    print('Файл', sys.argv[1], 'является исполнимым PE64 файлом Windows.')
    else:
    print('Файл', sys.argv[1],'не является PE файлом Windows.')

    Или можешь использовать вот такое правило для Yara:

    import "pe" //импортируем Yara-модуль pe
    rule is_pe_file
    {
    strings:
    $MZ_signature = "MZ"
    condition:
    ($MZ_signature at 0) and (pe.is_32bit() or pe.is_64bit())
    }

    Поиск в VirusTotal по хешу

    Отправить на VirusTotal для проверки можно не только сам файл, но и его хеш (md5, sha1 или sha256). В этом случае, если такой же файл уже анализировался, VirusTotal покажет результаты этого анализа, при этом сам файл на VirusTotal мы не засветим.

    Думаю, как узнать хеш файла, ты прекрасно знаешь. В крайнем случае можно написать небольшой скрипт на Python:

    import hashlib
    with open(<путь к файлу>, 'rb') as file:
    buffer = file.read()
    print('md5 =', hashlib.md5(buffer).hexdigest())
    print('sha1 =', hashlib.sha1(buffer).hexdigest())
    print('sha256 =', hashlib.sha256(buffer).hexdigest())

    Результат подсчета хеша шлем на VirusTotal либо применяем мои рекомендации из статьи «Тотальная проверка. Используем API VirusTotal в своих проектах» и автоматизируем этот процесс с помощью небольшого скрипта на Python.

    import sys
    import requests
    ## будем использовать 2-ю версию API VirusTotal
    api_url = 'https://www.virustotal.com/vtapi/v2/file/report'
    ## не забудь про ключ доступа к функциям VirusTotal
    params = dict(apikey=<ключ доступа к API VirusTotal>, resource=str(sys.argv[1]))
    response = requests.get(api_url, params=params)
    if response.status_code == 200:
    result = response.json()
    if result['response_code'] == 1:
    print('Обнаружено:', result['positives'], '/', result['total'])
    print('Результаты сканирования:')
    for key in result['scans']:
    print('t' + key, '==>', result['scans'][key]['result'])
    elif result['response_code'] == -2:
    print('Запрашиваемый объект находится в очереди на анализ.')
    elif result['response_code'] == 0:
    print('Запрашиваемый объект отсутствует в базе VirusTotal.')
    else:
    print('Ошибка ответа VirusTotal.')
    else:
    print('Ошибка ответа VirusTotal.')

    Как видишь, скрипт получает значение хеша, переданного в виде аргумента командной строки, формирует все нужные запросы для VirusTotal и выводит результаты анализа.

    Если VirusTotal выдал в ответ какие-нибудь результаты анализа, это значит, что исследуемый файл уже кто-то загружал для анализа и его можно загрузить туда повторно и получить более актуальные результаты, на чем анализ можно и завершать. Но вот если VirusTotal не найдет файла в базах, тогда есть смысл идти дальше.

    Поиск и анализ строк

    Некоторые строки внутри файла могут явно свидетельствовать о его злонамеренности, а иногда по ним даже понятно, что конкретно он делает. Например, URL или IP-адреса внутри файла подскажут, что она взаимодействует с какими-то серверами (их, кстати, тоже можно пробить через VirusTotal на вредоносность).

    Могут попадаться и строки с ключами реестра. Например, вот такие пути будут явно указывать на желание файла закрепиться в системе надолго:

    HKLMSOFTWAREMicrosoftWindowsCurrentVersionRun
    HKLMSOFTWAREWow6432NodeMicrosoftWindowsCurrentVersionRun

    Скорее всего, вместе с такими строками в секции импорта найдутся и запросы к функциям API, которые манипулируют ключами реестра.

    Строки можно напрямую поискать с помощью HEX-редактора, а можно использовать консольную утилиту Strings из состава Sysinternals Suite, которая выводит весь текст, что найдет в файле. Строкой утилита считает любую последовательность из трех и более символов ASCII или Unicode, которая завершается нулевым символом.

    Кроме URL, IP и ключей реестра стоит обратить внимание на следующие разновидности текстовых данных.

    • Строки с именами процессов антивирусных программ и различных утилит исследования системы (например, avp.exe для Касперского, ekrn.exe для ESET, drweb32.exe для DrWeb или procexp.exe для Process Explorer из состава Sysinternals Suite). Они могут свидетельствовать о том, что программа ищет эти процессы и собирается их завершить.
    • Строки с именами процессов средств виртуализации (например, VBoxTray.exe или VBoxService.exe для Virtual Box, prl_cc.exe или prl_tools.exe для Parallels, vmsrvc.exe или vmusrvc.exe для Virtual PC) могут означать, что программа пытается определить, что ее запускают в виртуальной машине.
    • Строки с именами процессов браузеров (iexplore.exe, firefox.exe, chrome.exe и т. п.) — возможно, признак внедрения кода в эти браузеры. Это может понадобиться для перехвата трафика или вводимой информации. Как вариант, программа может пытаться загрузить расширение или даже использовать целевой эксплоит для браузера.
    • Строки с именами системных процессов (explorer.exe, svchost.exe и т. д.) могут быть признаком попыток внедрения вредоносного кода в эти процессы либо признаком запуска вредоносных процессов под видом системных. Иногда для поиска и манипуляций с процессом explorer.exe используют имя его окна — progman. Стоит поискать и его.
    • Строки подозрительного содержания. Например, что-нибудь типа keylogger.txt или Portscanner startip.

    Для Yara можно написать универсальные правила, которые помогут искать строки, применив регулярные выражения. Например, для поиска URL или IP в файле можно написать так:

    rule URL
    {
    strings:
    $url = /(https?://)?([w.]+).([a-z]{2,6}.?)(/[w.]*)*/?/ wide ascii
    condition:
    $url
    }
    rule IP
    {
    strings:
    $ip = /([0-9]{1,3}.){3}[0-9]{1,3}/ wide ascii
    condition:
    $ip
    }

    Создатели некоторых вредоносов специально шифруют строки, но серьезные алгоритмы шифрования в таких случаях — это редкость. Так что шифровки можно поискать консольной утилитой Floss (FireEye Labs Obfuscated String Solver). Как и Strings, она ищет строки в файле, но иногда позволяет найти обфусцированные или зашифрованные варианты.

    WWW
    Подробнее об использовании Floss в блоге FireEye

    Часто вирусописатели не заморачиваются и шифруют строки при помощи XOR. Такие строки легко найти при помощи правила для Yara.

    rule xor_string
    {
    strings:
    $string = "HKLMSOFTWAREMicrosoftWindowsCurrentVersionRun" xor
    condition:
    $string
    }

    Такое правило будет искать в файле строку с ключом реестра, поксоренную производным байтом. К сожалению, с регулярными выражениями модификатор xor применить нельзя.

    INFO
    Еще одна удобная программа для поиска строк — это pestudio. Она отмечает все подозрительные строки, на которые стоит обратить внимание.

    Анализ информации PE-заголовка

    При компиляции PE-файла в него включается заголовок (PE-header), который описывает структуру файла. При выполнении файла загрузчик ОС читает информацию из этого заголовка, а затем копирует содержимое файла в память и передает ему исполнение.

    Заголовок PE содержит в себе много информации, например по какому адресу PE-файл должен быть загружен в память, адрес запуска (он же — точка входа), списки библиотек, функций и ресурсов, которые файл будет использовать. Так что изучение заголовка дает при исследовании очень многое.

    Анализ таблицы импорта

    Большинство программ, в том числе вредоносных, используют API-функции, которые предоставляет операционная система. Их код содержится в разных DLL, откуда их и импортирует исполняемый файл. Собственно, перечень этих функций, содержащийся в заголовке, — это один из самых полезных фрагментов информации при исследовании. Стоит на него взглянуть, и уже примерно понимаешь, что делает программа.

    Все это можно посмотреть в так называемой таблице импорта. Например, при помощи CFF Explorer.

    Таблица импорта в CFF Explorer

    Таблица импорта в CFF Explorer

    Или можно использовать Hiew.

    Таблица импорта в Hiew

    Таблица импорта в Hiew

    Как вариант, здесь во всей красе может показать себя Python-модуль pefile. Для вывода секции импорта можно использовать такой скрипт:

    import pefile
    ## не забудь указать реальный путь к исследуемому файлу
    pe = pefile.PE(<путь к файлу>)
    if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
    for dll_entry in pe.DIRECTORY_ENTRY_IMPORT:
    print(dll_entry.dll.decode('utf-8'))
    for api_entry in dll_entry.imports:
    print('t' + api_entry.name.decode('utf-8'))
    else:
    print('Файл не содержит секцию импорта.')

    Вывод таблицы импорта с помощью скрипта на Python

    Вывод таблицы импорта с помощью скрипта на Python

    Вот наиболее популярные DLL, которые встречаются в любых программах:

    • kernel32.dll — содержит базовые функции: доступ и управление памятью, работа с файлами и устройствами;
    • advapi32.dll — обеспечивает доступ к ключевым компонентам Windows (диспетчер служб, реестр), а также содержит API-функции криптографической подсистемы Windows;
    • user32.dll — содержит компоненты графического интерфейса;
    • gdi32.dll — содержит функции графических операций;
    • winnet.dll — содержит высокоуровневые сетевые API-функции, реализующие такие протоколы, как FTP, HTTP и NTP.

    На что стоит обратить внимание при исследовании таблицы импорта?

    В первую очередь — на наличие библиотек ntdll.dll, wsock32.dll и ws2_32.dll. Эти библиотеки редко встречаются в обычных программах, поскольку содержат в себе низкоуровневые API-функции.

    • ntdll.dll содержит функции доступа к компонентам системы. Если встретишь импорт API из этого DLL, это может означать, что программа пытается перехватить системные функции, реализует разные антиотладочные приемы, манипулирует процессами, противодействует антивирусам и т. п.
    • wsock32.dll и ws2_32.dll содержат низкоуровневые API-функции для работы с сокетами. Они обычно используются в узкоспециализированном ПО — и если встретятся при анализе обычной программы, это должно насторожить.

    Наличие библиотеки advapi32.dll и криптографических API-функций вроде CryptGenKey, CryptEncrypt, CryptDecrypt и подобных сразу вызывает подозрение, что перед нами очередной шифровальщик-вымогатель. Создатели таких программ часто используют стандартные крипто-API, а не придумывают собственные реализации.

    Наличие этой же библиотеки вкупе с вызовом функций работы с реестром (типа RegCreateKeyEx, RegEnumKeyEx, RegDeleteKeyExA и т. п.) говорит о манипуляциях с реестром и возможной записи в автозагрузку. Подтверждает это наличие строк с соответствующими ключами реестра.

    Также стоит обратить внимание на слишком маленький импорт или его отсутствие. Это крайне нетипично для обычных программ. Также не совсем типично присутствие в импорте связки API-функций LoadLibrary и GetProcAddress (либо LdrLoadDll и LdrGetProcAddress). Это однозначно говорит о реализации так называемого импорта времени выполнения (в отличие от динамического импорта, когда все импортируемые функции перечислены в секции импорта) и свидетельствует о попытке скрыть настоящее назначение файла. Либо это может говорить о том, что файл упакован.

    INFO

    Как правило при использовании связки LoadLibrary (или LoadLibraryEx) и GetProcAddress (или LdrLoadDll + LdrGetProcAddress) необходимы имена функций, которые будут импортироваться во время выполнения программы, поэтому если нашел эти API в импорте, есть смысл поискать строки с именами импортируемых во время выполнения API-функций. При этом стоит помнить, что они могут быть зашифрованы или обфусцированы.

    Следующие API или их связки также требуют особого внимания. Их наличие в исследуемом файле — повод насторожиться.

    • Связка из VirtualAlloc и VirtualProtect или HeapAlloc и VirtualProtect может свидетельствовать о распаковке рабочей нагрузки вредоносного файла.
    • API-функции CreateProcess или ShellExecute могут свидетельствовать о создании дочерних процессов, например чтобы отслеживать наличие в системе основного процесса и восстанавливать его в случае остановки (это один из распространенных и простейших способов создания так называемого «неубиваемого процесса»).
    • Связка из OpenProcess, VirtualAlloc (или VirtualAllocEx), WriteProcessMemory и CreateRemoteThread — весьма красноречивый признак попытки внедрения кода в какой-либо процесс (особенно вкупе с наличием в файле строки с именем какого-либо процесса).
    • SetWindowsHookEx свидетельствует об установке перехватов других API-функций. Очень часто это делается вовсе не во благо ничего не подозревающего пользователя.
    • Функция RegisterHotKey — признак кейлоггера, она может использоваться для перехвата нажатий на клавиши;
    • Связка из OpenSCManager, CreateService и StartService свидетельствует о создании системного сервиса. Она тоже может использоваться во вред, в частности для создания «неубиваемого процесса».
    • Связка из URLDownloadToFile и ShellExecute — весьма вероятный признак трояна-даунлоадера;
    • Функция TerminateProcess совместно со строками имен процессов антивирусных программ в одном файле практически однозначно свидетельствует о желании исследуемого файла обезопасить себя, грохнув процесс антивируса;
    • Функции IsDebuggerPresent, CheckRemoteDebuggerPresent или OutputDebugString могут говорить о применении простейших антиотладочных приемов. В обычных программах они встречаются редко.

    Правило для Yara, которое распознает, к примеру, связку из OpenProcess, VirtualAlloc, WriteProcessMemory и CreateRomoteThread, может выглядеть так:

    rule api_bandle
    {
    strings:
    $str_api_1 = "OpenProcess"
    $str_api_2 = "VirtualAllocEx"
    $str_api_3 = "WriteProcessMemory"
    $str_api_4 = "CreateRemoteThread"
    condition:
    $str_api_1 and $str_api_2 and $str_api_3 and $str_api_4
    }

    Или так (с использованием Yara-модуля pe):

    import "pe" //импортируем Yara-модуль pe
    rule api_bandle
    {
    condition:
    pe.imports("kernel32.dll", "OpenProcess") and pe.imports("kernel32.dll", "VirtualAllocEx") and pe.imports("kernel32.dll", "WriteProcessMemory") and pe.imports("kernel32.dll", "CreateRemoteThread")
    }

    А вот правило для Yara для распознавания связки из LoadLibrary (или LoadLibraryEx) и GetProcAddress и строк с импортируемой во время выполнения связкой OpenProcess, VirtualAllocEx, WriteProcessMemory и CreateRemoteThread, которые могут быть закрыты побайтовым XOR:

    import "pe" //импортируем Yara-модуль pe
    rule api_bandle
    {
    strings:
    $str_api_1 = "OpenProcess" xor
    $str_api_2 = "VirtualAllocEx" xor
    $str_api_3 = "WriteProcessMemory" xor
    $str_api_4 = "CreateRemoteThread" xor
    condition:
    $str_api_1 and $str_api_2 and $str_api_3 and $str_api_4 and (pe.imports("kernel32.dll", "LoadLibrary") or pe.imports("kernel32.dll", "LoadLibraryEx")) and pe.imports("kernel32.dll", "GetProcAddress")
    }

    Для сравнения секций импорта разных файлов можно использовать хеш импорта, так называемый imphash. Это хеш md5 от секции импорта после некоторой нормализации. Подробнее о нем можешь почитать в блоге FireEye.

    В Yara imphash можно определить с помощью функции imphash() модуля pe:

    import "pe"
    rule imphash
    {
    condition:
    pe.imphash() == "8a25c84dc57052979d26f561d4f12335"
    }

    На Python можно написать вот так:

    import pefile
    ## не забудь указать реальный путь к исследуемому файлу
    pe = pefile.PE(<путь к файлу>)
    print('Imphash =', pe.get_imphash())

    Используя значение imphash, вычисленное для одного файла, с помощью написанного выше правила Yara можно искать файлы с одинаковой таблицей импорта (и с большой вероятностью с похожим предназначением).

    INFO

    Утилита pestudio тоже позволяет анализировать секцию импорта, причем она не только показывает импортируемые API-функции, но и отмечает те, что часто встречаются в малвари, и показывает возможный вектор атаки по классификации MITRE ATT&CK.

    Анализ таблицы экспорта

    Вредоносные файлы с экспортируемыми функциями — редкое явление, однако иногда на просторах вирусных полей они встречаются. Бывают в том числе и вредоносные DLL.

    Таблицу экспорта, в которой перечислены экспортируемые функции, можно так же, как и таблицу импорта, посмотреть в CFF Explorer или Hiew.

    Таблица экспорта в CFF Explorer

    Таблица экспорта в CFF Explorer

    Здесь нужно обратить внимание на говорящие сами за себя названия экспортируемых функций, либо на названия функций в виде беспорядочного набора символов, либо на отсутствие названий функций при наличии только ординалов (номеров) функций (такое тоже может быть, ведь функции можно экспортировать не только по имени, но и по ординалу).

    На Python можно сделать следующий скрипт для просмотра таблицы экспорта:

    import pefile
    ## не забудь указать реальный путь к исследуемому файлу
    pe = pefile.PE(<путь к файлу>)
    if hasattr(pe, 'DIRECTORY_ENTRY_EXPORT'):
    for export_entry in pe.DIRECTORY_ENTRY_EXPORT.symbols:
    print('t' + export_entry.name.decode('utf-8'))
    print('ttОрдинал:', str(hex(export_entry.ordinal)))
    print('ttRVA функции:', str(hex(export_entry.address)))
    else:
    print('Файл не содержит секцию экспорта.')

    Анализ таблицы секций

    Фактически все содержимое PE-файла разбито на секции. Каждая секция хранит в себе либо код, который будет исполнен при запуске файла, либо данные, необходимые для выполнения, либо ресурсы, используемые файлом. У каждой секции есть имя, однако операционная система определяет назначение секции не по имени, а по атрибуту Characteristics, а имена используются только для наглядности.

    Помимо назначения секции атрибут Characteristics определяет операции, которые можно проводить с данными секции (чтение, выполнение, запись и т. д.). Более подробно о секции в целом и об этом атрибуте можно почитать в официальной документации. Наиболее часто используемые названия секций:

    • .text или CODE — как правило, содержит исполняемый код (название секции CODE характерно для программ, написанных на Delphi), в большинстве случаев имеет значение атрибута Characteristics, равное 0x60000020 (IMAGE_SCN_CNT_CODE & IMAGE_SCN_MEM_EXECUTE & IMAGE_SCN_MEM_READ);
    • .data или DATA — обычно здесь лежат данные для чтения или записи (название секции DATA также характерно для программ, написанных на Delphi), Characteristics чаще всего равен 0xс0000040 (IMAGE_SCN_CNT_INITIALIZED_DATA & IMAGE_SCN_MEM_READ & IMAGE_SCN_MEM_WRITE);
    • .rdata — данные только для чтения, иногда здесь лежат таблицы импорта и экспорта, Characteristics равен 0x40000040 (IMAGE_SCN_CNT_INITIALIZED_DATA & IMAGE_SCN_MEM_READ) или 0x50000040 (IMAGE_SCN_CNT_INITIALIZED_DATA & IMAGE_SCN_MEM_READ & IMAGE_SCN_MEM_SHARED);
    • .idata — информация об импорте (если секция отсутствует, то импорт содержится в секции .rdata), Characteristics чаще всего равен 0xс0000040 (такое же, как и у секции .data);
    • .edata — информация об экспорте (если секция отсутствует, то экспорт содержится в секции .rdata), Characteristics обычно равен 0xс0000040 (такое же, как и у секции .data);
    • .rsrc — ресурсы, используемые PE-файлом (иконки, диалоговые окна, меню, строки и т. д.), Characteristics равен 0x50000040 либо 0x40000040.

    Также могут встречаться секции .tls, .reloc, .pdata, .bss (или BSS), .debug, .CRT, .didat. Наличие секции BSS вместе с секциями CODE и DATA означает, что автор программы использовал компилятор Delphi, а если есть секции .bss и .CRT, это может означать, что программу компилировали в MinGW.

    Увидеть это все легко можно с помощью, например, CFF Explorer.

    Таблица секций в CFF Explorer

    Таблица секций в CFF Explorer

    На что нужно обратить внимание при анализе таблицы секций?

    Во-первых, на необычные названия секций. Например, в виде беспорядочного набора символов.

    Во-вторых, на несоответствие атрибута Characteristics назначению и содержимому секции. Например, может быть так, что у секции .text, в которой содержится исполняемый код, помимо прочего еще добавлено IMAGE_SCN_MEM_WRITE, то есть в секцию с кодом можно писать данные. Это явный признак самомодифицирующегося кода, и в обычных программах такое почти не встречается. То же можно сказать и про секцию с данными (.data или DATA): если в атрибуте Characteristics помимо прочего присутствует IMAGE_SCN_MEM_EXECUTE, то это очень серьезный повод для подозрения.

    В-третьих, наличие секций вроде UPX0, UPX1 или .aspack красноречиво свидетельствует о применении соответствующих упаковщиков.

    Секции UPX0 и UPX1 в запакованном файле

    Секции UPX0 и UPX1 в запакованном файле

    Также о применении упаковщиков может свидетельствовать высокое значение (близкое к 8) энтропии какой-либо секции. Посчитать энтропию секций PE-файла можно с помощью вот такого скрипта на Python:

    import pefile
    ## не забудь указать реальный путь к исследуемому файлу
    pe = pefile.PE(<путь к файлу>)
    for section_entry in pe.sections:
    print(section_entry.Name.decode('utf-8'))
    print('tCharacteristics:', hex(section_entry.Characteristics))
    print('tMD5 хэш секции:', section_entry.get_hash_md5())
    print('tЭнтропия секции:', section_entry.get_entropy())

    Скрипт выводит имена всех секций PE-файла, значение атрибута Characteristics, md5-хеш и энтропию каждой секции.

    Значение энтропии одной из секций свидетельствует о возможном наличии упаковки

    Значение энтропии одной из секций свидетельствует о возможном наличии упаковки

    В Yara энтропию можно определить с помощью функции entropy() модуля math.

    Временная метка компиляции

    Информация о времени компиляции анализируемого файла может быть полезна при построении графа атаки и его анализе. Время создания (и, соответственно, компиляции PE-файла) хранится в PE-заголовке в виде четырехбайтового числа, содержащего количество секунд, прошедших с 0 часов 0 минут 1 января 1970 года.

    Время компиляции файла в CFF Explorer

    Время компиляции файла в CFF Explorer

    В удобоваримом виде значение этого времени можно посмотреть с помощью такого скрипта:

    import pefile
    ## не забудь указать реальный путь к исследуемому файлу
    pe = pefile.PE(<путь к файлу>)
    print('Дата и время компиляции:', time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(pe.FILE_HEADER.TimeDateStamp)))

    Для Delphi (а вредоносные файлы, написанные на Delphi, встречаются и по сей день) это значение всегда равно 0x2a425e19, что значит 0 часов 0 минут 19 июня 1992 года. В этом случае реальную дату компиляции можно попытаться определить из отметки времени секции .rsrc (в файлах, создаваемых Delphi, она всегда присутствует). Временная метка находится по смещению 4 от начала секции .rsrc и представляет собой четырехбайтовое число в формате MS-DOS time.

    Посмотреть это значение в пристойном виде можно следующим скриптом:

    import pefile
    ## не забудь указать реальный путь к исследуемому файлу
    pe = pefile.PE(<путь к файлу>)
    time_stamp_dos = pe.DIRECTORY_ENTRY_RESOURCE.struct.TimeDateStamp
    ## преобразуем время из MS DOS формата в «нормальный» вид
    day = time_stamp_dos >> 16 & 0x1f
    month = time_stamp_dos >> 21 & 0x7
    year = (time_stamp_dos >> 25 & 0xff) + 1980
    second = (time_stamp_dos & 0x1f) * 2
    minute = time_stamp_dos >> 5 & 0x3f
    hour = time_stamp_dos >> 11 & 0x1f
    print('Дата и время компиляции: {}-{}-{} {:02d}:{:02d}:{:02d}'.format(day, month, year, hour, minute, second))

    Если PE-файл компилировался Visual Studio и при компиляции в файл была включена отладочная информация (а это можно определить по наличию таблицы Debug Directory в PE-файле), то дата компиляции (помимо заголовка PE-файла) также содержится и в этой таблице:

    Таблица Debug Directory в PE-файле и отметка о времени компиляции

    Таблица Debug Directory в PE-файле и отметка о времени компиляции

    Посмотреть временную метку компиляции из Debug Directory в «нормальном» виде можно следующим скриптом:

    import pefile
    ## не забудь указать реальный путь к исследуемому файлу
    pe = pefile.PE(<путь к файлу>)
    time_stamp = pe.DIRECTORY_ENTRY_DEBUG[0].struct.TimeDateStamp
    print('Дата и время компиляции:', time.strftime('%d-%m-%Y %H:%M:%S', time.gmtime(time_stamp)))

    При анализе временной метки компиляции под подозрением должны быть:

    • недавняя дата компиляции программы (или нереальные ее значения, например еще не наступившая дата);
    • несовпадение даты компиляции и версии компилятора (согласись, странно видеть дату компиляции, например, 20 июня 2005 года для экзешника, откомпилированного Visual Studio 19 версии);
    • значение даты компиляции равно нулю (велика вероятность, что создатель программы это сделал намеренно, соответственно возникает вопрос — зачем);
    • для файлов, которые по всем признакам откомпилированы в Delphi, дата не соответствует значению 0x2a425e19, а дата, полученная из секции .rsrc, равна нулю или меньше, чем дата в PE-заголовке;
    • дата компиляции из заголовка анализируемого файла не совпадает с датой, указанной в Debug Directory (весьма вероятно, что эти значения были зачем-то скорректированы).

    INFO

    У некоторых компонентов Windows поле TimeDateStamp в PE-заголовке может иметь интересные значения — либо из будущего (к примеру, у меня для «Блокнота» это 8 сентября 2028 года), либо из прошлого (встречаются компоненты, датированные 1980 годом).

    Анализ ресурсов исполняемого файла

    Ресурсы, необходимые для работы exe-файла (такие как иконки, диалоговые окна, меню, изображения, информация о версии, конфигурационные данные), хранятся в секции .rsrc. Просмотреть можно при помощи все того же CFF Explorer.

    Содержимое секции .rsrc в CFF Explorer

    Содержимое секции .rsrc в CFF Explorer

    Но все же для просмотра ресурсов в PE-файлах лучше использовать Resource Hacker.

    Просмотр информации о версии программы в секции ресурсов Resource Hacker

    Просмотр информации о версии программы в секции ресурсов Resource Hacker

    Поскольку в секции ресурсов могут хранится любые данные, туда могут быть помещены либо вредоносная нагрузка, либо драйвер (например, перехватывающий системные функции), либо еще что-нибудь не очень хорошее. Поэтому стоит призадуматься, если найдешь здесь что-то совсем не похожее на иконки, картинки, диалоги, окна, информацию о версии и прочие безобидные вещи.

    Rich-сигнатура

    В статье я не упомянул такую примечательную структуру PE-файла, как Rich-сигнатура. На нее тоже стоит обратить внимание при анализе подозрительных файлов. Почитать о ней на английском можно здесь:

    • Rich Headers: Leveraging this Mysterious Artifact of the PE Format (PDF)
    • Microsoft’s Rich Signature (NTCore)

    Также я написал скрипт на Python для просмотра Rich-сигнатуры.

    Заключение

    С помощью нескольких относительно простых инструментов мы можем быстро проанализировать подозрительный исполняемый файл, частично (а иной раз и достаточно полно) понять, что он собой представляет, и вынести вердикт о возможной вредоносности. Однако при анализе сложных файлов, подвергнутых упаковке, шифрованию и обфускации, этого может оказаться недостаточно. Тогда без более детального статического и динамического анализа не обойтись. Об этом мы и поговорим в следующий раз.

    Опубликовал | Дата 21 мая, 2012

    Как проверить НЕХ-файл

         Многие радиолюбители, пытаясь повторить то или иное устройство на микроконтроллере, нередко сталкиваются с необъяснимыми, на первый взгляд, трудностями. И микроконтроллер в порядке, и программатор исправен, и схема рабочая, но работать, как следует, устройство не хочет. На самом деле в подавляющем большинстве случаев виноваты ошибки, допущенные при ручном вводе в компьютер НЕХ-файла программы. Значительно реже бывают сбои при копировании файлов с дисков или «скачивании» их из Интернета.
    Любая опечатка в НЕХ-файле ведет к выполнению микроконтроллером неверной команды. Ни один программист в этой ситуации не сможет по внешним признакам точно указать место ошибки. Остается очень тщательно сверять НЕХ-файл. Очень муторное занятие. К счастью для проверки Hex- файлов существует программа CheckHEX, которой была посвящена статья А. Долгого «Как проверить HEX-файл» («Радио», 2003, № 8, с. 27, 28) и которую можно скачать здесь.

    Дополнение
    Для проверки HEX- файлов есть еще одна программа, разработанная П. Высочанским. Ее можно скачать с FTP-сервера журнаоа «Радио» . Описание этой программы опубликовано в «Радио» за 2009г №10 стр.26

    Просмотров:4 917

    Понравилась статья? Поделить с друзьями:
  • Ошибки водогрейки аристон
  • Ошибки загрузки и отображения почты яндекс
  • Ошибки водителей при дтп
  • Ошибки водителей новичков
  • Ошибки жизненного пути обломова