Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
12
Добавлен:
20.04.2024
Размер:
10.74 Mб
Скачать

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Небольшая часть иерархии классов Cocoa

Литературы на русском языке по ObjC пока немного. Но есть хорошие гайды на английском языке

//Класс Dog — наследник NSObject

//Разместим его интерфейс в «Dog.h» @interface Dog : NSObject

{

//Здесь размещаем поля объекта @private

int Age; @public

int Color;

}

//После этого идет описание сообщений,

//на которые отвечает объект.

//Перед сообщениями экземпляров ставится «-»,

//а перед сообщениями класса

//(аналог статических методов в C++) — знак «+».

//В описании сообщения указывается имя

//сообщения, список передаваемых параметров

//и тип возвращаемого значения.

-(void) voice;

-(void) setAge: (int) age;

-(int) getAge;

@end

// Реализация сообщений нашего класса (Dog.m) @implementation Dog

- (void) voice

{

NSLog(@"Woof woof");

}

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

//Вообще, для этого есть свойства,

//íî î íèõ как-нибудь в следующий раз - (void) setAge: (int) age

{

Age = age;

}

- (int) getAge

{

return Age;

}

@end

Для вызова метода используется следующий синтаксис:

[my_class_pointer message_name: arg1 arg2_name: arg2 arg3_name: arg3]

Например:

[dog1 setAge: 3];

Немного непривычно после точек и стрелок C++ и Java, но к такому синтаксису быстро привыкаешь и даже начинаешь считать его удобным. Что интересно, мы можем посылать сообщения нулевому указателю (nil). Результат всегда будет nil.

После того, как класс описан и определена реализация для методов-обработчиков сообщений, можно создавать объекты этого класса.

Для того, чтобы создать объект, нужно сделать две вещи — выделить для него память и инициализировать ее. В Objective-C эти два действия разделены. Это может показаться излишним, но на самом деле придает процессу создания объектов дополнительную гибкость. Чтобы создать объект Dog, нам потребуется следующая строчка:

Dog * dog1 = [[Dog alloc] init];

alloc — метод класса NSObject. Он выделит необходимое количество памяти под наш объект и вернет указатель на него. После этого мы можем выполнить инициализацию, послав только что созданному объекту сообщение init. Мы не переопределяли обработку сообщений alloc и init, поэтому будут использованы реализации из NSObject. На практике init часто приходится переопределять для того, чтобы произвести какую-то начальную настройку объекта или передать дополнительные параметры. init играет роль конструктора в ObjC.

Cocoa Framework

Cocoa — набор классов и функций Objective-С, предоставляющих доступ к сервисам Mac OS X для пользовательских приложений. Поскольку для взаимодействия с классами Cocoa необходима среда выполнения ObjC, разработка с использованием этого фреймворка возможна только на Objective-C. Для Сocoa существует возможность кроссплатформенной разработки под Linux и Windows благодаря проектам GNUStep и cocotron.

Carbon Framework

Carbon — процедурный фреймворк Mac OS X, предназна- ченный для использования в приложениях на C/C++. Он предоставляет обратную совместимость с более ранними версиями Mac OS (например, Mac OS 9).

В настоящее время возможности Carbon для работы с Mac OS X становятся все скромнее. Так, напри-

мер, невозможно получить доступ к GUI из приложения Carbon для 64-битного окружения — Apple отдает предпочтение Cocoa.

XÀÊÅÐ 12 /143/ 10

099

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

CODING

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Теперь, когда мы создали экземпляр класса, мы имеем полное право отправлять ему сообщения:

int age = [dog1 getAge]; [dog1 voce];

Для того, чтобы уничтожить объект и освободить выделенную ему память и (возможно) другие ресурсы, ему нужно отправить сообще-

ние release:

[dog release];

Управление памятью реализовано в ObjC в виде подсчета ссылок. alloc создает объект с числом ссылок, равным единице.

