После установки 2005й версии
нужно выполнить ряд настроек
1. Выключить проверку сертификатов:
http://msmvps.com/blogs/gladchenko/archive/2007/01/16/497463.aspx
EXEC sp_fulltext_service 'verify_signature', 0;
GO
2. Указать фиксированный объем памяти
3. Обновить версию до SP3 (>=9.0.4035), т.к. изменена работа оптимизатора запросов
4. Использовать только х64 редакцию (2005й лучше реализует преимущества на больших объемах данных), а версия Enterprise "умеет делать параллельное выполнение индексирования". На небольших объемах данных и количестве пользователей разница не существенна.
5. Проинсталировать Perfomance Dashboard (с SP2)
6. Региональные настройки (кодовая страница) SQL должны соответствовать рег.настройкам Windows Server
7.Иногда бывает полезным выключать служебную трассировку:
select * from fn_trace_getinfo(0)
exec sp_configure 'show advanced options', 1
reconfigure with override
exec sp_configure 'default trace enabled', 0
reconfigure with override
Незнание у IT-специалистов этих тонкостей создает ложное представление о возможностях СУБД
взято у http://www.gilev.ru/1c/mssql/SQL2005vs2000.htm за что большая благодарность
Monday, June 29, 2009
Friday, January 30, 2009
продолжаем мучать WMI
получаем пользователей с компа или домена(актив директории)
public static void GetUsers()
{
SelectQuery sQuery = new SelectQuery("Win32_UserAccount","Domain='CHAKS-PC'");
try
{
ManagementObjectSearcher mSearcher = new ManagementObjectSearcher(sQuery);
Console.WriteLine("User Accounts");
Console.WriteLine("");
foreach (ManagementObject mObject in mSearcher.Get())
{
Console.WriteLine(mObject["Name"]);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.ReadKey();
}
Получение группы
public static void GetGroups()
{
SelectQuery sQuery = new SelectQuery("Win32_Group", "Domain='CHAKS-PC'");
try
{
ManagementObjectSearcher mSearcher = new ManagementObjectSearcher(sQuery);
Console.WriteLine("Groups");
Console.WriteLine("");
foreach (ManagementObject mObject in mSearcher.Get())
{
Console.WriteLine(mObject["Name"]);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.ReadKey();
}
Решение выборка пользователей из группы
public static void GetUsers(String DomainName, String GroupName)
{
#region Build WMI query using SelectQuery
///
/// Alternate method for building query
/// Which I think is better approach
///
StringBuilder sBuilder = new StringBuilder("GroupComponent=");
sBuilder.Append('"');
sBuilder.Append("Win32_Group.Domain=");
sBuilder.Append("'");
sBuilder.Append(DomainName);
sBuilder.Append("'");
sBuilder.Append(",Name=");
sBuilder.Append("'");
sBuilder.Append(GroupName);
sBuilder.Append("'");
sBuilder.Append('"');
SelectQuery sQuery = new SelectQuery("Win32_GroupUser", sBuilder.ToString());
#endregion
///
/// Execute the query
/// Construct a ManagementPath from the PartComponent and check for ClassName
/// and extract the UserName
/// Depending on which method you used to build the query,
/// pass the String or SelectQuery object to ManagementObjectSearcher
///
try
{
ManagementObjectSearcher mSearcher = new ManagementObjectSearcher(sQuery);
foreach (ManagementObject mObject in mSearcher.Get())
{
ManagementPath path = new ManagementPath(mObject["PartComponent"].ToString());
if (path.ClassName == "Win32_UserAccount")
{
String[] names = path.RelativePath.Split(',');
Console.WriteLine(names[1].Substring(names[1].IndexOf("=") + 1).Replace('"', ' ').Trim());
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.ReadKey();
}
Добавляем безопасность
ConnectionOptions co = new ConnectionOptions();
co.Username = "Домен\Пользователь";
co.Impersonation = ImpersonationLevel.Impersonate;
co.Password = "Пароль пользователя";
string stringMachineName = "Компутер";
System.Management.ManagementScope mSearcher = new System.Management.ManagementScope("\\\\" + stringMachineName + "\\root\\cimv2", co);
public static void GetUsers()
{
SelectQuery sQuery = new SelectQuery("Win32_UserAccount","Domain='CHAKS-PC'");
try
{
ManagementObjectSearcher mSearcher = new ManagementObjectSearcher(sQuery);
Console.WriteLine("User Accounts");
Console.WriteLine("");
foreach (ManagementObject mObject in mSearcher.Get())
{
Console.WriteLine(mObject["Name"]);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.ReadKey();
}
Получение группы
public static void GetGroups()
{
SelectQuery sQuery = new SelectQuery("Win32_Group", "Domain='CHAKS-PC'");
try
{
ManagementObjectSearcher mSearcher = new ManagementObjectSearcher(sQuery);
Console.WriteLine("Groups");
Console.WriteLine("");
foreach (ManagementObject mObject in mSearcher.Get())
{
Console.WriteLine(mObject["Name"]);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.ReadKey();
}
Решение выборка пользователей из группы
public static void GetUsers(String DomainName, String GroupName)
{
#region Build WMI query using SelectQuery
///
/// Alternate method for building query
/// Which I think is better approach
///
StringBuilder sBuilder = new StringBuilder("GroupComponent=");
sBuilder.Append('"');
sBuilder.Append("Win32_Group.Domain=");
sBuilder.Append("'");
sBuilder.Append(DomainName);
sBuilder.Append("'");
sBuilder.Append(",Name=");
sBuilder.Append("'");
sBuilder.Append(GroupName);
sBuilder.Append("'");
sBuilder.Append('"');
SelectQuery sQuery = new SelectQuery("Win32_GroupUser", sBuilder.ToString());
#endregion
///
/// Execute the query
/// Construct a ManagementPath from the PartComponent and check for ClassName
/// and extract the UserName
/// Depending on which method you used to build the query,
/// pass the String or SelectQuery object to ManagementObjectSearcher
///
try
{
ManagementObjectSearcher mSearcher = new ManagementObjectSearcher(sQuery);
foreach (ManagementObject mObject in mSearcher.Get())
{
ManagementPath path = new ManagementPath(mObject["PartComponent"].ToString());
if (path.ClassName == "Win32_UserAccount")
{
String[] names = path.RelativePath.Split(',');
Console.WriteLine(names[1].Substring(names[1].IndexOf("=") + 1).Replace('"', ' ').Trim());
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.ReadKey();
}
Добавляем безопасность
ConnectionOptions co = new ConnectionOptions();
co.Username = "Домен\Пользователь";
co.Impersonation = ImpersonationLevel.Impersonate;
co.Password = "Пароль пользователя";
string stringMachineName = "Компутер";
System.Management.ManagementScope mSearcher = new System.Management.ManagementScope("\\\\" + stringMachineName + "\\root\\cimv2", co);
Tuesday, January 20, 2009
ms sql int to bit
ms sql int to bit
declare @intvalue int
set @intvalue=9999999
declare @vsresult varchar(64)
declare @inti int
select @inti = 24, @vsresult = ''
while @inti>0
begin
select @vsresult=convert(char(1), @intvalue % 2)+@vsresult,
@intvalue = convert(int, (@intvalue / 2)),
@inti=@inti-1
end
select @vsresult
declare @intvalue int
set @intvalue=9999999
declare @vsresult varchar(64)
declare @inti int
select @inti = 24, @vsresult = ''
while @inti>0
begin
select @vsresult=convert(char(1), @intvalue % 2)+@vsresult,
@intvalue = convert(int, (@intvalue / 2)),
@inti=@inti-1
end
select @vsresult
Monday, January 19, 2009
Контрольные суммы
CRC: как защитить программу
Всем нам свойственно ошибаться, но иногда мы вовремя обнаруживаем свои ошибки. Пусть ты не сможешь умножить в уме 790 г. колбасы на 134 рубля 50 копеек, но если продавщица говорит: «115 рублей, молодой человек», то ты можешь прикинуть (около 120 рублей умножить на 1/4 килограмма будет 30 рублей, 130 минус 30 — сто рублей) и понять, что эта добрая тетя пытается тебя обдурить, присвоив себе десятку. Компьютеры тоже ошибаются. Сбоит память, на винчестерах появляются бэдблоки, мыши в колодцах грызут телефонные кабели. Так в информацию вносятся ошибки, которые нужно обнаруживать и по возможности исправлять.
Чтобы найти ошибку, к сообщению добавляют контрольную сумму (checksum). В самом простом случае это сумма всех байтов сообщения. Например:
Сообщение: 12 34 56
Контрольная сумма: 12+34+56=102
После передачи в это сообщение могут быть внесены помехи, например, так:
Искаженное сообщение: 12 36 56, контрольная сумма 102
Если теперь сложить байты сообщения, результат не совпадет с контрольной суммой. Так программа может сделать вывод, что данные были повреждены, и принять меры (например, еще раз запросить пакет TCP/IP или выдать сообщение, что архив поврежден).
CRC, или циклический избыточный код, — это улучшенный (и усложненный) вариант контрольной суммы. В этой статье будет рассказано об алгоритме CRC32, который применяется в протоколе TCP/IP, архиваторах Zip и Rar. Затем я расскажу тебе, как защитить свою программу от модификаций, проверяя ее CRC.
Чем плоха контрольная сумма
Во-первых, если просто складывать байты, то старшие биты будут изменяться реже, чем младшие. То есть, если мы складываем
12 34 56, контрольная сумма 102
12 34 56 23, контрольная сумма 125
12 34 56 23 45, контрольная сумма 170
результат останется в пределах двух сотен. Если контрольная сумма записана в 32-разрядное или 64-разрядное слово, старшие байты будут содержать нули. Это не есть хорошо, так как все биты контрольной суммы должны быть равноценными.
Во-вторых, сообщения с переставленными байтами будут иметь одну и ту же сумму:
12 34 56, контрольная сумма 102
56 12 34, контрольная сумма 102
Несмотря на все эти недостатки, разные варианты контрольной суммы используются довольно широко, например, в штрих-кодах (barcode). У меня в руках банка консервированной кукурузы, на которой написан такой штрих-код:
5 998483 710125
Это код EAN-13 (тринадцать цифр). Правило для его проверки такое: сложи цифры на четных позициях, умножь сумму на три и добавь цифры на нечетных позициях. Должно получиться число, которое делится на десять:
9 + 8 + 8+ 7 + 0 + 2 = 34
5 + 9 + 4 + 3 + 1 + 1 + 5 = 28
34 * 3 + 28 = 130, делится на 10
А чтобы это условие выполнялось, последнюю цифру, 5, делают контрольной суммой. То есть складывают по этим правилам все остальные цифры, а последнюю цифру вычисляют как 10 минус последняя цифра суммы. Контрольная сумма нужна затем, чтобы сканер в супермаркете не считывал неправильный код если упаковка грязная или продавщица случайно закрыла код рукой. Если интересно, можешь проверить по этому правилу штрих-коды на любых упаковках пищевых продуктов (но не книг — у них другой код, ISBN).
Есть очень простой, короткий и быстрый (примерно в 10 раз быстрее CRC) способ подсчета контрольной суммы. Берем по 4 байта из файла, и делаем с ними логическую операцию XOR. То, что получится в результате, — контрольная сумма.
unsigned long XORCount(void* data, size_t bytesread)
// data — сообщение, size_t — его длина
{
*(long*)(data + bytesread) = 0; // Подписать 4 нулевых байта
bytesread /= sizeof(long);
while(bytesread--)
sum ^= *(long*)data, data+=sizeof(long);
// Первые 4 байта XOR вторые 4 байта XOR третьи...
return sum;
}
В этой контрольной сумме все байты используются полностью, среди них нет более значимых или менее значимых. Теоретическая вероятность того, что контрольная сумма окажется правильной для испорченного файла — 1 шанс на 2 ^ 32. Но операция XOR обладает таким свойством, что A XOR A = 0. Поэтому для сообщений
12 34 A6 7B 91 92 93 94 91 92 93 94
12 34 A6 7B 12 34 56 78 12 34 56 78
12 34 A6 7B 00 00 00 00 00 00 00 00
контрольная сумма будет одинаковой, как и для любых других, содержащих четное число одинаковых четверок байт (или же просто 8, 16, 24 или 32 одинаковых байт). И если вместо NOP'ов записать в исполнимый файл нули или любые другие байты (но число байт обязательно кратно 8), то программа этого не обнаружит. Все это плохо, но не смертельно, поэтому этим алгоритмом вполне можно пользоваться, если нужна высокая скорость проверки.
Что такое CRC
Запомни простую формулу: CRC = сообщение % полином
То есть все сообщение (файл, архив) делим по модулю на некоторую константу (ее называют полиномом). Остаток от деления и есть CRC. О том, как весь файл можно разделить на число, я скажу чуть ниже, а пока — урок арифметики. Но не обычной арифметики, а полиномиальной. Что же это за арифметика такая? Это двоичная арифметика без переносов и заемов. Если сложить 1+1 в обычной двоичной арифметике, получится 10 (переносим единицу). Если вычесть 10–1, получится 1 (занимаем единицу).
В полиномиальной арифметике:
0+0 = 0 0–0=0
0+1 = 1 0–1=1 (не занимаем!)
1+0 = 1 1–0=1
1+1 = 0 (не переносим!) 1–1=0
Видно, что сложение в полиномиальной арифметике — это то же, что и вычитание. И если тебя мучили таблицами истинности на уроках информатики, ты сразу вспомнишь, что это операция XOR. В учебниках по дискретной математике ее обозначают кружком с косым крестиком внутри. Я буду обозначать эту операцию крышкой ^, как в Си. В полиномиальной арифметике 100 плюс 110 равно 10, но 100 минус 110 тоже равно 10. Нет ни знака, ни определенного порядка битов. Все биты равнозначны, и это очень важное свойство для CRC. Если переставить несколько битов в обоих слагаемых, те же биты будут переставлены в сумме:
1010 ^ 1100=01 10, поменяем местами первые два и последние два бита:
1010 ^ 0011=10 01 (а теперь сравни 19+34=53 и 91+43=134, а не 35).
Биты можно представить как коэффициенты многочлена (полинома). Поэтому арифметику называют полиномиальной, а делитель в алгоритмах CRC — полиномом. В общем, все это математические заморочки, но знать будет не лишнее.
Умножение в полиномиальной арифметике нам не понадобится, а вот о делении нужно сказать подробнее. Делим, как во втором классе, уголком, но вместо вычитания используем операцию XOR:
Сообщение: 1101010
Полином: 101
1101010
^101
====
111010
^101
===
10010
^101
===== получили 0, сдвигаемся на 2 бита
110
^101
===
11
Готово! CRC = 11
Именно так считают CRC. Заметь, что в каждом столбике мы вычитаем старшие биты 1–1=0. В следующих битах могут быть любые числа. Один раз мы получили ноль в старшем бите, и нам пришлось сдвинуться вправо на 2 бита, а не на один. Итак, можно записать такой алгоритм (это не рабочий код, он только показывает алгоритм):
// data - сообщение (битовая строка), POLY - полином
while(length(data) > length(POLY)){
r = TOPBIT(data); // Выделяем старший бит data
data <<= 1; // И выкидываем его из основного числа data
if(r)
data ^= POLY;
}
В столбиках мы сдвигали полином 101 вправо, каждый раз вычитая его из сообщения. В этом алгоритме полином остается на месте, но мы «двигаем» делимое влево. Если старший бит r равен нулю, мы сдвигаемся еще на один бит, не вычитая POLY. Константа POLY равна полиному без старшей единицы, то есть 01. Обрати на это внимание: первую единицу писать незачем, так как двоичное число всегда начинается с единицы. Как работает этот код, легче понять на примере. Возьмем то же сообщение 1101010 и тот же полином 101 (сравни со столбиком выше):
Шаг 1. r = 1 // Отделили первый бит
data = 101010 // r=1, поэтому делаем XOR
^01
======
111010
Шаг 2. r = 1
data = 11010
^01
=====
10010
Шаг 3. r = 1
data = 0010
^01
====
0110
Шаг 4. r = 0 // XOR не делаем
data = 110
Шаг 5. r = 1
data = 10
^01
==
11
Итак, алгоритм в целом понятен: делим нацело data на POLY, получаем crc. И при делении 0–1=1, 1+1=0 без переноса.
Сложность состоит в том, что сообщение может весить пару мегабайт. Как же разделить его на полином? Заметь, что при каждом проходе цикла у нас меняются только 2 первых бита data. Значит, можно проходить по всему сообщению, читая в каждый момент времени небольшую порцию данных (в нашем случае — первые два бита).
Как работает табличная реализация
Но у этого алгоритма есть еще один недостаток: он обрабатывает по одному биту сообщения. Например, для мегабайтного файла он сделает 8 миллионов проходов цикла, и каждый раз будет извлекать отдельные биты. Согласись, это никуда не годится! Есть общепринятый трюк, который ускоряет подсчет CRC чуть ли не в десятки раз. Идея такова: будем обрабатывать по байту за один проход цикла. Когда мы делим байт на полином, у нас в остатке получается некоторое число, причем оно не зависит от других байтов сообщения. Вот это число мы можем хранить в таблице для каждого делимого байта. Имея такую таблицу, будем получать CRC для каждого байта за один проход. Сейчас я расскажу, как построить такую таблицу и что конкретно в ней будет находиться. Чтобы не маяться с длинными таблицами, возьмем байт, равный 3 битам, и короткий полином 111. Пусть сообщение состоит из 5 бит, назовем их abcde. Пройдем наш старый алгоритм по шагам:
Шаг 1. if(a) // Запись условная, это не рабочий код
bc ^= 11;
Шаг 2. if(b)
cd ^= 11; // Полином 110 без первой единицы
Шаг 3. if(c)
de ^= 11;
Когда мы подсчитали bcd и перешли на второй шаг, бит a уже не нужен, и на дальнейшие подсчеты он никак не влияет. Когда дошли до последнего шага, оказались ненужными биты a и b. А после третьего шага сыграл свою роль бит c, который теперь сходит со сцены. То, что поменялись биты abc, уже не важно, потому что на четвертом, пятом и так далее шаге они не будут использоваться. Но на этих трех шагах как-то изменились биты de. И изменились они в зависимости от битов abc. Давай переберем все значения abc, начиная с 000 и до 111.
000 (a=0, b=0, c=0) — ни одно из условий не выполняется, поэтому биты def не изменились.
001 (a=0, b=0, c=1) — условие if(c) выполнилось. Я запишу это так:
abc
001def
^11
010 — условие if(b) выполнилось, но после добавления единицы к c выполнилось также if(c). Запишем под чертой результат операции XOR над двумя соответствующими числами в битах de:
abc
010de
^11
^11
==
01
011 — выполнилось условие if(b), но бит c был при этом обнулен, поэтому if(c) не сработало:
abc
011de
^11
==
10
100 — сработало условие if(a), которое вызвало if(b). В результате бит d будет подвергнут операции XOR с единицей (далее будем говорить проще, XOR'ится с единицей):
abc
100de
^11
^11
==
10
101 — аналогично, но бит c обнулился, и результат — нулевой:
abc
101de
^11
==
00
То же самое ты можешь написать для 110 и 111. Довольно муторное дело, но в нем нет ничего сложного. Сделаем массив T с индексами от 000 до 111, в котором будем хранить результаты наших вычислений:
индекс значение
000 00
001 11
010 01
011 10
100 10
101 00
110 11
111 00
Теперь рассчитать CRC можно, что называется, в два притопа, три прихлопа. Смотри:
de ^= t[abc]; // Код условный, не рабочий.
gh ^= t[def]; // t — массив, abc def ghi — сообщение
crc = ghi;
Если вынести текущий изменяемый байт в отдельную переменную, расширить байт до 8 бит и взять 32-битный полином, получим почти готовый код для расчета CRC:
static const long t[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd,
// И так далее, все 256 элементов смотри в коде к статье
}
unsigned long CRCCount(char* buff, size_t bufflen)
{
unsigned long crc = CRCINIT;
while(bufflen--)
crc = t[crc >> 24] ^ ((crc << 8) | *buff++));
сrс = t[сrс >> 24] ^ (сrс << 8); // Подчищаем «хвосты»
сrс = t[сrс >> 24] ^ (сrс << 8);
сrс = t[сrс >> 24] ^ (сrс << 8);
сrс = t[сrс >> 24] ^ (сrс << 8);
return ~crc; // Вернуть инвертированный crc - см. ниже
}
Здесь на каждом шаге мы выбираем элемент из таблицы T по значению старшего байта (crc >> 24) и XOR'им его с очередным байтом. Этот байт у нас каждый раз сдвигается влево, а на его место приходит новый из сообщения (*buff++). Все эти сдвиги нужны для того, чтобы использовать длинный 32-битный полином, который XOR'ится с четырьмя соседними байтами сразу. В последних четырех строчках мы проводим через серию XOR'ов и сдвигаем влево оставшийся в младшем байте crc последний байт файла. По правилам вычисления CRC все символы должны «уйти» влево, за пределы переменной. На этом заканчивается вычисление CRC — остатка от деления сообщения на полином в полиномиальной арифметике. Итак, в таблице хранятся сдвинутые и проXORенные значения полинома. Конкретные сдвиги зависят от индекса массива, который есть предыдущий байт (abc или crc >> 24), а значение следующего байта (def или (crc << 8) | *buff++) XOR'ится с элементом массива t[abc].
Где кончается теория и начинается практика
Что же, простая и быстрая реализация алгоритма для расчета CRC у нас уже есть. Уточним некоторые детали: как выбрать полином и что такое перевернутые алгоритмы. Начнем с того, что приведенный выше алгоритм практически всегда преобразуют по некоторым математическим формулам и переписывают так:
crc = CRCINIT;
while (bufflen--)
crc = t[(crc >> 24 ^ *buff++) & 0xFF] ^ (crc << 8);
Это позволяет избавиться от четырех последних строчек, хотя не делает алгоритм ни проще, ни быстрее. Кстати, скобки вокруг (crc << 8) необязательны, потому что операция сдвига в Си имеет больший приоритет, чем XOR. Но для удобочитаемости скобки обычно ставят.
CRCINIT — это начальное значение остатка. Во всех предыдущих рассуждениях оно равнялось нулю (когда мы делим в столбик, предполагается, что слева от старшей цифры делимого записаны нули). Но обычно выбирают CRCINIT=0xFFFF FFFF, чтобы файлы разной длины, состоящие из нулевых байтов, имели разный CRC.
Как выбрать полином? Лучше предоставить этот выбор математикам, то есть взять один из широко известных полиномов, которые хорошо проверены и уже много лет используются другими программистами. Полином в нашей программе будет задаваться константой CRCPOLY.
Часто используется CRC-32 (32-битный алгоритм) c параметрами CRCINIT=0xFFFF FFFF, CRCPOLY=0xEDB88320. Именно этот алгоритм считает CRC в ZIP, RAR, WinHEX и во многих других программах. Этот алгоритм «перевернутый», то есть рассчитан на обработку битов в обратном порядке. По историческим причинам «перевернутые» алгоритмы сейчас встречаются чаще, чем обычные. Реализовать их можно двумя способами. Во-первых, можно переворачивать байт при каждом проходе цикла (это медленно и криво). Другой способ намного лучше. Давай делать все наоборот: выделять младший байт, а не старший, сдвигать на 8 разрядов вправо, а не влево. И перевернем сам полином, то есть запишем его биты в обратном порядке. В результате получится, что мы перевернули все, кроме значений байтов из файла. Образно можно сказать так: вместо того чтобы встать на голову самому, ты переворачиваешь вверх ногами весь остальной мир:
while(bufflen--)
crc = t[(crc ^ *buff++) & 0xFF] ^ (crc >> 8);
Такой код будет давать перевернутый CRC, и именно его ты скорее всего найдешь на сайтах для программистов и в различных FAQ по CRC. Еще раз повторюсь, что именно так считают CRC большинство программ.
Из-за путаницы с перевернутыми алгоритмами можно найти описание алгоритма с полиномом 0x04C11DB7 и другого алгоритма с полиномом 0xEDB88320. На самом деле это одно и то же, только авторы первого алгоритма переворачивали байты при каждом проходе цикла, а во втором алгоритме переделали сдвиг (crc << 8) в (crc >> 8), выделили младший байт вместо старшего и записали задом наперед полином:
EDB88320 = 11101101101110001000001100100000
04C11DB7 = 00000100110000010001110110110111
После вычисления CRC32 его обычно инвертируют (заменяют единицы нулями, а нули единицами). Это записывается либо как crc ^= 0xFFFF FFFF, либо crc = ~crc. Второй вариант быстрее и короче, поэтому мы будем пользоваться им.
Ищем оптимальный алгоритм
Табличная реализация CRC совсем непохожа на деление в полиномиальной арифметике. Еще более забавные вещи начнутся, когда мы будем оптимизировать этот алгоритм. Массив t[], конечно, можно рассчитывать заранее и записывать в константы, как показано выше. Но есть более оптимальный путь — генерировать этот массив при запуске программы. На это уходят буквально доли секунды, а программа становится на килобайт (256 элементов умножить на 4 байт) короче:
static unsigned long t[256]; // Таблица для подсчета CRC
void CRCInit()
{
for (int i = 0; i < 0xFF; i++) // Для каждого элемента T
{
t[i]=i;
for (int j = 8; j > 0; j--) // Для каждого бита
if(t[i] & 1) // Если младший бит
t[i] = (t[i]>>1) ^ CRCPOLY;
else
t[i] >>= 1;
}
}
Особых пояснений этот алгоритм не требует, потому что он делает то же, что мы делали вручную, когда рассчитывали таблицу t[]: проходит по всем битам abcdefhi, и если бит равен единице, XOR'ит следующие биты с полиномом. Длина байта здесь равна 8 символам, а полином 32-битный. Алгоритм перевернутый. В «прямом» алгоритме будет отличаться только вложенный цикл:
t[i] = i << 24;
for (int j = 8; j > 0; j--) // Для каждого бита
if(t[i] & 0x80000000) // Если старший бит
t[i] = (t[i]<<1) ^ CRCPOLY;
else
t[i] <<= 1;
Оба алгоритма можно очень хорошо разогнать, если развернуть вложенный цикл и убрать условие. Я напишу «турбореактивную» версию перевернутого алгоритма, так как почти всегда ты будешь пользоваться именно им:
for (int i = 0; i <= 0xFF; i++)
{ unsigned long x=i;
// Если младший бит установлен, то
// -(x & 1) равно -1, если не установлен, нулю.
// Соответственно, когда он установлен,
// x = (x >> 1) ^ CRCPOLY, иначе
// x = (x >> 1) ^ 0 = x >> 1;
x = (x>>1) ^ (CRCPOLY & (-(signed long)(x & 1)));
x = (x>>1) ^ (CRCPOLY & (-(signed long)(x & 1)));
x = (x>>1) ^ (CRCPOLY & (-(signed long)(x & 1)));
x = (x>>1) ^ (CRCPOLY & (-(signed long)(x & 1)));
x = (x>>1) ^ (CRCPOLY & (-(signed long)(x & 1)));
x = (x>>1) ^ (CRCPOLY & (-(signed long)(x & 1)));
x = (x>>1) ^ (CRCPOLY & (-(signed long)(x & 1)));
x = (x>>1) ^ (CRCPOLY & (-(signed long)(x & 1)));
t[i] = x;
}
Эта программа выполняется на Duron-800 за 12 микросекунд, тогда как исходная версия — за 35 мксек. Ускорение просто невероятное, но толку от него немного, потому что инициализация таблицы занимает очень небольшую часть от общего времени работы алгоритма. Проще говоря, 12 микросекунд не отличишь на глаз от тридцати пяти (одна микросекунда — миллионная доля секунды). Затем я попробовал частично развернуть цикл подсчета CRC:
crc = CRCINIT;
bufflen /= 4; // bufflen должно быть кратно 4. Для хвостов
while(bufflen--) // следует использовать обычный алгоритм
{ x = *(long*)buff;
crc = t[(crc ^ x) & 0xFF] ^ (crc >> 8);
crc = t[(crc ^ x >> 8) & 0xFF] ^ (crc >> 8);
crc = t[(crc ^ x >> 16) & 0xFF] ^ (crc >> 8);
crc = t[(crc ^ x >> 24) & 0xFF] ^ (crc >> 8);
buff += 4;
}
crc = ~crc; // Инвертировать CRC
Это дает некоторый прирост скорости, но этот прирост невелик (не больше 5%). Так или иначе, конечная версия моей программы для подсчета CRC использует именно этот алгоритм и динамическую генерацию таблицы t[].
Как защитить свою программу от взлома
Ты можешь подсчитать CRC своего exe'шника, сравнить его с CRC, хранящимся в том же exe'шнике, и убедиться, что программа не была повреждена / взломана. Идея не нова, и она используется, в частности, в Total Commander (на проверке CRC прокололись многие крэкеры, написавшие патчи к TC). В exe'шниках DOS и Windows уже предусмотрены поля для контрольной суммы (16-битной по смещению 0x12..0x13 от начала файла и 32-битной по смещению 0x8-0xB от начала PE-заголовка). Самым простым вариантом будет использовать их. В компоновщике Link для MSVC++ предусмотрена опция /RELEASE, которая заставляет пересчитывать контрольную сумму после каждой компиляции программы. А Win32 API имеет функцию MapFileAndCheckSum для проверки этой суммы. Если нужно защитить программу от повреждений и вирусов, это действительно лучший вариант — всего-то пара строчек кода. Но такая «защита» не остановит ни одного крэкера. Придется придумать что-нибудь получше, а именно считать CRC самостоятельно. В заголовке exe'шника есть куча неиспользуемых и зарезервированных полей, в которые можно записать CRC. Я выбрал поле 0x2C из заголовка MS-DOS. Чтобы не получилось так, что CRC файла изменился из-за того, что мы вписали в этот же файл CRC, будем считать CRC начиная со смещения 0x40 (пропускаем заголовок MS-DOS). Получаем имя данного exe'шника функцией GetModuleFileName, открываем его, подсчитываем CRC и сравниваем с хранящимся в файле:
#define QUANT 1024 // Читать по 1024 байт файла
#define CRCPOLY 0xEDB88320
#define CRCINIT 0xFFFFFFFF
int CRCCheckThisExe()
{ // Проверить целостность exe (возвращает 1,
// если программа была изменена)
char FileName[MAX_PATH]; HANDLE hFile; DWORD bytesread;
char data[QUANT], *p; unsigned long crc, x;
GetModuleFileName(NULL, FileName, MAX_PATH);
hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if(hFile == INVALID_HANDLE_VALUE)
return 0;
// Читать со смещения 40
SetFilePointer(hFile, 0x40, NULL, FILE_BEGIN);
CRCInit(); // Создать массив t
crc = CRCINIT;
for(;;) // Подсчет CRC
{
ReadFile(hFile, data, QUANT, &bytesread, NULL);
p = data;
if(bytesread != QUANT) // Досчитываем остаток
{
while(bytesread--)
crc = t[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
break; // Выйти, когда файл закончился
}
// Так как bytesread == QUANT, bytesread кратно 4
bytesread /= 4;
while(bytesread--)
{ x = *(long*)p;
crc = t[(crc ^ x) & 0xFF] ^ (crc >> 8);
crc = t[(crc ^ x >> 8) & 0xFF] ^ (crc >> 8);
crc = t[(crc ^ x >> 16) & 0xFF] ^ (crc >> 8);
crc = t[(crc ^ x >> 24) & 0xFF] ^ (crc >> 8);
p += 4;
}
}
// Считать CRC из файла и сравнить с рассчитанным
SetFilePointer(hFile, 0x2C, NULL, FILE_BEGIN);
x = 0;
ReadFile(hFile, &x, sizeof(x), &bytesread, NULL);
CloseHanlde(hFile);
return x != crc;
}
Как показывает опыт, на скорость расчета CRC сильно влияет размер считываемого куска QUANT. Я получал хорошие результаты при QUANT = 1024 и QUANT = 2048. Ты можешь подобрать другие значения. По идее, они должны быть кратны размеру сектора диска (512 байт), но можно еще попробовать учесть, что мы считываем файл не с начала, а со смещения 0x40.
Считает и записывает CRC в exe'шник отдельная программа, CRCMaker. Ее можно прописать в свойства проекта (Post-build step), чтобы после каждой компиляции CRC пересчитывался автоматически. Чтобы усилить защиту, нужно «размазать» вычисление CRC по всей твоей программе. При запуске программы вызови GetModuleFileName и сохрани путь в глобальной переменной. Затем где-то в другом месте открой файл и начни подсчет CRC. Хороших результатов можно добиться, если подсчитывать CRC при простое программы (когда пользователь не работает с клавиатурой и мышью или когда переключился в другую программу). Два значения CRC — рассчитанное и взятое из файла — нужно записать в глобальные переменные и в нескольких точках программы сверять между собой. Лучше не выдавать никаких предупреждающих сообщений, а сразу выходить из программы. Все это более или менее обезопасит твою прогу от цепких лап любителей SoftIce.
Что еще почитать на тему CRC
Ross Williams. A painless guide to CRC error detection algorithms. — ftp://www.internode.net.au/clients/rocksoft/papers/crc_v3.txt (русский перевод см. http://www.rsdn.ru/article/files/classes/SelfCheck/crcguide.pdf). Очень подробное описание принципа подсчета CRC, но не слишком оптимальные алгоритмы. Можно почитать, если ты хочешь разобраться в математических подробностях.
FAQ по CRC. — http://faqs.org.ru/progr/common/crc_faq.rar. Самые короткие и вразумительные алгоритмы вычисления CRC из всех, что я встречал. На Си, Паскале, ассемблере. Там же — как взломать CRC (подобрать сообщение под заданный CRC).
Алексей Кирюшкин. Защита исполняемых файлов от искажений. — http://www.rsdn.ru/article/files/classes/selfcheck.xml. Автор предлагает хранить CRC в разделе данных и находить его по некоторой сигнатуре. Неплохой способ, хотя он немного сложнее, чем хранение CRC в заголовках exe'шника.
Скачать пример программы можно отсюда. Программа XakepCRC проверяет CRC файлов, но она также защищает себя от взлома с помощью CRC. Заголовочные файлы из каталога CRClib ты можешь использовать в своих программах.
взято с
Всем нам свойственно ошибаться, но иногда мы вовремя обнаруживаем свои ошибки. Пусть ты не сможешь умножить в уме 790 г. колбасы на 134 рубля 50 копеек, но если продавщица говорит: «115 рублей, молодой человек», то ты можешь прикинуть (около 120 рублей умножить на 1/4 килограмма будет 30 рублей, 130 минус 30 — сто рублей) и понять, что эта добрая тетя пытается тебя обдурить, присвоив себе десятку. Компьютеры тоже ошибаются. Сбоит память, на винчестерах появляются бэдблоки, мыши в колодцах грызут телефонные кабели. Так в информацию вносятся ошибки, которые нужно обнаруживать и по возможности исправлять.
Чтобы найти ошибку, к сообщению добавляют контрольную сумму (checksum). В самом простом случае это сумма всех байтов сообщения. Например:
Сообщение: 12 34 56
Контрольная сумма: 12+34+56=102
После передачи в это сообщение могут быть внесены помехи, например, так:
Искаженное сообщение: 12 36 56, контрольная сумма 102
Если теперь сложить байты сообщения, результат не совпадет с контрольной суммой. Так программа может сделать вывод, что данные были повреждены, и принять меры (например, еще раз запросить пакет TCP/IP или выдать сообщение, что архив поврежден).
CRC, или циклический избыточный код, — это улучшенный (и усложненный) вариант контрольной суммы. В этой статье будет рассказано об алгоритме CRC32, который применяется в протоколе TCP/IP, архиваторах Zip и Rar. Затем я расскажу тебе, как защитить свою программу от модификаций, проверяя ее CRC.
Чем плоха контрольная сумма
Во-первых, если просто складывать байты, то старшие биты будут изменяться реже, чем младшие. То есть, если мы складываем
12 34 56, контрольная сумма 102
12 34 56 23, контрольная сумма 125
12 34 56 23 45, контрольная сумма 170
результат останется в пределах двух сотен. Если контрольная сумма записана в 32-разрядное или 64-разрядное слово, старшие байты будут содержать нули. Это не есть хорошо, так как все биты контрольной суммы должны быть равноценными.
Во-вторых, сообщения с переставленными байтами будут иметь одну и ту же сумму:
12 34 56, контрольная сумма 102
56 12 34, контрольная сумма 102
Несмотря на все эти недостатки, разные варианты контрольной суммы используются довольно широко, например, в штрих-кодах (barcode). У меня в руках банка консервированной кукурузы, на которой написан такой штрих-код:
5 998483 710125
Это код EAN-13 (тринадцать цифр). Правило для его проверки такое: сложи цифры на четных позициях, умножь сумму на три и добавь цифры на нечетных позициях. Должно получиться число, которое делится на десять:
9 + 8 + 8+ 7 + 0 + 2 = 34
5 + 9 + 4 + 3 + 1 + 1 + 5 = 28
34 * 3 + 28 = 130, делится на 10
А чтобы это условие выполнялось, последнюю цифру, 5, делают контрольной суммой. То есть складывают по этим правилам все остальные цифры, а последнюю цифру вычисляют как 10 минус последняя цифра суммы. Контрольная сумма нужна затем, чтобы сканер в супермаркете не считывал неправильный код если упаковка грязная или продавщица случайно закрыла код рукой. Если интересно, можешь проверить по этому правилу штрих-коды на любых упаковках пищевых продуктов (но не книг — у них другой код, ISBN).
Есть очень простой, короткий и быстрый (примерно в 10 раз быстрее CRC) способ подсчета контрольной суммы. Берем по 4 байта из файла, и делаем с ними логическую операцию XOR. То, что получится в результате, — контрольная сумма.
unsigned long XORCount(void* data, size_t bytesread)
// data — сообщение, size_t — его длина
{
*(long*)(data + bytesread) = 0; // Подписать 4 нулевых байта
bytesread /= sizeof(long);
while(bytesread--)
sum ^= *(long*)data, data+=sizeof(long);
// Первые 4 байта XOR вторые 4 байта XOR третьи...
return sum;
}
В этой контрольной сумме все байты используются полностью, среди них нет более значимых или менее значимых. Теоретическая вероятность того, что контрольная сумма окажется правильной для испорченного файла — 1 шанс на 2 ^ 32. Но операция XOR обладает таким свойством, что A XOR A = 0. Поэтому для сообщений
12 34 A6 7B 91 92 93 94 91 92 93 94
12 34 A6 7B 12 34 56 78 12 34 56 78
12 34 A6 7B 00 00 00 00 00 00 00 00
контрольная сумма будет одинаковой, как и для любых других, содержащих четное число одинаковых четверок байт (или же просто 8, 16, 24 или 32 одинаковых байт). И если вместо NOP'ов записать в исполнимый файл нули или любые другие байты (но число байт обязательно кратно 8), то программа этого не обнаружит. Все это плохо, но не смертельно, поэтому этим алгоритмом вполне можно пользоваться, если нужна высокая скорость проверки.
Что такое CRC
Запомни простую формулу: CRC = сообщение % полином
То есть все сообщение (файл, архив) делим по модулю на некоторую константу (ее называют полиномом). Остаток от деления и есть CRC. О том, как весь файл можно разделить на число, я скажу чуть ниже, а пока — урок арифметики. Но не обычной арифметики, а полиномиальной. Что же это за арифметика такая? Это двоичная арифметика без переносов и заемов. Если сложить 1+1 в обычной двоичной арифметике, получится 10 (переносим единицу). Если вычесть 10–1, получится 1 (занимаем единицу).
В полиномиальной арифметике:
0+0 = 0 0–0=0
0+1 = 1 0–1=1 (не занимаем!)
1+0 = 1 1–0=1
1+1 = 0 (не переносим!) 1–1=0
Видно, что сложение в полиномиальной арифметике — это то же, что и вычитание. И если тебя мучили таблицами истинности на уроках информатики, ты сразу вспомнишь, что это операция XOR. В учебниках по дискретной математике ее обозначают кружком с косым крестиком внутри. Я буду обозначать эту операцию крышкой ^, как в Си. В полиномиальной арифметике 100 плюс 110 равно 10, но 100 минус 110 тоже равно 10. Нет ни знака, ни определенного порядка битов. Все биты равнозначны, и это очень важное свойство для CRC. Если переставить несколько битов в обоих слагаемых, те же биты будут переставлены в сумме:
1010 ^ 1100=01 10, поменяем местами первые два и последние два бита:
1010 ^ 0011=10 01 (а теперь сравни 19+34=53 и 91+43=134, а не 35).
Биты можно представить как коэффициенты многочлена (полинома). Поэтому арифметику называют полиномиальной, а делитель в алгоритмах CRC — полиномом. В общем, все это математические заморочки, но знать будет не лишнее.
Умножение в полиномиальной арифметике нам не понадобится, а вот о делении нужно сказать подробнее. Делим, как во втором классе, уголком, но вместо вычитания используем операцию XOR:
Сообщение: 1101010
Полином: 101
1101010
^101
====
111010
^101
===
10010
^101
===== получили 0, сдвигаемся на 2 бита
110
^101
===
11
Готово! CRC = 11
Именно так считают CRC. Заметь, что в каждом столбике мы вычитаем старшие биты 1–1=0. В следующих битах могут быть любые числа. Один раз мы получили ноль в старшем бите, и нам пришлось сдвинуться вправо на 2 бита, а не на один. Итак, можно записать такой алгоритм (это не рабочий код, он только показывает алгоритм):
// data - сообщение (битовая строка), POLY - полином
while(length(data) > length(POLY)){
r = TOPBIT(data); // Выделяем старший бит data
data <<= 1; // И выкидываем его из основного числа data
if(r)
data ^= POLY;
}
В столбиках мы сдвигали полином 101 вправо, каждый раз вычитая его из сообщения. В этом алгоритме полином остается на месте, но мы «двигаем» делимое влево. Если старший бит r равен нулю, мы сдвигаемся еще на один бит, не вычитая POLY. Константа POLY равна полиному без старшей единицы, то есть 01. Обрати на это внимание: первую единицу писать незачем, так как двоичное число всегда начинается с единицы. Как работает этот код, легче понять на примере. Возьмем то же сообщение 1101010 и тот же полином 101 (сравни со столбиком выше):
Шаг 1. r = 1 // Отделили первый бит
data = 101010 // r=1, поэтому делаем XOR
^01
======
111010
Шаг 2. r = 1
data = 11010
^01
=====
10010
Шаг 3. r = 1
data = 0010
^01
====
0110
Шаг 4. r = 0 // XOR не делаем
data = 110
Шаг 5. r = 1
data = 10
^01
==
11
Итак, алгоритм в целом понятен: делим нацело data на POLY, получаем crc. И при делении 0–1=1, 1+1=0 без переноса.
Сложность состоит в том, что сообщение может весить пару мегабайт. Как же разделить его на полином? Заметь, что при каждом проходе цикла у нас меняются только 2 первых бита data. Значит, можно проходить по всему сообщению, читая в каждый момент времени небольшую порцию данных (в нашем случае — первые два бита).
Как работает табличная реализация
Но у этого алгоритма есть еще один недостаток: он обрабатывает по одному биту сообщения. Например, для мегабайтного файла он сделает 8 миллионов проходов цикла, и каждый раз будет извлекать отдельные биты. Согласись, это никуда не годится! Есть общепринятый трюк, который ускоряет подсчет CRC чуть ли не в десятки раз. Идея такова: будем обрабатывать по байту за один проход цикла. Когда мы делим байт на полином, у нас в остатке получается некоторое число, причем оно не зависит от других байтов сообщения. Вот это число мы можем хранить в таблице для каждого делимого байта. Имея такую таблицу, будем получать CRC для каждого байта за один проход. Сейчас я расскажу, как построить такую таблицу и что конкретно в ней будет находиться. Чтобы не маяться с длинными таблицами, возьмем байт, равный 3 битам, и короткий полином 111. Пусть сообщение состоит из 5 бит, назовем их abcde. Пройдем наш старый алгоритм по шагам:
Шаг 1. if(a) // Запись условная, это не рабочий код
bc ^= 11;
Шаг 2. if(b)
cd ^= 11; // Полином 110 без первой единицы
Шаг 3. if(c)
de ^= 11;
Когда мы подсчитали bcd и перешли на второй шаг, бит a уже не нужен, и на дальнейшие подсчеты он никак не влияет. Когда дошли до последнего шага, оказались ненужными биты a и b. А после третьего шага сыграл свою роль бит c, который теперь сходит со сцены. То, что поменялись биты abc, уже не важно, потому что на четвертом, пятом и так далее шаге они не будут использоваться. Но на этих трех шагах как-то изменились биты de. И изменились они в зависимости от битов abc. Давай переберем все значения abc, начиная с 000 и до 111.
000 (a=0, b=0, c=0) — ни одно из условий не выполняется, поэтому биты def не изменились.
001 (a=0, b=0, c=1) — условие if(c) выполнилось. Я запишу это так:
abc
001def
^11
010 — условие if(b) выполнилось, но после добавления единицы к c выполнилось также if(c). Запишем под чертой результат операции XOR над двумя соответствующими числами в битах de:
abc
010de
^11
^11
==
01
011 — выполнилось условие if(b), но бит c был при этом обнулен, поэтому if(c) не сработало:
abc
011de
^11
==
10
100 — сработало условие if(a), которое вызвало if(b). В результате бит d будет подвергнут операции XOR с единицей (далее будем говорить проще, XOR'ится с единицей):
abc
100de
^11
^11
==
10
101 — аналогично, но бит c обнулился, и результат — нулевой:
abc
101de
^11
==
00
То же самое ты можешь написать для 110 и 111. Довольно муторное дело, но в нем нет ничего сложного. Сделаем массив T с индексами от 000 до 111, в котором будем хранить результаты наших вычислений:
индекс значение
000 00
001 11
010 01
011 10
100 10
101 00
110 11
111 00
Теперь рассчитать CRC можно, что называется, в два притопа, три прихлопа. Смотри:
de ^= t[abc]; // Код условный, не рабочий.
gh ^= t[def]; // t — массив, abc def ghi — сообщение
crc = ghi;
Если вынести текущий изменяемый байт в отдельную переменную, расширить байт до 8 бит и взять 32-битный полином, получим почти готовый код для расчета CRC:
static const long t[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd,
// И так далее, все 256 элементов смотри в коде к статье
}
unsigned long CRCCount(char* buff, size_t bufflen)
{
unsigned long crc = CRCINIT;
while(bufflen--)
crc = t[crc >> 24] ^ ((crc << 8) | *buff++));
сrс = t[сrс >> 24] ^ (сrс << 8); // Подчищаем «хвосты»
сrс = t[сrс >> 24] ^ (сrс << 8);
сrс = t[сrс >> 24] ^ (сrс << 8);
сrс = t[сrс >> 24] ^ (сrс << 8);
return ~crc; // Вернуть инвертированный crc - см. ниже
}
Здесь на каждом шаге мы выбираем элемент из таблицы T по значению старшего байта (crc >> 24) и XOR'им его с очередным байтом. Этот байт у нас каждый раз сдвигается влево, а на его место приходит новый из сообщения (*buff++). Все эти сдвиги нужны для того, чтобы использовать длинный 32-битный полином, который XOR'ится с четырьмя соседними байтами сразу. В последних четырех строчках мы проводим через серию XOR'ов и сдвигаем влево оставшийся в младшем байте crc последний байт файла. По правилам вычисления CRC все символы должны «уйти» влево, за пределы переменной. На этом заканчивается вычисление CRC — остатка от деления сообщения на полином в полиномиальной арифметике. Итак, в таблице хранятся сдвинутые и проXORенные значения полинома. Конкретные сдвиги зависят от индекса массива, который есть предыдущий байт (abc или crc >> 24), а значение следующего байта (def или (crc << 8) | *buff++) XOR'ится с элементом массива t[abc].
Где кончается теория и начинается практика
Что же, простая и быстрая реализация алгоритма для расчета CRC у нас уже есть. Уточним некоторые детали: как выбрать полином и что такое перевернутые алгоритмы. Начнем с того, что приведенный выше алгоритм практически всегда преобразуют по некоторым математическим формулам и переписывают так:
crc = CRCINIT;
while (bufflen--)
crc = t[(crc >> 24 ^ *buff++) & 0xFF] ^ (crc << 8);
Это позволяет избавиться от четырех последних строчек, хотя не делает алгоритм ни проще, ни быстрее. Кстати, скобки вокруг (crc << 8) необязательны, потому что операция сдвига в Си имеет больший приоритет, чем XOR. Но для удобочитаемости скобки обычно ставят.
CRCINIT — это начальное значение остатка. Во всех предыдущих рассуждениях оно равнялось нулю (когда мы делим в столбик, предполагается, что слева от старшей цифры делимого записаны нули). Но обычно выбирают CRCINIT=0xFFFF FFFF, чтобы файлы разной длины, состоящие из нулевых байтов, имели разный CRC.
Как выбрать полином? Лучше предоставить этот выбор математикам, то есть взять один из широко известных полиномов, которые хорошо проверены и уже много лет используются другими программистами. Полином в нашей программе будет задаваться константой CRCPOLY.
Часто используется CRC-32 (32-битный алгоритм) c параметрами CRCINIT=0xFFFF FFFF, CRCPOLY=0xEDB88320. Именно этот алгоритм считает CRC в ZIP, RAR, WinHEX и во многих других программах. Этот алгоритм «перевернутый», то есть рассчитан на обработку битов в обратном порядке. По историческим причинам «перевернутые» алгоритмы сейчас встречаются чаще, чем обычные. Реализовать их можно двумя способами. Во-первых, можно переворачивать байт при каждом проходе цикла (это медленно и криво). Другой способ намного лучше. Давай делать все наоборот: выделять младший байт, а не старший, сдвигать на 8 разрядов вправо, а не влево. И перевернем сам полином, то есть запишем его биты в обратном порядке. В результате получится, что мы перевернули все, кроме значений байтов из файла. Образно можно сказать так: вместо того чтобы встать на голову самому, ты переворачиваешь вверх ногами весь остальной мир:
while(bufflen--)
crc = t[(crc ^ *buff++) & 0xFF] ^ (crc >> 8);
Такой код будет давать перевернутый CRC, и именно его ты скорее всего найдешь на сайтах для программистов и в различных FAQ по CRC. Еще раз повторюсь, что именно так считают CRC большинство программ.
Из-за путаницы с перевернутыми алгоритмами можно найти описание алгоритма с полиномом 0x04C11DB7 и другого алгоритма с полиномом 0xEDB88320. На самом деле это одно и то же, только авторы первого алгоритма переворачивали байты при каждом проходе цикла, а во втором алгоритме переделали сдвиг (crc << 8) в (crc >> 8), выделили младший байт вместо старшего и записали задом наперед полином:
EDB88320 = 11101101101110001000001100100000
04C11DB7 = 00000100110000010001110110110111
После вычисления CRC32 его обычно инвертируют (заменяют единицы нулями, а нули единицами). Это записывается либо как crc ^= 0xFFFF FFFF, либо crc = ~crc. Второй вариант быстрее и короче, поэтому мы будем пользоваться им.
Ищем оптимальный алгоритм
Табличная реализация CRC совсем непохожа на деление в полиномиальной арифметике. Еще более забавные вещи начнутся, когда мы будем оптимизировать этот алгоритм. Массив t[], конечно, можно рассчитывать заранее и записывать в константы, как показано выше. Но есть более оптимальный путь — генерировать этот массив при запуске программы. На это уходят буквально доли секунды, а программа становится на килобайт (256 элементов умножить на 4 байт) короче:
static unsigned long t[256]; // Таблица для подсчета CRC
void CRCInit()
{
for (int i = 0; i < 0xFF; i++) // Для каждого элемента T
{
t[i]=i;
for (int j = 8; j > 0; j--) // Для каждого бита
if(t[i] & 1) // Если младший бит
t[i] = (t[i]>>1) ^ CRCPOLY;
else
t[i] >>= 1;
}
}
Особых пояснений этот алгоритм не требует, потому что он делает то же, что мы делали вручную, когда рассчитывали таблицу t[]: проходит по всем битам abcdefhi, и если бит равен единице, XOR'ит следующие биты с полиномом. Длина байта здесь равна 8 символам, а полином 32-битный. Алгоритм перевернутый. В «прямом» алгоритме будет отличаться только вложенный цикл:
t[i] = i << 24;
for (int j = 8; j > 0; j--) // Для каждого бита
if(t[i] & 0x80000000) // Если старший бит
t[i] = (t[i]<<1) ^ CRCPOLY;
else
t[i] <<= 1;
Оба алгоритма можно очень хорошо разогнать, если развернуть вложенный цикл и убрать условие. Я напишу «турбореактивную» версию перевернутого алгоритма, так как почти всегда ты будешь пользоваться именно им:
for (int i = 0; i <= 0xFF; i++)
{ unsigned long x=i;
// Если младший бит установлен, то
// -(x & 1) равно -1, если не установлен, нулю.
// Соответственно, когда он установлен,
// x = (x >> 1) ^ CRCPOLY, иначе
// x = (x >> 1) ^ 0 = x >> 1;
x = (x>>1) ^ (CRCPOLY & (-(signed long)(x & 1)));
x = (x>>1) ^ (CRCPOLY & (-(signed long)(x & 1)));
x = (x>>1) ^ (CRCPOLY & (-(signed long)(x & 1)));
x = (x>>1) ^ (CRCPOLY & (-(signed long)(x & 1)));
x = (x>>1) ^ (CRCPOLY & (-(signed long)(x & 1)));
x = (x>>1) ^ (CRCPOLY & (-(signed long)(x & 1)));
x = (x>>1) ^ (CRCPOLY & (-(signed long)(x & 1)));
x = (x>>1) ^ (CRCPOLY & (-(signed long)(x & 1)));
t[i] = x;
}
Эта программа выполняется на Duron-800 за 12 микросекунд, тогда как исходная версия — за 35 мксек. Ускорение просто невероятное, но толку от него немного, потому что инициализация таблицы занимает очень небольшую часть от общего времени работы алгоритма. Проще говоря, 12 микросекунд не отличишь на глаз от тридцати пяти (одна микросекунда — миллионная доля секунды). Затем я попробовал частично развернуть цикл подсчета CRC:
crc = CRCINIT;
bufflen /= 4; // bufflen должно быть кратно 4. Для хвостов
while(bufflen--) // следует использовать обычный алгоритм
{ x = *(long*)buff;
crc = t[(crc ^ x) & 0xFF] ^ (crc >> 8);
crc = t[(crc ^ x >> 8) & 0xFF] ^ (crc >> 8);
crc = t[(crc ^ x >> 16) & 0xFF] ^ (crc >> 8);
crc = t[(crc ^ x >> 24) & 0xFF] ^ (crc >> 8);
buff += 4;
}
crc = ~crc; // Инвертировать CRC
Это дает некоторый прирост скорости, но этот прирост невелик (не больше 5%). Так или иначе, конечная версия моей программы для подсчета CRC использует именно этот алгоритм и динамическую генерацию таблицы t[].
Как защитить свою программу от взлома
Ты можешь подсчитать CRC своего exe'шника, сравнить его с CRC, хранящимся в том же exe'шнике, и убедиться, что программа не была повреждена / взломана. Идея не нова, и она используется, в частности, в Total Commander (на проверке CRC прокололись многие крэкеры, написавшие патчи к TC). В exe'шниках DOS и Windows уже предусмотрены поля для контрольной суммы (16-битной по смещению 0x12..0x13 от начала файла и 32-битной по смещению 0x8-0xB от начала PE-заголовка). Самым простым вариантом будет использовать их. В компоновщике Link для MSVC++ предусмотрена опция /RELEASE, которая заставляет пересчитывать контрольную сумму после каждой компиляции программы. А Win32 API имеет функцию MapFileAndCheckSum для проверки этой суммы. Если нужно защитить программу от повреждений и вирусов, это действительно лучший вариант — всего-то пара строчек кода. Но такая «защита» не остановит ни одного крэкера. Придется придумать что-нибудь получше, а именно считать CRC самостоятельно. В заголовке exe'шника есть куча неиспользуемых и зарезервированных полей, в которые можно записать CRC. Я выбрал поле 0x2C из заголовка MS-DOS. Чтобы не получилось так, что CRC файла изменился из-за того, что мы вписали в этот же файл CRC, будем считать CRC начиная со смещения 0x40 (пропускаем заголовок MS-DOS). Получаем имя данного exe'шника функцией GetModuleFileName, открываем его, подсчитываем CRC и сравниваем с хранящимся в файле:
#define QUANT 1024 // Читать по 1024 байт файла
#define CRCPOLY 0xEDB88320
#define CRCINIT 0xFFFFFFFF
int CRCCheckThisExe()
{ // Проверить целостность exe (возвращает 1,
// если программа была изменена)
char FileName[MAX_PATH]; HANDLE hFile; DWORD bytesread;
char data[QUANT], *p; unsigned long crc, x;
GetModuleFileName(NULL, FileName, MAX_PATH);
hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if(hFile == INVALID_HANDLE_VALUE)
return 0;
// Читать со смещения 40
SetFilePointer(hFile, 0x40, NULL, FILE_BEGIN);
CRCInit(); // Создать массив t
crc = CRCINIT;
for(;;) // Подсчет CRC
{
ReadFile(hFile, data, QUANT, &bytesread, NULL);
p = data;
if(bytesread != QUANT) // Досчитываем остаток
{
while(bytesread--)
crc = t[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
break; // Выйти, когда файл закончился
}
// Так как bytesread == QUANT, bytesread кратно 4
bytesread /= 4;
while(bytesread--)
{ x = *(long*)p;
crc = t[(crc ^ x) & 0xFF] ^ (crc >> 8);
crc = t[(crc ^ x >> 8) & 0xFF] ^ (crc >> 8);
crc = t[(crc ^ x >> 16) & 0xFF] ^ (crc >> 8);
crc = t[(crc ^ x >> 24) & 0xFF] ^ (crc >> 8);
p += 4;
}
}
// Считать CRC из файла и сравнить с рассчитанным
SetFilePointer(hFile, 0x2C, NULL, FILE_BEGIN);
x = 0;
ReadFile(hFile, &x, sizeof(x), &bytesread, NULL);
CloseHanlde(hFile);
return x != crc;
}
Как показывает опыт, на скорость расчета CRC сильно влияет размер считываемого куска QUANT. Я получал хорошие результаты при QUANT = 1024 и QUANT = 2048. Ты можешь подобрать другие значения. По идее, они должны быть кратны размеру сектора диска (512 байт), но можно еще попробовать учесть, что мы считываем файл не с начала, а со смещения 0x40.
Считает и записывает CRC в exe'шник отдельная программа, CRCMaker. Ее можно прописать в свойства проекта (Post-build step), чтобы после каждой компиляции CRC пересчитывался автоматически. Чтобы усилить защиту, нужно «размазать» вычисление CRC по всей твоей программе. При запуске программы вызови GetModuleFileName и сохрани путь в глобальной переменной. Затем где-то в другом месте открой файл и начни подсчет CRC. Хороших результатов можно добиться, если подсчитывать CRC при простое программы (когда пользователь не работает с клавиатурой и мышью или когда переключился в другую программу). Два значения CRC — рассчитанное и взятое из файла — нужно записать в глобальные переменные и в нескольких точках программы сверять между собой. Лучше не выдавать никаких предупреждающих сообщений, а сразу выходить из программы. Все это более или менее обезопасит твою прогу от цепких лап любителей SoftIce.
Что еще почитать на тему CRC
Ross Williams. A painless guide to CRC error detection algorithms. — ftp://www.internode.net.au/clients/rocksoft/papers/crc_v3.txt (русский перевод см. http://www.rsdn.ru/article/files/classes/SelfCheck/crcguide.pdf). Очень подробное описание принципа подсчета CRC, но не слишком оптимальные алгоритмы. Можно почитать, если ты хочешь разобраться в математических подробностях.
FAQ по CRC. — http://faqs.org.ru/progr/common/crc_faq.rar. Самые короткие и вразумительные алгоритмы вычисления CRC из всех, что я встречал. На Си, Паскале, ассемблере. Там же — как взломать CRC (подобрать сообщение под заданный CRC).
Алексей Кирюшкин. Защита исполняемых файлов от искажений. — http://www.rsdn.ru/article/files/classes/selfcheck.xml. Автор предлагает хранить CRC в разделе данных и находить его по некоторой сигнатуре. Неплохой способ, хотя он немного сложнее, чем хранение CRC в заголовках exe'шника.
Скачать пример программы можно отсюда. Программа XakepCRC проверяет CRC файлов, но она также защищает себя от взлома с помощью CRC. Заголовочные файлы из каталога CRClib ты можешь использовать в своих программах.
взято с
Tuesday, December 23, 2008
Monday, December 22, 2008
MasterPage в ASP 2008
Что бы долго не долбать себе мозги и листать интернет, не знаю по чему, но у меня пока разобрался ушло пол дня, делаем следующее, в студио создаем проект, далее добавляем новую страницу masterpage с именем что то типа RootMasterPage.Master с минимальным содержания, а дальше уже на вкус добавляем все что нужно:
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="RootMasterPage.master.cs" Inherits="SIP3.RootMasterPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>SIP</title>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
<style type="text/css">
.style2
{
color: #000066;
background-color: #66CCFF;
}
.style3
{
color: #000066;
}
.style4
{
background-color: #66CCFF;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<div>
<table border="0" cellpadding="0" cellspacing="0"
style="width: 100%; height: 100%; color: #99FF33; background-color: #66CCFF;">
<tr>
<td style="height: 7px">
<h2 style="text-align: center"><span class="style2">%u0426%u0435%u043D%u0442%u0440 %u043E%u0431%u0440%u0430%u0431%u043E%u0442%u043A%u0438 %u0418%u043D%u0444%u043E%u0440%u043C%u0430%u0446%u0438%u0438</span></h2>
<h2 style="text-align: center" class="style3"><span class="style4">SIP</span></h2>
</td>
</tr>
<tr>
<td>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1"
runat="server">
</asp:ContentPlaceHolder>
</td>
</tr>
</table>
</div>
</form>
</body>
</html>
Далее добавляем еще одну страницу мастер пейдж Node1MasterPage
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Node1MasterPage.master.cs" Inherits="SIP3.Node1MasterPage" MasterPageFile="~/RootMasterPage.Master" %>
<asp:Content ID="Content1"
ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<table border="0" cellpadding="0" cellspacing="0"
style="width: 100%; height: 100%; margin-bottom: 0px; color: #000066; ">
<tr>
<td style=" width:15%;height: 1000px; background-image: none; background-color:inherit; text-align:left; top:auto; "
>
<div>
<h2>
<a href="Default.aspx"><span class="style2">%u041E%u0441%u043D%u043E%u0432%u043D%u0430%u044F</span></a></h2>
<h3>
<a href="TypeCards.aspx"><span class="style2">%u0422%u0438%u043F%u044B %u043A%u0430%u0440%u0442%u043E%u0447%u0435%u043A</span></a></h3>
<h3>
<a href="TypeCards.aspx"><span class="style5">%u0422%u0438%u043F%u044B %u043F%u043E%u043A%u0443%u043F%u0430%u0442%u0435%u043B%u0435%u0439</span></a></h3>
<h3>
<a href="TypeCards.aspx"><span class="style5">%u0422%u0438%u043F%u044B %u0441%u043A%u0438%u0434%u043E%u043A</span></a></h3>
<h3>
<a href="TypeCards.aspx"><span class="style5">%u0422%u0438%u043F%u044B %u043B%u0438%u043C%u0438%u0442%u043E%u0432</span></a></h3>
<a href="Markets.aspx"><span class="style2">%u041C%u0430%u0440%u043A%u0435%u0442%u044B</span></a><br class="style2" />
<a href="Markets.aspx"><span class="style2">%u041F%u043E%u043A%u0443%u043F%u0430%u0442%u0435%u043B%u0438</span></a>
</div>
</td>
<td style="background-color: #FFFFFF" align="center">
<asp:ContentPlaceHolder ID="CPH2" runat="server">
</asp:ContentPlaceHolder>
</td>
</tr>
</table>
</asp:Content>
<asp:Content ID="Content2" runat="server" contentplaceholderid="head">
<style type="text/css">
.%u043D%u043E%u0432%u044B%u0439%u0421%u0442%u0438%u043B%u044C1
{
line-height: normal;
}
.style2
{
color: #FFFF66;
}
.style5
{
background-color: #66CCFF;
color: #000066;
}
</style>
</asp:Content>
В самом итоге меняем Default.aspx и ее внутренний текст:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="SIP3._Default" MasterPageFile="~/Node1MasterPage.Master" %>
<asp:Content ID="Content1" ContentPlaceHolderID="CPH2"
Runat="Server">
<h3>%u0414%u043E%u0431%u0440%u043E %u043F%u043E%u0436%u0430%u043B%u043E%u0432%u0430%u0442%u044C!</h3>
</asp:Content>
В итоге у нас получается, что создавая любую новую страницу, что бы она работала как и весь сайт с мастер пейджом, просто вставляем данные с default и дорабатываем до необходимости.
Основная работа с мастерпейдж состоит в ContentPlaceHolderID
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="RootMasterPage.master.cs" Inherits="SIP3.RootMasterPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>SIP</title>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
<style type="text/css">
.style2
{
color: #000066;
background-color: #66CCFF;
}
.style3
{
color: #000066;
}
.style4
{
background-color: #66CCFF;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<div>
<table border="0" cellpadding="0" cellspacing="0"
style="width: 100%; height: 100%; color: #99FF33; background-color: #66CCFF;">
<tr>
<td style="height: 7px">
<h2 style="text-align: center"><span class="style2">%u0426%u0435%u043D%u0442%u0440 %u043E%u0431%u0440%u0430%u0431%u043E%u0442%u043A%u0438 %u0418%u043D%u0444%u043E%u0440%u043C%u0430%u0446%u0438%u0438</span></h2>
<h2 style="text-align: center" class="style3"><span class="style4">SIP</span></h2>
</td>
</tr>
<tr>
<td>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1"
runat="server">
</asp:ContentPlaceHolder>
</td>
</tr>
</table>
</div>
</form>
</body>
</html>
Далее добавляем еще одну страницу мастер пейдж Node1MasterPage
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Node1MasterPage.master.cs" Inherits="SIP3.Node1MasterPage" MasterPageFile="~/RootMasterPage.Master" %>
<asp:Content ID="Content1"
ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<table border="0" cellpadding="0" cellspacing="0"
style="width: 100%; height: 100%; margin-bottom: 0px; color: #000066; ">
<tr>
<td style=" width:15%;height: 1000px; background-image: none; background-color:inherit; text-align:left; top:auto; "
>
<div>
<h2>
<a href="Default.aspx"><span class="style2">%u041E%u0441%u043D%u043E%u0432%u043D%u0430%u044F</span></a></h2>
<h3>
<a href="TypeCards.aspx"><span class="style2">%u0422%u0438%u043F%u044B %u043A%u0430%u0440%u0442%u043E%u0447%u0435%u043A</span></a></h3>
<h3>
<a href="TypeCards.aspx"><span class="style5">%u0422%u0438%u043F%u044B %u043F%u043E%u043A%u0443%u043F%u0430%u0442%u0435%u043B%u0435%u0439</span></a></h3>
<h3>
<a href="TypeCards.aspx"><span class="style5">%u0422%u0438%u043F%u044B %u0441%u043A%u0438%u0434%u043E%u043A</span></a></h3>
<h3>
<a href="TypeCards.aspx"><span class="style5">%u0422%u0438%u043F%u044B %u043B%u0438%u043C%u0438%u0442%u043E%u0432</span></a></h3>
<a href="Markets.aspx"><span class="style2">%u041C%u0430%u0440%u043A%u0435%u0442%u044B</span></a><br class="style2" />
<a href="Markets.aspx"><span class="style2">%u041F%u043E%u043A%u0443%u043F%u0430%u0442%u0435%u043B%u0438</span></a>
</div>
</td>
<td style="background-color: #FFFFFF" align="center">
<asp:ContentPlaceHolder ID="CPH2" runat="server">
</asp:ContentPlaceHolder>
</td>
</tr>
</table>
</asp:Content>
<asp:Content ID="Content2" runat="server" contentplaceholderid="head">
<style type="text/css">
.%u043D%u043E%u0432%u044B%u0439%u0421%u0442%u0438%u043B%u044C1
{
line-height: normal;
}
.style2
{
color: #FFFF66;
}
.style5
{
background-color: #66CCFF;
color: #000066;
}
</style>
</asp:Content>
В самом итоге меняем Default.aspx и ее внутренний текст:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="SIP3._Default" MasterPageFile="~/Node1MasterPage.Master" %>
<asp:Content ID="Content1" ContentPlaceHolderID="CPH2"
Runat="Server">
<h3>%u0414%u043E%u0431%u0440%u043E %u043F%u043E%u0436%u0430%u043B%u043E%u0432%u0430%u0442%u044C!</h3>
</asp:Content>
В итоге у нас получается, что создавая любую новую страницу, что бы она работала как и весь сайт с мастер пейджом, просто вставляем данные с default и дорабатываем до необходимости.
Основная работа с мастерпейдж состоит в ContentPlaceHolderID
Sunday, December 21, 2008
Для нормальной работы с блогом
Спасибо Записки дебианщика для вставки кода пользуемся сайтом http://www.elliotswan.com/postable/
ISS7.0 Visual Studio 2008 Vista Web project
Имеем проблему на vista с iss 7.0 и с Visual Studio 2008 когда не запускается отладка.
необходимо добавить строку в web.config после <system.web>
необходимо добавить строку в web.config после <system.web>
<trust level="Full" originUrl="" />, а также для нормальной отлатки
<compilation batch="false" debug="true">
Thursday, December 18, 2008
Запуск внешний обработки 1Сv7/1Cv8 из C#
Для того чтоб запустить внешнюю обработку на семерке надо:
object v77 = null;
object retVal = null;
try
{
string BaseCatalog,
User = "",
Pass = "";
object[] arg = new object[3];
Type lateBoundType = Type.GetTypeFromProgID("v77.Application", true);
v77 = Activator.CreateInstance(lateBoundType);
arg[0] = lateBoundType.InvokeMember("RMTrade", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, null, v77, null);
arg[1] = @"/D" + "D:\\Work\\База 1С" + " /N" + User + " /P" + Pass;
arg[2] = "NO_SPLASH_SHOW";
lateBoundType.InvokeMember("Initialize", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, null, v77, arg);
object[] arg1 = new object[] { "ОткрытьФорму(\"Обработка\", ,\"C:\\Parts\\СоздатьЗаказ.ert\")" };
// запускаем обработку если Р=1 то выполнено успешно,если 0 то невыполнено
retVal = lateBoundType.InvokeMember("EvalExpr", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, null, v77, arg1);
}
catch (Exception er)
{ }
finally
{
// убиваем 1С
System.Runtime.InteropServices.Marshal.ReleaseComObject(v77);
GC.GetTotalMemory(true);
}
Для восьмерки надо:
1.Создать метод в обработке с атрибутом эксопрт
функция МояПроцедура() экспорт
возврат 5;
конецфункции
2.В программе:
var v81comType = Type.GetTypeFromProgID("V8.Application");
var v81 = Activator.CreateInstance(v81comType);
Object[] arguments = { @"File=""D:\Work\База 1С"";Usr=""Администратор"";" };
object trade = v81comType.InvokeMember("Connect", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, null, v81, arguments);
object v8_componenta = v81comType.InvokeMember("NewObject", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, null, v81, new object[] { "ВнешниеОбработкиМенеджер" });
object[] arg = { "c:\\111.epf" };
object myCompanent = v81comType.InvokeMember("Создать", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, null, v8_componenta, arg);
object myForm = v81comType.InvokeMember("МояПроцедура", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, null, myCompanent, null);
System.Runtime.InteropServices.Marshal.ReleaseComObject(v81);
GC.GetTotalMemory(true);
object v77 = null;
object retVal = null;
try
{
string BaseCatalog,
User = "",
Pass = "";
object[] arg = new object[3];
Type lateBoundType = Type.GetTypeFromProgID("v77.Application", true);
v77 = Activator.CreateInstance(lateBoundType);
arg[0] = lateBoundType.InvokeMember("RMTrade", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, null, v77, null);
arg[1] = @"/D" + "D:\\Work\\База 1С" + " /N" + User + " /P" + Pass;
arg[2] = "NO_SPLASH_SHOW";
lateBoundType.InvokeMember("Initialize", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, null, v77, arg);
object[] arg1 = new object[] { "ОткрытьФорму(\"Обработка\", ,\"C:\\Parts\\СоздатьЗаказ.ert\")" };
// запускаем обработку если Р=1 то выполнено успешно,если 0 то невыполнено
retVal = lateBoundType.InvokeMember("EvalExpr", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, null, v77, arg1);
}
catch (Exception er)
{ }
finally
{
// убиваем 1С
System.Runtime.InteropServices.Marshal.ReleaseComObject(v77);
GC.GetTotalMemory(true);
}
Для восьмерки надо:
1.Создать метод в обработке с атрибутом эксопрт
функция МояПроцедура() экспорт
возврат 5;
конецфункции
2.В программе:
var v81comType = Type.GetTypeFromProgID("V8.Application");
var v81 = Activator.CreateInstance(v81comType);
Object[] arguments = { @"File=""D:\Work\База 1С"";Usr=""Администратор"";" };
object trade = v81comType.InvokeMember("Connect", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, null, v81, arguments);
object v8_componenta = v81comType.InvokeMember("NewObject", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, null, v81, new object[] { "ВнешниеОбработкиМенеджер" });
object[] arg = { "c:\\111.epf" };
object myCompanent = v81comType.InvokeMember("Создать", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, null, v8_componenta, arg);
object myForm = v81comType.InvokeMember("МояПроцедура", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, null, myCompanent, null);
System.Runtime.InteropServices.Marshal.ReleaseComObject(v81);
GC.GetTotalMemory(true);
Коллекторы "вне закона" на страже сверхприбылей банкиров
Коллекторы "вне закона" на страже сверхприбылей банкиров
В ближайшее время ко многим украинским гражданам в дверь постучится коллектор с требованием погасить долги. Что нужно знать "погоревшему" заемщику.
Раздавая направо и налево кредиты, большая часть банков обросла «проблемной задолженностью». Все тайное рано или поздно становится явным – так и сейчас во время кризиса все начали обсуждать возможность массового невозврата кредитов. Одна из причин – многие из них либо давались под покупку недвижимости либо для предпринимательской деятельности или покупок под залог недвижимости.
Банки ориентировались на высокую стоимость недвижимости и не утруждали себе детальной проверкой платежеспособности клиента. В том числе – в будущем и при возможных изменениях экономической ситуации в государстве (как-то рост курса доллара). Теперь, когда всем стало понятно очевидное – стоимость недвижимости в Украине завышена в 2-3 раза, банки обеспокоились тем, что многие кредиты могут стать «проблемной задолженностью».
Причем залоговая недвижимость банки не спасет – ее реальная цена, особенно при массовой продаже, будет значительно ниже. Не желая терпеть огромные убытки вследствие своей недавней сверхприбыльной деятельности, банки хотят ужесточить ответственность заемщиков за невозврат кредитов. Параллельно с вышеописанными процессами, на рынке потребительского кредитования в Украине развивался «коллекторский бизнес».
Не желая самостоятельно решать проблему неплатежей, банки стали активно привлекать сторонние компании к ее разрешению - так называемые «коллекторские». Пока что большинство из них ограничиваются только надоедливыми звонками и sms-ками по телефону. Но иногда применяются незаконные методы «психологического воздействия».
В частности информирование родственников должника или его начальства на работе о наличии проблемного кредита. Одна из причин такой политики банков - невыгодность взыскания задолженности в судебном порядке. Кроме затрат времени и денег на судебные процессы, после решения суда банк обязан оплатить налоги (понятие налога в украине).
Но когда он получит «живые деньги» по решению суда? Желание обойти действующее законодательство Украины с целью не понести огромные убытки вследствие получения на протяжении многих лет сверхприбылей вынуждает банкиров искать «внесудебные» методы работы с должниками. А спрос как известно порождает предложение. В данном случае – пресловутые коллекторские компании.
Незаконность действий по передаче другому субъекту хозяйствования информации о банковском кредите гражданина очевидна. Согласно ст. 60 Закона Украины «О банках и банковском деле»:
«Інформація щодо діяльності та фінансового стану клієнта, яка стала відомою банку у процесі обслуговування клієнта та взаємовідносин з ним чи третім особам при наданні послуг банку і розголошення якої може завдати матеріальної чи моральної шкоди клієнту, є банківською таємницею. Банківською таємницею, зокрема, є: …2) операції, які були проведені на користь чи за дорученням клієнта, здійснені ним угоди;…» - то есть кредитные соглашения также подпадают под «банковскую тайну».
Ст. 62 этого закона устанавливает порядок и основания раскрытия «банковской тайны». Никаких коллекторских компаний либо просроченных кредитов там не указано. Согласно ст. 231, 232 Уголовного кодекса Украины, преследуется как разглашение банковской тайны, так и за умышленный сбор и использование таких сведений.
Кроме того, действия некоторых особенно «настырных» коллекторских компаний подпадают под состав преступления, предусмотренный ст. 182 УК Украины – нарушение неприкосновенности частной жизни, выразившееся в незаконном сборе, хранении, использовании и распространении информации о лице без его согласия (напомним – ни один закон коллекторских компаний не предусматривает; как в прочем – и таких действий по погашению просроченных банковских кредитов).
Почему бездействуют правоохранительные органы? Потому что работа коллекторских компаний спасает банки, принадлежащие известным олигархам и политикам, а также влиятельным иностранным компаниям от убытков. Однако это не значит, что нужно терпеть беспредел, потакая жадным на наживу банкирам. Они должны усвоить простую народную мудрость: «Любишь медок (сверхдоходы во время кредитного бума) – люби и холодок (массовые невозвраты кредитов и убытки, когда этот кредитный бум заканчивается)».
Общественные организации обращались в некоторые органы государственной власти с просьбой разъяснить законность работы коллекторов. В ответе Министерства Юстиции Украины (№2571-0-33-08 от 21.04.2008 за подписью заместителя Министра Л. В. Ефименко) фактически процитированы те же нормы законов Украины, которые указаны в начале статьи. Также разъяснен порядок раскрытия банковской тайны, при этом никакой возможности предоставления информации о клиентах-должниках коллекторским компаниям не указано.
Однако Минюст не стал делать однозначный вывод о незаконности работы таких компаний, сославшись на то, что «Враховуючи наведене, пропонуємо Вам звернутися до Національного Банку України, оскільки порушене питання належить до їх компетенції. Разом з тим повідомляємо, що листи міністерств, інших центральних органів виконавчої влади, не є нормативно-правовими актами, вони лише мають роз’яснювальний та інформаційний характер і не встановлюють правових норм».
В то же время, автор статьи опыту знает, что судьи при рассмотрении «скандальных» дел рады любой «бумажке», разъясняющей спорные правоотношения. Из которой можно выписать толкование неоднозначных норм закона в мотивировочную часть решения суда и сослаться на эту «бумагу» в случае дисциплинарного разбирательства по жалобе проигравшей стороны.
Национальный Банк Украины в своем письме (№18-313/1466-5604 от 24.04.2008 за подписью и.о. Главы А. В. Шаповалова) также указывает на нормы ст. ст. 60, 62 Закона Украины «О банках и банковском деятельности» и ст. 1076 Гражданского кодекса Украины как и Минюст. Однако дополнительно отмечает: «Відповідно до ст. 55 Закону України «Про банки та банківську діяльність (далі – Закон) відносини банку з клієнтом регулюється законодавством України, нормативно-правовими актами Національного Банку України та угодами (договорами) між клієнтом та банком.
Пунктами 1.4 глави 1 та 3.6 глави 3 Правил зберігання, захисту, використання та розкриття банківської таємниці, затверджених постановою Правління НБУ № 267 від 14.07.2006 (далі – Правила), передбачено, що відомості щодо заборгованості клієнта перед банком становлять банківську таємницю, а також те, що банки зобов’язані за погодженням з клієнтом відображати в договорах, що укладаються між банком і клієнтом, застереження щодо збереження банківської таємниці та відповідальності за її незаконне розголошення або використання».
То есть напрашивается вывод, что возможность привлечения «коллекторских» компаний к работе с проблемной задолженность должна быть прописана в кредитных договорах. Однако НБУ развивает свою мысль, ссылаясь на возможность привлечения баком к своей деятельности посторонних лиц, при условии сохранения банковской тайны и неиспользования этой тайной информации в свою пользу или в пользу третьих лиц.
Исходя из этого, в последнем абзаце письма НБУ указано: «Враховуючи наведене, вважаємо, що банк може передати третім особам інформацію щодо прострочених кредитів відповідно до вимог ст. 62 Закону України «Про банки і банківську діяльність» та пункту 3.1 глави 3 Правил».
Такой вывод НБУ противоречит сам себе – ведь эта информация (о клиентах – должниках) используется коллекторскими компаниями для осуществления своей хозяйственной деятельности (оказания услуг банкам) и обеспечению интересов банков. А ведь на запрет такого использования информации содержащей банковскую тайну он сам указывает в своем письме. То есть в очередной раз подтверждается истина, что нельзя совмещать регулирование и надзор за определенной отраслью в одних руках. В данном случае – у НБУ в сфере банков, банковской деятельности и банковской системы.
Так как НБУ больше беспокоится за то, чтобы банки не «лопнули», раздавая направо и налево кредиты (а для этого нужны жесткие средства борьбы с «проблемной» задолженностью). Чем в отстаивании конституционного права гражданина на сохранения тайны его частной жизни, в том числе – банковской тайны.
В условиях кризиса даже незаконная работа коллекторов не позволяет уберечь банки от убытков. Поэтому массово идут призывы от банкиров и «сочувствующих» им политиков:
* ввести уголовную ответственность за невозврат кредитов;
* упростить работу по взыскания задолженности по кредитам, исключив такие звенья как суд (ввести внесудебный порядок) и государственную исполнительную службу (разрешить работу частных исполнительных служб);
Относительно первого предложения, необходимо отделить «мухи от котлет». Для его обоснования часто приводятся данные о распространенной фальсификации документов необходимых для получения кредитов. Однако изобретать велосипед не нужно – действующий Уголовный кодекс Украины предусматривает довольно серьезную ответственность за такие действия (ст. ст. 190, 222). Что же касается просто невозврата кредитов, то существует очень хорошая юридическая гарантия для простых граждан, предусмотренная Европейской конвенцией по правам человека.
Согласно ст. 1 Протокола № 4: «Стаття 1. Заборона ув'язнення за борг. Нікого не може бути позбавлено свободи лише на підставі неспроможності виконати своє договірне зобов'язання.». Видимо не только в Украине крупный бизнес хотел бы превратить людей в рабов: «или плати или будешь лишен свободы». Так что бороться против инициатив наших политиков в этой части можно и вполне юридическими методами.
Что касается второго предложения, советуем нашим избирателям не поддерживать его по ряду причин. Во-первых, уровень добросовестности и законопослушания бизнес-структур в Украине невысокий. Многие сталкивались с судами о взыскании задолженности за жилищно-коммунальные услуги, когда единственным доказательством по делу становится справка о задолженности из бухгалтерии кредитора.
То есть судебный процесс строится на началах «сам себе подтвердил». Со схожей проблемой можно столкнуться и в банковской сфере если убрать судебное звено - тогда будут начисляться баснословные штрафы по непонятно какой методике. А если не согласны – вы теперь сами должны будете идти в суд и доказывать «что не верблюд».
Во-вторых, логичней, чтобы банки «несли на своих плечах» проблему судебных процессов, а не простой гражданин, не имеющий средств на оплату адвоката и времени. Пускай государство в лице своих органов (суда и исполнительной службы) ненадежный и необъективный арбитр, но лучше уж пусть будет такой, чем попасть во всевластие крупного бизнеса в отсутствие какого-либо арбитра.
P.S.Не вступайте в контакт со сборщиком долгов без надежной поддержки юриста!
«Кто такие коллекторы, что делать, если они явились домой или звонят с какими-то не то угрозами, не то предостережениями? Какие права у этих людей, что они могут, чего нет? Георгий Сергеевич».
Отвечает руководитель адвокатского объединения «Бирк и Партнер» Александр Шипка:
«Действующее гражданское законодательство позволяет кредитору совершать уступку права требования долга третьим лицам. Заинтересованная сторона обязана письменно поставить об этом в известность должника. Уведомление должно содержать суть требования, полное наименование организации, которой должен быть сделан платеж (статья 1082 ГК Украины). У должника есть право требования предоставить в разумные сроки доказательства перехода права требования долга именно к этому лицу.
Рост неплатежей в банковской, коммунальной, телекоммуникационной и иных сферах породил появление так называемых коллекторских (от английского collect - собирать) компаний, специализирующихся на сборе долгов. В отличие от других стран, в Украине пока отсутствуют какие-либо акты, регулирующие их деятельность. Это порождает различные криминогенные ситуации по вине как кредиторов, так и должников.
Что же делать, столкнувшись с данной проблемой на практике? Однозначно обратиться за юридической помощью, и чем быстрее, тем лучше. Это позволит выработать конкретный алгоритм действий с учетом юридических, экономических, психологических аспектов именно. Представитель кредитора при вступлении с вами в контакт обязан предъявить документ, удостоверяющий личность, доверенность на представление интересов по данному делу.
Общение по телефону, как и личный контакт должны проходить исключительно в урочное время. Запрещено прибегать к физическому и психологическому давлению, угрожать распространением компрометирующих сведений среди окружения должника, публично обвинять в мошенничестве, сообщать ему о якобы принятых мерах воздействия, которые объективно не могут быть совершены, лишать права или ограничивать право на распоряжение имуществом, собирать сведения о личной жизни и так далее. Без консультаций с юристом или хотя бы внимательного ознакомления с текстом не следует подписывать какие-либо документы».
* Источник: Cегодня
В ближайшее время ко многим украинским гражданам в дверь постучится коллектор с требованием погасить долги. Что нужно знать "погоревшему" заемщику.
Раздавая направо и налево кредиты, большая часть банков обросла «проблемной задолженностью». Все тайное рано или поздно становится явным – так и сейчас во время кризиса все начали обсуждать возможность массового невозврата кредитов. Одна из причин – многие из них либо давались под покупку недвижимости либо для предпринимательской деятельности или покупок под залог недвижимости.
Банки ориентировались на высокую стоимость недвижимости и не утруждали себе детальной проверкой платежеспособности клиента. В том числе – в будущем и при возможных изменениях экономической ситуации в государстве (как-то рост курса доллара). Теперь, когда всем стало понятно очевидное – стоимость недвижимости в Украине завышена в 2-3 раза, банки обеспокоились тем, что многие кредиты могут стать «проблемной задолженностью».
Причем залоговая недвижимость банки не спасет – ее реальная цена, особенно при массовой продаже, будет значительно ниже. Не желая терпеть огромные убытки вследствие своей недавней сверхприбыльной деятельности, банки хотят ужесточить ответственность заемщиков за невозврат кредитов. Параллельно с вышеописанными процессами, на рынке потребительского кредитования в Украине развивался «коллекторский бизнес».
Не желая самостоятельно решать проблему неплатежей, банки стали активно привлекать сторонние компании к ее разрешению - так называемые «коллекторские». Пока что большинство из них ограничиваются только надоедливыми звонками и sms-ками по телефону. Но иногда применяются незаконные методы «психологического воздействия».
В частности информирование родственников должника или его начальства на работе о наличии проблемного кредита. Одна из причин такой политики банков - невыгодность взыскания задолженности в судебном порядке. Кроме затрат времени и денег на судебные процессы, после решения суда банк обязан оплатить налоги (понятие налога в украине).
Но когда он получит «живые деньги» по решению суда? Желание обойти действующее законодательство Украины с целью не понести огромные убытки вследствие получения на протяжении многих лет сверхприбылей вынуждает банкиров искать «внесудебные» методы работы с должниками. А спрос как известно порождает предложение. В данном случае – пресловутые коллекторские компании.
Незаконность действий по передаче другому субъекту хозяйствования информации о банковском кредите гражданина очевидна. Согласно ст. 60 Закона Украины «О банках и банковском деле»:
«Інформація щодо діяльності та фінансового стану клієнта, яка стала відомою банку у процесі обслуговування клієнта та взаємовідносин з ним чи третім особам при наданні послуг банку і розголошення якої може завдати матеріальної чи моральної шкоди клієнту, є банківською таємницею. Банківською таємницею, зокрема, є: …2) операції, які були проведені на користь чи за дорученням клієнта, здійснені ним угоди;…» - то есть кредитные соглашения также подпадают под «банковскую тайну».
Ст. 62 этого закона устанавливает порядок и основания раскрытия «банковской тайны». Никаких коллекторских компаний либо просроченных кредитов там не указано. Согласно ст. 231, 232 Уголовного кодекса Украины, преследуется как разглашение банковской тайны, так и за умышленный сбор и использование таких сведений.
Кроме того, действия некоторых особенно «настырных» коллекторских компаний подпадают под состав преступления, предусмотренный ст. 182 УК Украины – нарушение неприкосновенности частной жизни, выразившееся в незаконном сборе, хранении, использовании и распространении информации о лице без его согласия (напомним – ни один закон коллекторских компаний не предусматривает; как в прочем – и таких действий по погашению просроченных банковских кредитов).
Почему бездействуют правоохранительные органы? Потому что работа коллекторских компаний спасает банки, принадлежащие известным олигархам и политикам, а также влиятельным иностранным компаниям от убытков. Однако это не значит, что нужно терпеть беспредел, потакая жадным на наживу банкирам. Они должны усвоить простую народную мудрость: «Любишь медок (сверхдоходы во время кредитного бума) – люби и холодок (массовые невозвраты кредитов и убытки, когда этот кредитный бум заканчивается)».
Общественные организации обращались в некоторые органы государственной власти с просьбой разъяснить законность работы коллекторов. В ответе Министерства Юстиции Украины (№2571-0-33-08 от 21.04.2008 за подписью заместителя Министра Л. В. Ефименко) фактически процитированы те же нормы законов Украины, которые указаны в начале статьи. Также разъяснен порядок раскрытия банковской тайны, при этом никакой возможности предоставления информации о клиентах-должниках коллекторским компаниям не указано.
Однако Минюст не стал делать однозначный вывод о незаконности работы таких компаний, сославшись на то, что «Враховуючи наведене, пропонуємо Вам звернутися до Національного Банку України, оскільки порушене питання належить до їх компетенції. Разом з тим повідомляємо, що листи міністерств, інших центральних органів виконавчої влади, не є нормативно-правовими актами, вони лише мають роз’яснювальний та інформаційний характер і не встановлюють правових норм».
В то же время, автор статьи опыту знает, что судьи при рассмотрении «скандальных» дел рады любой «бумажке», разъясняющей спорные правоотношения. Из которой можно выписать толкование неоднозначных норм закона в мотивировочную часть решения суда и сослаться на эту «бумагу» в случае дисциплинарного разбирательства по жалобе проигравшей стороны.
Национальный Банк Украины в своем письме (№18-313/1466-5604 от 24.04.2008 за подписью и.о. Главы А. В. Шаповалова) также указывает на нормы ст. ст. 60, 62 Закона Украины «О банках и банковском деятельности» и ст. 1076 Гражданского кодекса Украины как и Минюст. Однако дополнительно отмечает: «Відповідно до ст. 55 Закону України «Про банки та банківську діяльність (далі – Закон) відносини банку з клієнтом регулюється законодавством України, нормативно-правовими актами Національного Банку України та угодами (договорами) між клієнтом та банком.
Пунктами 1.4 глави 1 та 3.6 глави 3 Правил зберігання, захисту, використання та розкриття банківської таємниці, затверджених постановою Правління НБУ № 267 від 14.07.2006 (далі – Правила), передбачено, що відомості щодо заборгованості клієнта перед банком становлять банківську таємницю, а також те, що банки зобов’язані за погодженням з клієнтом відображати в договорах, що укладаються між банком і клієнтом, застереження щодо збереження банківської таємниці та відповідальності за її незаконне розголошення або використання».
То есть напрашивается вывод, что возможность привлечения «коллекторских» компаний к работе с проблемной задолженность должна быть прописана в кредитных договорах. Однако НБУ развивает свою мысль, ссылаясь на возможность привлечения баком к своей деятельности посторонних лиц, при условии сохранения банковской тайны и неиспользования этой тайной информации в свою пользу или в пользу третьих лиц.
Исходя из этого, в последнем абзаце письма НБУ указано: «Враховуючи наведене, вважаємо, що банк може передати третім особам інформацію щодо прострочених кредитів відповідно до вимог ст. 62 Закону України «Про банки і банківську діяльність» та пункту 3.1 глави 3 Правил».
Такой вывод НБУ противоречит сам себе – ведь эта информация (о клиентах – должниках) используется коллекторскими компаниями для осуществления своей хозяйственной деятельности (оказания услуг банкам) и обеспечению интересов банков. А ведь на запрет такого использования информации содержащей банковскую тайну он сам указывает в своем письме. То есть в очередной раз подтверждается истина, что нельзя совмещать регулирование и надзор за определенной отраслью в одних руках. В данном случае – у НБУ в сфере банков, банковской деятельности и банковской системы.
Так как НБУ больше беспокоится за то, чтобы банки не «лопнули», раздавая направо и налево кредиты (а для этого нужны жесткие средства борьбы с «проблемной» задолженностью). Чем в отстаивании конституционного права гражданина на сохранения тайны его частной жизни, в том числе – банковской тайны.
В условиях кризиса даже незаконная работа коллекторов не позволяет уберечь банки от убытков. Поэтому массово идут призывы от банкиров и «сочувствующих» им политиков:
* ввести уголовную ответственность за невозврат кредитов;
* упростить работу по взыскания задолженности по кредитам, исключив такие звенья как суд (ввести внесудебный порядок) и государственную исполнительную службу (разрешить работу частных исполнительных служб);
Относительно первого предложения, необходимо отделить «мухи от котлет». Для его обоснования часто приводятся данные о распространенной фальсификации документов необходимых для получения кредитов. Однако изобретать велосипед не нужно – действующий Уголовный кодекс Украины предусматривает довольно серьезную ответственность за такие действия (ст. ст. 190, 222). Что же касается просто невозврата кредитов, то существует очень хорошая юридическая гарантия для простых граждан, предусмотренная Европейской конвенцией по правам человека.
Согласно ст. 1 Протокола № 4: «Стаття 1. Заборона ув'язнення за борг. Нікого не може бути позбавлено свободи лише на підставі неспроможності виконати своє договірне зобов'язання.». Видимо не только в Украине крупный бизнес хотел бы превратить людей в рабов: «или плати или будешь лишен свободы». Так что бороться против инициатив наших политиков в этой части можно и вполне юридическими методами.
Что касается второго предложения, советуем нашим избирателям не поддерживать его по ряду причин. Во-первых, уровень добросовестности и законопослушания бизнес-структур в Украине невысокий. Многие сталкивались с судами о взыскании задолженности за жилищно-коммунальные услуги, когда единственным доказательством по делу становится справка о задолженности из бухгалтерии кредитора.
То есть судебный процесс строится на началах «сам себе подтвердил». Со схожей проблемой можно столкнуться и в банковской сфере если убрать судебное звено - тогда будут начисляться баснословные штрафы по непонятно какой методике. А если не согласны – вы теперь сами должны будете идти в суд и доказывать «что не верблюд».
Во-вторых, логичней, чтобы банки «несли на своих плечах» проблему судебных процессов, а не простой гражданин, не имеющий средств на оплату адвоката и времени. Пускай государство в лице своих органов (суда и исполнительной службы) ненадежный и необъективный арбитр, но лучше уж пусть будет такой, чем попасть во всевластие крупного бизнеса в отсутствие какого-либо арбитра.
P.S.Не вступайте в контакт со сборщиком долгов без надежной поддержки юриста!
«Кто такие коллекторы, что делать, если они явились домой или звонят с какими-то не то угрозами, не то предостережениями? Какие права у этих людей, что они могут, чего нет? Георгий Сергеевич».
Отвечает руководитель адвокатского объединения «Бирк и Партнер» Александр Шипка:
«Действующее гражданское законодательство позволяет кредитору совершать уступку права требования долга третьим лицам. Заинтересованная сторона обязана письменно поставить об этом в известность должника. Уведомление должно содержать суть требования, полное наименование организации, которой должен быть сделан платеж (статья 1082 ГК Украины). У должника есть право требования предоставить в разумные сроки доказательства перехода права требования долга именно к этому лицу.
Рост неплатежей в банковской, коммунальной, телекоммуникационной и иных сферах породил появление так называемых коллекторских (от английского collect - собирать) компаний, специализирующихся на сборе долгов. В отличие от других стран, в Украине пока отсутствуют какие-либо акты, регулирующие их деятельность. Это порождает различные криминогенные ситуации по вине как кредиторов, так и должников.
Что же делать, столкнувшись с данной проблемой на практике? Однозначно обратиться за юридической помощью, и чем быстрее, тем лучше. Это позволит выработать конкретный алгоритм действий с учетом юридических, экономических, психологических аспектов именно. Представитель кредитора при вступлении с вами в контакт обязан предъявить документ, удостоверяющий личность, доверенность на представление интересов по данному делу.
Общение по телефону, как и личный контакт должны проходить исключительно в урочное время. Запрещено прибегать к физическому и психологическому давлению, угрожать распространением компрометирующих сведений среди окружения должника, публично обвинять в мошенничестве, сообщать ему о якобы принятых мерах воздействия, которые объективно не могут быть совершены, лишать права или ограничивать право на распоряжение имуществом, собирать сведения о личной жизни и так далее. Без консультаций с юристом или хотя бы внимательного ознакомления с текстом не следует подписывать какие-либо документы».
* Источник: Cегодня
Subscribe to:
Posts (Atom)