release уменьшает количество ссылок для данного объекта на 1. Объект будет уничтожен, когда счетчик достигнет 0. Если тебе когданибудь приходилось использовать COM, то такая реализация управления памятью должна быть тебе хорошо знакома.

Значение счетчика можно увеличивать, посылая объекту сообщение retain. Кстати, начиная с Objective-C 2.0, стала доступна сборка мусора, ее можно совмещать с классическим управлением памятью с помощью подсчета ссылок. Кроме явного уничтожения объекта, ты можешь добавить его в пул временных объектов

(NSAutoreleasePool), послав сообщение autorelease. Так часто посту-

пают, например, при возвращении объектов методы классов Cocoa (метод stringByAppendingString объектов NSString, например).

NSAutoreleasePool *pool;

pool = [[NSAutoreleasePool alloc] init]; NSString *str;

//Проинициализируем строчку и добавим

//åå â pool

str = [[[NSString alloc] init] autorelease]; // ...

[pool drain]; // Здесь объект str будет уничтожен

В этом кратком обзоре ObjC следует, пожалуй, сказать еще об исключениях Objective-C. Обработка ошибок времени выполнения в С трудоемка и может порождать множество других ошибок. На самом деле в C есть два варианта обработки ошибок времени выполнения

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

Код нормального процесса исполнения и код обработки ошибок смешивается, что не есть хорошо. К счастью, в ObjC, как и в C++, есть механизм исключений.

Вот пример обработки исключительной ситуации в ObjC:

Обработка исключений в Objective-C

Cup * cup = [[Cup alloc] init];

@try

{

[cup fill];

}

@catch ( NSException * exc )

{

NSLog ( @"Exception caught: %@", exc );

}

@finally

{

[cup release];

}

Конечно, описать полностью стандарт языка в одной короткой статье невозможно. Поэтому, если ты заинтересовался, я привел ссылки на некоторые полезные ресурсы.

«Кокао» для кодера

После экскурса по Objective-C можно поговорить о доступных фреймворках МакОСи.

Куда же без них? Фреймворк сделает за тебя всю грязную работу, чтобы ты мог спокойно заниматься основной задачей. Для разработки нативных приложений под МакОСь распространение получили два фреймворка — Cocoa и Carbon. Если ты пишешь под Мак или под iOS на Objective-C, то твой выбор

— Cocoa.

Cocoa — это продукт эволюции программных сред NeXTSTEP

иOPENSTEP, которые разрабатывались компанией NeXT. Перекочевав на Mac OS X, фреймворк сильно изменился, и в нем появилось множество новых классов. Все они, как в С# или Java, являются наследниками одного класса — NSObject. В Cocoa представлены базовые типы, такие как NSNumber

иNSString, различные контейнеры (NSArray, NSDictionary),

обертки для системных объектов и т.д.

Давай-ка опробуем Cocoa и Objective-C в действии и создадим небольшое консольное Cocoa-приложение.

В Сети существует множество веб-сервисов. Некоторые из них просто предоставляют информацию в удобном формате, напри-

мер, в XML.

Одним из таких сервисов является сервис Российского Центробанка, предоставляющий информацию о текущих курсах валют. По адресу www.cbr.ru/scripts/XML_daily.asp можно полу-

чить XML’ку следующего вида:

<ValCurs Date="22.09.2010" name="Foreign Currency Market">

<Valute ID="R01010"> <NumCode>036</NumCode> <CharCode>AUD</CharCode> <Nominal>1</Nominal> <Value>29,4185</Value>

</Valute>

...

<Valute ID="R01020A"> <NumCode>944</NumCode> <CharCode>AZN</CharCode> <Nominal>1</Nominal> <Value>38,6777</Value>

</Valute>

</ValCurs>

Создадим класс ObjC RCBDayly, который будет скачивать эту XML’ку, парсить ее и предоставлять данные в удобном для нас виде. Исходник нашего класса ты можешь увидеть на врезке. На этом примере ты можешь видеть, как легко в Cocoa работать с сетью и XML. При создании подобных приложений можно обойтись, конечно, и средствами POSIX, а вот если ты хочешь создать GUI-приложение, без Cocoa тебе не обойтись. Но об этом как-нибудь в другой раз.

Заключение

Разнообразные гаджеты от Apple производятся и продаются по всему миру в огромном количестве. Всех их объединяет то, что на них работает Mac OS X или iOS и, если ты хочешь освоить разработку под эти операционки, знания Objective-C тебе очень пригодятся. До встречи в эфире!z

100

XÀÊÅÐ 12 /143/ 10

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

 

 

X

 

 

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

 

F

 

 

 

 

 

 

t

 

 

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

 

 

r

 

 

P

 

 

 

 

 

NOW!

 

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

w Click

to

 

 

 

 

 

 

CODING

 

 

 

 

 

 

 

m

Александр Эккерт stannic.man@gmail.com

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

o

 

 

 

 

.

 

 

 

 

 

.c

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

...В ПРОГЕ ОБНАРУЖИЛСЯ БАГ. ПЕРВОЕ ОБРАЩЕНИЕ К БАЗЕ ОТВАЛИВАЛОСЬ ПО ТАЙМАУТУ, НО СЛЕДУЮЩИЕ ШЛИ НОРМАЛЬНО. ВЫЯСНИЛОСЬ, ЧТО ИНДУСЫ НАКОЛБАСИЛИ МЕТОД В 75000 СТРОК, И ПОДКЛЮЧЕНИЕ К БД ОТВАЛИВАЛОСЬ ЗА ТО ВРЕМЯ, ПОКА ШЛА JITКОМПИЛЯЦИЯ МЕТОДА...

ПО-МОЕМУ, МЕТОД В 75К СТРОК НА С# СКОРЕЕ ПРИЗОВЕТ ДЬЯВОЛА, ЧЕМ ЗАРАБОТАЕТ.

Перехватываем.NET

Теорияипрактикаперехватавызовов

.NET-функций

Помню, несколько лет назад мы с друзьями язвили по поводу того, что скоро мобильные телефоны уже не будут отставать от компьютеров по мощности микропроцессора. И вот, пожалуйста — в том месте, где я работаю, 20% компов УЖЕ уступают по мощности современному GalaxyS.

АНАЛОГИЧНАЯ СИТУАЦИЯ СКЛАДЫВАЕТСЯ И С РАЗРАБОТКОЙ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ — ПАРУ ЛЕТ НАЗАД ПРОГРЕССИВНОЕ

ЧЕЛОВЕЧЕСТВО БЫЛО УВЕРЕНО, ЧТО ПЕРЕХВАТ ВЫЗОВА .NET ФУНКЦИЙ — УДЕЛ ИЗВРАЩЕНЦЕВ. И я бы с ними согласился.

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

речь идет о стандартном WinAPI-интерфейсе. Идея перехвата вызовов функций в .NET поначалу вызывала лишь улыбки программистов. Улыбали и попытки написания вирусов под .NET Framework. Времена изменились, и вместе с ними изменились требования, которые потенциальный заказчик ставит для разработчика. Теперь перехват вызовов в .NET-прогах — не такая уж никчемная и безумная задача, как казалось раньше. И теперь после прочтения этой статьи ты легко сможешь взять под контроль свои .NETприложения!

102

XÀÊÅÐ 12 /143/ 10

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

HTTP://WWW

links http://reflector. red-gate.com — сайт программы.NET Reflector, которыйпо-

зволяетвосстановить исходныйкод.NETпрограмм, дажеесли ихсорцынедоступны. Рекомендуется кпользованию!

DVD

dvd

Metadata Expert – твой незаменимый помощник

Надискетынайдешь законченныйвариантлибы, которая позволяетвнедрять кодв.NET’овские сборки

Собираем мозаику

Теперь можно со всей смелостью утверждать, что ответ Майкрософта вездесущей Java удался — разработчик на .NET на сегодняшний день так же востребован, как и Java-программист. С внедрением .NET Framework принципиально поменялась схема «язык программирования — ОС». Если раньше речь шла об адаптации одного языка для разных платформ, то сейчас — об адаптации разных языков для одной платформы. Давай вкратце вспомним, что такое .NET,

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

Платформа .NET содержит общеязыковую среду выполнения (Common Language Runtime — CLR).

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

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

Metadata

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

Итак, в них хранятся все классы, типы, константы и строки, используемые .NET-приложением. Metadata, в свою очередь, делится на несколько отдельных куч (heaps) или потоков. В Microsoft .NET предусмотрены пять куч: #US, #Strings, #Blob #GUID и #~.

#US-куча хранит все строки, которые программист «заготовил» в своем коде. К примеру, если программа выводит на экран строку функцией Print("hello"), то hello будет храниться в #US-куче.

#Strings-куча хранит в себе такие вещи, как имена методов и имена файлов.

#Blob-куча содержит в себе бинарные данные, на которые ссылается сборка, такие как, например, сигнатура методов.

#~-куча содержит набор таблиц, которые определяют важное содержимое .NET-сборки. Например, там содер-

жатся таблицы AssemblyRef, MethodRef, MethodDef, и

таблицы Param. Таблица AssemblyRef включает набор внешних сборок, от которых зависит сама сборка. Таблица MethodRef включает в себя лист внешних методов, которые используются сборкой. Таблица MethodDef содержит все методы, которые определены в сборке. Param, в свою очередь, содержит все параметры, которые используются методами, определенными в таблице

MethodDef.

«К чему эта скукота?», — спросишь ты. Спокойно! Сверни ковер нетерпения и положи его в сундук ожидания, ведь без понимания того, «как же эта хрень работает», смысл статьи до тебя может и не дойти :). Поговорим поподробнее о таблице MethodDef. Для перехвата методов .NET-приложений это крайне нужная вещь.

Каждая запись в таблице методов содержит RVA (relative virtual address) метода, флаги метода, имя метода, смещение в куче #Blob на сигнатуру метода

INFO

info

Дляисследования

Metadata всвоих

.NET-приложениях могупосоветовать

.NET Metadata Expert — этоудобный инструментисследованияприложений, разработанныхдля платформыMicrosoft

.NET Framework.

XÀÊÅÐ 12 /143/ 10

103

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

 

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

w Click

to

BUY

 

 

 

 

 

CODING

 

 

 

 

 

 

m

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

PLINQ

 

TPL

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Будущие релизы

LINQ

WCF

 

WPF

(Indigo)

 

(Avalon)

 

 

 

ADO.NET

Entity Framework

WCS

 

WF

(InfoCard)

 

(Workflow)

 

 

 

5.3

0.3

Base Class Library

Common Language Runtime (CLR)

Внутри .NET

NET. Framework 0.2

и индекс в таблице Param, которая содержит первый параметр, передаваемый функции. RVA метода указывает на тело метода (который содержит IL-код) в секции .TEXT.

Сигнатура метода определяет порядок передачи параметров (calling convention), какой тип будет на возврате из метода и т.д.

Чтобы ты смог понять тему на уровне Дао, на сайте rsdn.ru выложены аж целых три статьи на тему метаданных в .NET, которые рекомендуются к обязательному изучению (http://www.rsdn.ru/article/ dotnet/refl.xml, …/phmetadata.xml, и …/dne.xml).

Как далеко можно зайти в лес?

До его середины — дальше лес уже кончается. Спешу обрадовать: половину леса мы уже прошли и постепенно продвигаемся к нашей главной цели — научиться перехватывать .NET-вызовы.

Рассмотрим вопрос исполнения .NET-приложений чисто практически:

Mscoree.dll (исполнительный движок среды .NET)

Mscorwks.dll (where most of the stuff happens)

Mscorjit.dll (та самая JIT)

Mscorsn.dll (обрабатывает верификацию «строгих» имен)

Mscorlib.dll (Base Class Library — библиотека базовых классов)

Fushion.dll (assembly binding)

Любое .NET-приложение на точке входа имеет всего одну инструкцию. Эта инструкция реализует джамп на функцию _CorExeMain, которая располагается в таблице импорта.

_CorExeMain, в свою очередь, ссылается на mscoree.dll, которая и начинает процесс загрузки и исполнения .NET-приложения. Mscoree.dll вызывает _CorExeMain из mscorwks.dll. Mscorwks.dll — это довольно большая библиотека, которая контролирует и обрабатывает процесс загрузки. Она загружа-

ет библиотеки базовых классов (BCL) и только затем вызывает точку входа Main() твоего .NET-приложения. Так как Main() в этом моменте все еще не декомпилировано, код Main() будет перебро-

шен обратно в mscorwks.dll для компиляции. Mscorwks.dll

вызовет JITFunction, которая загрузит среду JIT из mscorjit.dll. Как только сгенерированный IL-код будет скомпилирован в native-код, контроль будет передан обратно в Main(), которая и начнет непосредственное исполнение.

Перехват? Легко!

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

Первое, что надо уяснить для осуществления перехвата — это то, что методы, которые мы хотим перехватить, хранятся в конце секции .TEXT. Это сделано, потому что секция .TEXT

.NET’овской сборки довольно компактна — там недостаточно места для хранения всех перехваченных функций.

Кто-то может спросить, почему нельзя просто изменить стандартным общеизвестными способом (инструкции «CALL» и «JUMP» RVA-метода) на перехватываемый код, а затем просто перехватить код всех оригинальных функций? Причина проста

— инструкции «CALL» и «JUMP» в MSIL-коде используют токены (сигнатуры) методов, а не смещения на них. Таким образом, если я хочу получить ссылку на код, который нужно перехватить, это нужно будет сделать путем поиска токена метода. Итак, для решения нашей задачи перехвата нам нужно будет раздвинуть секцию .TEXT кода.

104

XÀÊÅÐ 12 /143/ 10

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Структура файла

Заголовок MSDOS

Заголовок PE

Заголовки PE-секций, включая .NET-заголовок

Секция кода (.TEXT), включая Metadata

Секция данных (.DATA или .RSRC)

Секция релоков (.RELOC или .RDATA)

Схема .NET исполняемого файла

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

Второе — нам нужно найти RVA метода в таблице MethodDef и перезаписать его так, чтобы он указывал на место расположения нового перехваченного метода. Для совершения этой операции нужно увеличить размер секции .TEXT для того, чтобы она смогла вместить все это хозяйство. При этом должны быть учтены и виртуальный, и raw-размер секции. Виртуальный размер — это актуальный, действительный размер секции, rawразмер — это размер, округленный до выравнивания секции. Виртуальные адреса и размеры нужны для того, чтобы знать, как исполняемый файл загружается в память.

Если, к примеру, секция .TEXT имеет виртуальный адрес 0x1000, то по этому смещению в памяти запущенного процесса мы и найдем эту самую секцию .TEXT, которая туда была спроецирована. Вместе с тем, raw-адрес секции может быть 0x200, а это значит, что секция .TEXT в самом файле расположена по смещению 0x200.

Те секции, которые идут за .TEXT (секции данных и релоки), тоже нужно будет выровнять, потому что расширение секции

.TEXT «наедет» на начало следующей секции, в результате чего файл просто не запустится. В конце всего этого действа обновляются PE-заголовки. Все, теперь наш перехваченный код вшит прямо в сборку, а другие методы остались нетронутыми.

Колбасим код

Как ты, наверное, уже догадался, один из основных моментов, который позволит нам взять под контроль .NET-программулину, заключается в получении указателя на заголовок CLIHeader, который, в свою очередь, содержит такое поле, как Metadata. Оно-то нам и нужно:

XÀÊÅÐ 12 /143/ 10

ПОЛУЧИМ УКАЗАТЕЛЬ НА CLIHEADER C#

FileReader Input = new FileReader(AssemblyPath); byte[] Buffer = Input.Read();

[skip...]

ImageBase = Marshal.AllocHGlobal(Buffer.Length * 2); HeaderOffset = *((UInt32 *)(ImageBase + 60));

PE = (PEHeader *)(ImageBase + HeaderOffset); HeaderOffset += (UInt32)sizeof(PEHeader); StandardHeader = (PEStandardHeader *)(ImageBase +

HeaderOffset);

RVA *CLIHeaderRVA = (RVA *)((byte *) StandardHeader + 208);

SectionOffset = GetSectionOffset(CLIHeaderRVA-> Address);

CLI = (CLIHeader *)(ImageBase + CLIHeaderRVA->Address - SectionOffset);

MetaDataHeader = (MetaDataHeader *)(ImageBase + CLI->MetaData.Address - SectionOffset);

metadata = new MetaData(Function, ImageBase, (Int32)CLI->MetaData.Address, MetaDataHeader, CLI->MetaData.Size);

Далее будет ненамного сложнее, особенно для тех, кто знаком со способом внедрения в PE-файлы путем расширения его секций.

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

VirtualSize = TextSectionHeader->VirtualSize

+HookSize; RawDataSize = VirtualSize;

if ((RawDataSize % FileAlignment) != 0) RawDataSize += (FileAlignment -

(RawDataSize % FileAlignment)); StandardHeader->CodeSize = RawDataSize; HookAddress = TextSectionHeader->VirtualAddress

+TextSectionHeader->VirtualSize; TextSectionHeader->VirtualSize = VirtualSize; TextSectionHeader->RawDataSize = RawDataSize; [skip...]

StandardHeader->DataBase = DataSectionHeader-> VirtualAddress;

StandardHeader->ImageSize = SectionHeader-> VirtualAddress + SectionHeader->VirtualSize;

if ((StandardHeader->ImageSize % SectionAlignment) != 0) StandardHeader->ImageSize +=

(SectionAlignment -

(StandardHeader->ImageSize % SectionAlignment));

Вот и все. К сожалению, те 75 тысяч строк кода, которые мне хотелось бы выложить на страницы журнала, в него просто не влезут. Шутка :). Полностью рабочий код ты, как и всегда, сможешь найти на диске.

Заключение

Так уж получилось, что большая часть статьи — это описание принципов действия .NET’овской среды, о которых ты наверняка наслышан. Но, как говорится, RTFM — и будет тебе счастье. Для того, чтобы полностью овладеть этой техникой и прослыть шаманом, тебе придется хорошенько потрудиться. Но это не страшно, ведь перехват .NET-приложений в твоем исполнении того стоит.z

105

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

X

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

 

 

 

 

 

 

 

 

 

 

F

 

 

 

 

 

 

t

 

 

 

 

 

 

 

 

 

 

 

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

r

 

 

 

 

 

 

 

 

 

 

P

 

 

 

 

 

NOW!

 

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

w Click

to

BUY

 

 

 

 

 

 

 

CODING

 

 

 

 

 

 

 

 

 

 

 

 

 

 

m

Денис «c0n Difesa» Макрушин http://twitter.com/difezza, http://defec.ru

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

o

 

 

 

 

 

 

 

 

 

 

 

 

 

.

 

 

 

 

 

.c

 

 

 

 

 

 

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Погружение вматрицу

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Анализструктурыиметоды распознаванияQR-кода

В современном мире информация может представляться в самых причудливых формах. Причины для этого разные и не всегда имеют стеганографическую подоплеку. У «человека разумного» буквально появился «третий глаз»: мобильный телефон стал неотъемлемым атрибутом каждого из нас. А что именно с его помощью мы попытаемся разглядеть, ты узнаешь из этой статьи.

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

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

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

Пришел. Увидел. Распознал.

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

1)Линейный (одномерный). Наиболее распространенный представитель — (в народе называемый «штрихкодом»).

2)Двумерный. В свою очередь он делится на:

2.1) многоуровневый (stacked);

2.2) матричный (matrix).

Многоуровневые коды нам неинтересны, так как они представляют собой попросту «многослойный» линейный код. В свою очередь, матричные кодировки «упаковывают» информацию как по гори-

106

XÀÊÅÐ 12 /143/ 10

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

F

 

 

 

 

 

 

t

 

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

to

BUY

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

 

.

 

 

 

 

 

.c

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Результат разбора пациента — строка «Xakep Online: http://xakep.ru»

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

Из всего многообразия матричных кодов нам интересен QR-код. Его повсеместная распространенность (одна только Япония использует эти кодировки с такой завидной популярностью, как, например, мы используем таблички с указанием названия улицы и номера дома) обусловлена прежде всего высокой степенью его распознаваемости и, как следствие, простотой распознающего оборудования. Кстати, аббревиатура QR образована от англ. «quick response», что в переводе на великий и могучий означает «быстрый отклик». Быстро «откликнуться» конкретный экземпляр QR-кодов может на самое непривередливое оборудование. Так, например, имея в наличии мобильный телефон или любой другой девайс с камерой практически любого разрешения, можно считать себя уже достаточно укомплектованным для охоты за QR-кодами. Если сфотографировать QR-картинку, прилагающуюся к статье (или открыть ее с диска и сделать банальный PrintScreen, но это выглядит менее эффектно), пропустить фотографию через одну из программ распознавания, то мы получим следующую строку:

Xakep Online: http://xakep.ru

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

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

INFO

Матричный код PDF417. О сложности его

info

 

распознавания подручными средствами

ПоданнымВикипе-

и говорить не приходится

дии, максимальное

 

количествосимво-

Готовим инструменты

лов, котороепомеща-

етсяводинQR-код:

Разрабатывать приложение мы будем под платформу

• Цифры— 7089

.NET на языке C#. Выбор данного инструментария

• Цифрыибуквы

основан не только на удобстве и скорости разработки

(включаякириллицу)

приложения, но и на получении многоплатформенно-

— 4296

го результата. По определению, скомпилированный

• Двоичныйкод—

под .NET Framework проект в силу ряда особенностей

2953 байт

наделен свойствами кроссплатформенности. Плюс ко

• Иероглифы— 1817

всему, если скомпилировать полученный проект с под-

 

держкой окружения .NET Compact Framework, мы полу-

 

чаем высокопроизводительное приложение, специ-

 

ально адаптированное для запуска на мобильных плат-

 

формах. Указанная совместимость без дополнительных

HTTP://WWW

трудозатрат объясняется следующей особенностью:

 

Microsoft .NET Compact Framework представляет собой

links

несколько урезанную версию .NET Framework, поэтому

в большинстве случаев от разработчика приложений

http://www.partitek.

под мобильные устройства не требуется лишних дей-

com/ — официальный

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

веб-ресурсразработ-

на десктопные платформы.

чиковописанного

Если с выбором инструмента создания ПО все прак-

встатьеSDK.

тически очевидно, то с инструментами для манипуля-

http://qrcoder.ru/

ций с QR-кодом дела обстоят несколько сложнее. В

— сервисгенерации

.NET Framework нет «нативных» средств для работы с

QR-кодов.

матричными кодировками.

http://www.xakep.

В процессе поиска сторонних библиотек для работы с

ru/magazine/

матричными кодами я столкнулся с веб-ресурсом восточ-

xa/084/056/2.asp

ной компании, занимающейся профессиональной рабо-

— статья«Жукив

той с изображениями и обработкой баркодов (двумерных

полоску» оструктуре

кодов, к коим относится и QR). Результатами своей дея-

штрих-кода.

тельности в виде демонстрационных версий компонент

http://defec.ru

для кодирования/декодирования ряда двумерных пред-

мойресурс, гдеты

ставителей штрихкодов разработчики компании любезно

можешьзадатьво-

делятся с посетителями. SDK доступно для скачивания и

просыиподелиться

содержит библиотеки под разные платформы: Windows,

идеями.

*NIX, Windows Mobile, Symbian и iPhone (Mac OS). Для

 

интересующей нас платформы Windows, а также для

 

Windows Mobile SDK предоставляется вместе с динами-

 

ческой библиотекой (.dll), что позволяет легко использо-

 

вать его в проектах на .NET/VC/VB. Помимо манипуляций

DVD

с QRCode библиотека также умеет работать с DataMatrix

и PDF417. Так что если у тебя возникнет желание рас-

 

ширить свой кругозор и поиграться с другими типами

dvd

кодирования, то все нижеописанные действия в общем

случае подходят и для указанных кодировок.

Надискеприсутству-

Разбираем матрицу

ютисходныекоды

рассмотренного

Рассмотрим общую структуру приложения, которое, как

встатьеприложения

предполагается, будет декодировать QR-код.

совсеминеобходи-

Первую и, пожалуй, самую большую часть исходного

мымибиблиотеками.

XÀÊÅÐ 12 /143/ 10

107

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

CODING

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

F

 

 

 

 

 

 

t

 

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

 

to

 

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

 

 

 

 

 

 

 

 

 

 

 

.

 

 

 

 

 

.c

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

 

-x cha

 

 

 

 

Изображение-пациент, полученное с помощью мобильного телефона

кода занимает описание основного программного класса: определение констант, структурные секции, секции описания функций, предоставляемых сторонней библиотекой. Представление исходных данных в виде картинки описывает структура PTIMAGE.

Структура, описывающая параметры изображения

unsafe public struct PTIMAGE

{

public int dwWidth;// ширина изображения в пикселях public int dwHeight;//высота изображения в пикселях public byte* pBits;//указатель на данные исходного

изображения

public byte* pPalette;// указатель на данные о палитре изображения (1,4,8 бит)

public short wBitsPerPixel; //число бит на пиксель

}

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

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

Следующим этапом будет описание параметров библиотеки декодирования баркодов в структуре PTDECODEPARA:

Структура PTDECODEPARA используется для определения параметров при декодировании баркода на изображении

public unsafe struct PTDECODEPARA

{

public int dwStartX;// начало координаты X в пикселях в окне поиска изображений для декодирования

public int dwStartY; public int dwEndX; public int dwEndY;

public int dwMaxCount;//максимальное количество символов для поиска; если значение равно 0, то ищем все символы };

Манипулируя со значением переменной dwMaxCount, мы получаем возможность управлять производительностью приложения, фокусируя наш «декодировщик» на конкретных областях исходного

QR-код скрывает гораздо больше, чем может показаться на первый взгляд

изображения и избегая функционирования «в холостую». Следующая структура заполняется непосредственно после определения области изображения, в которой находится баркод:

После декодирования структура PTBARCODEINFO содержит баркод с информацией

public unsafe struct PTBARCODEINFO

{

/*координаты четырех углов баркода в пикселях*/ public int dwX1, dwY1;

public int dwX2, dwY2; public int dwX3, dwY3; public int dwX4, dwY4;

public byte* pData; //указатель на буфер, который содержит данные баркода

public int dwDataLen; //длина данных (в байтах) баркода };

Если ты внимательно посмотришь на картинку с QR-кодом, то сразу заметишь три выделяющихся квадратных области — это ориентиры для средств распознавания, своего рода «указатель» программе на то, что среди прочего набора пикселей на картинке присутствует QR-код. Главная функция нашего приложения проста до безобразия, поэтому в полном объеме приводить ее не будем, а сосредоточим внимание на следующих инструкциях:

static void Main(string[] args)

{

PtQRDecodeRegister("12345678901234567890");// использование ключа демонстрационной версии

PtInitImage(ref image); // инициализация структуры изображения

if (OpenFileDlg.FileName != "")

{

FileName = OpenFileDlg.FileName; DecodeQR();

}

}

108

XÀÊÅÐ 12 /143/ 10

Соседние файлы в папке журнал хакер