mł.asp.PawełOlber
biegłyz zakresubadańinformatycz nychLaboratorium Kryminalistyczn egoKomendy Wojewódz k iej PolicjiwOlsztynie pawel.olber @ol.policja.gov.pl
W
ykorzystanie s
kryptów pr
ogramu
EnC
ase
F
orensic
w
k
ryminalistycznych
b
adaniach c
yfrowych
n
ośni ków
d
anych
Streszczenie
Celem niniejszej pracy jest przedstawienie użytkownikowi programu EnCase Forensic składni języka pro
-gramowania EnScript, umożliwiającego tworzenie własnych rozwiązań programistycznych, a także przed-stawienie możliwości jego wykorzystania w kryminalistycznych badaniach cyfrowych nośników danych.
W celu zrozumieniaomawianego zagadnienia opis elementów ww. języka programowania poparty został
praktycznymi, autorskimiprzykładami. Przykładyzamieszczone w niniejszej pracypozwalają na zrozumienie
kodu istniejących już skryptów, zawartych m.in. w tzw. dokumentacji EnCase API. Dokumentacja ta jest najlepszym źródłem pozwalającym na zdobycie szczegółowych informacji o klasach ww. języka progra-mowania, ich składowych i funkcjach. Poza ww. dokumentem, w sieci Internet znajduje się wiele aplikacji
tworzonych przez pasjonatów języka programowania EnScript, które ułatwiają pisaniewłasnych skryptów orazstanowiącenneźródłoinformacjiiinspiracji.Zaletąpoznania ww.językaprogramowania jestmożliwość
tworzenia własnych rozwiązań programistycznych, pozwalających na automatyzację realizowanych zadań
wykonywanych w ramach przeprowadzanych analizśledczych, co jest bardzo istotnym elementem w pracy informatykaśledczego.
Słowa kluczoweEnCase Forensic, EnCase API, EnScript
Wprowadzenie i cel pracy
Niniejsza publikacja zawiera omówienie języka pro
-gramowania EnScript zdefiniowanego w programie EnCase Forensic, który jest jednym z najbardziej ce-nionych naświecie programów z informatyki śledczej
(computer forensic). Przeprowadzone badania
doty-czące ww.językaprogramowania, opartesąw
szcze-gólności na pracy w programie EnCase Forensic, który ma wbudowane własne środowisko programistyczne oraz zawiera skrypty służące do automatyzacji
cza-sochłonnych analiz śledczych. Środowisko progra-mistyczne ww. programu jest bardzo proste i brakuje w nim wielu przydatnych funkcji służących do forma-towania kodu źródłowego. Dlatego też przykładowe
skrypty prezentujące składnię języka EnScript napi
-sane zostaną przy użyciu aplikacji Microsoft Visual
C++ Express skonfigurowanej w sposób umożliwia jący współdziałanie z programem EnCase. Program Microsoft Visual C++ Express pozwala na zachowanie czytelneji przejrzystej struktury tworzonych skryptów, co ułatwia ich analizę i zrozumienie oraz uniknięcie błędów programistycznych. Informacje dotyczące
PROBLEMY KRYMINALISTYKI 288(2) 2015
składni językaprogramowania EnScript zgromadzone
zostaną przede wszystkim w wyniku analizy kodów
źródłowych skryptów,zawartych w tzw. dokumentacji
API programu EnCase Forensic. Ponadto przeprowa-dzona zostanie analiza dostępnych w sieci Internet skryptów, które są tworzone przez pasjonatów ww.
języka programowania.
W pierwszejczęści artykułuprzedstawionezostaną
podstawowe informacje i pojęcia dotyczące języka
programowania EnScript. Następnie przedstawiony zostanie prosty program, który będzie punktem
wyj-ścia do tworzeniabardziej skomplikowanychaplikacji.
W dalszej kolejności wyjaśnione zostaną elementy
składni języka programowania EnScript, w
szczegól-ności podstawowe typy danych, zmienne złożone,
instrukcje sterujące, operacje na zmiennych, a także
zagadnienia dotyczące programowania obiektowego.
Na końcu przedstawionezostaną autorskie rozwiąza
nia programistyczne, powstałe na potrzeby real
izowa-nych opinii kryminalistyczizowa-nych.
Celem starań podjętych przez autora jest omówie
-nie języka programowania EnScript zdefiniowanego w programie EnCase Forensic i przedstawienie jego
możliwości w kryminalistycznych badaniach cyfro-wych nośników danych. Informacje zawarte w publi-kacji powinny byćprzydatne dla osóbzajmującym się informatyką śledcząw tworzeniu autorskich narzędzi analitycznychsłużącychdo automatyzacjiczasochłon nych czynności wykonywanych w trakcie przeprowa-dzanych analiz. Przedmiotowa publikacja wydaje się o tyle istotna, że w resorcie brakuje specjalistycznych szkoleń dotyczącychomawianego zagadnienia.
EnScript - informacje podstawowe
EnScript jest obiektowym językiem programowania opartym naskładnidwóchjęzyków:C++ i Java. Język ten pozwala na automatyzację realizowanych zadań oraz uproszczenie wielu czasochłonnych czynności przeprowadzanych w trakcie wykonywanych analiz śledczych, takich jak np. wyszukiwanie i analizowanie konkretnych typów dokumentów, przetwarzanie oraz ekstrakcja danych zapisanych w różnego rodzaju pli-kach, tworzenie zbiorów zawierających funkcje skrótu itd. Korzystanie z tego języka programowania umoż liwia również przetwarzanie informacji wyselekcjono-wanych w wyniku przeprowadzonej analizy danych, które zostały dodane do zakładek (bookmarks) lub rekordów(records).
EnScript - składnia języka
Rozpoczęcie nauki tworzenia skryptów w języku EnScript wymaga zapoznaniaużytkownikaz podstawo-wymizagadnieniami orazterminologią dotyczącą pro-gramowania.W artykule omówione zostaną również: struktura programu, przebieg przetwarzania składo wych oraz funkcji programu. Poznanie ww. zagadnień jest bardzo istotne, ponieważ ułatwi użytkownikowi zrozumienie kodu źródłowegotworzonych przez niego aplikacji oraz pozwoli na skuteczną analizę istnieją cych już skryptów, m.in. domyślnie zdefiniowanych w programie EnCase orazdostępnychw sieci Internet.
Białeznaki
Białeznaki,tj. spacje,tabulatory oraz znaczniki no -wej linii, nie mająznaczenia w kodzie źródłowym isą ignorowane przez kompilator - program wykonujący kompilację, czyli tłumaczenie kodu źródłowego na językmaszynowy.
Komentarze
Dowolny fragment kodu źródłowego programu
może być objęty komentarzem. Komentarz jest całkowicie ignorowany przez kompilator, natomiast może byćprzydatny dla piszącego iczytającego kod. Komentarze stosowane są w celu opisu, wyjaśnienia pewnych fragmentów kodu programu, oddzielenia jednejczęści kodu od drugiej oraz oznaczania funkcji. Wjęzyku EnScript istniejądwadostępnesposoby ko-mentowania kodu: liniowe oraz blokowe.
Przykład: class MainClass {
void Main(CaseClass c) {
// Przykład komentarza li ni owego.
/*
Przykład komentarza blokowego,
którym można objąć wiel e linii .
*/
} }
Dyrektywainclude
Wjęzyku EnScript zapis inc/ude to tzw. dyrektywa - informacja o dołączeniu do kompilowanego pliku źródłowego zawartości wskazanego pliku o rozsze-rzeniu enscript,określanegojako biblioteka. Biblioteki zawierająfunkcje,z których można korzystaćw pliku źródłowym. Nazwę pliku podajesiębez rozszerzenia.
Przykład:
This script is a modification of "Sweep Enterprise" of EnCase V4.
Report alI bugs and queries to
techni cal s uppor t @gui dancesof t war e . com
////////////////////////////////////////////
*/
inclu de "GSI_Basi c"
include "GSI_SweepCaseLib"
include "GSI_Defa ultModules"
Dyrektywa typelib
Wjęzyku EnScript zapis typelib umożliwia dołącze
nie do kompilowanego pliku źródłowego zawartości
wskazanego pliku, tzw. biblioteki pochodzącej z
ze-wnętrznejaplikacji, np. programów z pakietu Microsoft Office.
Przykład:
typelib Excel "Exce l.Sheet"
typelib Scripting "Scrip ting. Fi leSyst emObject"
#ifdef Excel class MainClass { void Main() { SystemClass::ClearConsole()j CreateExcel()j } void CreateExcel() { Excel::Application apPj
if (app.Create(» { app.SetVisible(t r ue)j
Excel::Workbooks books
=
app.Workbooks()j Excel::Workbook book=
books.Add()j Excel::Sheets sheets=
book.Worksheets()j Excel: :Wordsheet sheet = Excel: :Worksheet ~::TypeCast ( s heet s .lt em( l » j Excel::Range cells
=
sheet.Cells()j AddTable(cells)jAddPieChart(sheet)j }
Konsola
Konsola jest w rzeczywistości plikiem, którego za-wartość wyświetlanajest w oknie podglądu programu EnCase Forensic. Konsola dostępna jest po wciśnię ciuzakładki .Console"(dot. V6)lub zapomocąmenu: View -> Console (dot. V7) i umożliwia wyświetlanie wszelkiego rodzaju komunikatów oraz innych treści, np. informacji o przebiegudziałan iaprogramu. W celu wyświetlenia komunikatu w konsoli należy posłużyć siępoleceniem WriteUne().
Pierwszy program
Tradycyjne książki o programowaniu zaczynają naukęprogramowania od przedstawienia aplikacji wy-świetlającej w konsoli lub na ekranie monitora zdanie:
"Hello Wor/d".Tradycja ta zostanie zachowana także i w niniejszej publikacji. Pierwszy program będzie punktem wyjściado bardziejzłożonychaplikacji, które pozwolą zrozumieć składnię języka EnScript.
Przykład: class MainClass { void Main(CaseClass c) { Console.WriteLine("Hello Worl d") ; } } Wynik:
I
Hello WorldGłównaklasa programu
Program napisany w języku EnScript jest zbiorem zmiennych, definicji i wywołań funkcji. Każdy skrypt utworzony w programie EnCase ma klasę o nazwie MainCIass, wewnątrzktórej znajduje sięfunkcja Main, przyjmującajako parametr zmienną typu CaseClass, która jest odpowiednikiem sprawy utworzonej przez użytkownika programu. Wewnątrz klasy głównej MainClass definiowane są pozostałe klasy i funkcje. Po uruchomieniu skryptu program EnCase lokalizuje obiekt typu MainClass i wywołuje jego konstruktor. Zagadnienia dotyczące konstruktorów przedstawione zostaną w dalszej części publikacji. Następnie
ww
.
obiektwywołuje funkcjęMain,która poprzedzona jest słowemkluczowym void. Oznacza to,żefunkcja ta nie zwraca żadnych danych. Na koniec program EnCase uruchamia destruktor klasy MainClass i ostatecznie usuwa obiekt klasy głównej. W tym miejscu program kończy działanie.
Pojęciezmiennej ipodstawowe typy danych Zmienna (variable) to miejsce w pamięci opera-cyjnej komputera przechowujące pojedynczą wartość określonego typu. Każda zmienna ma nazwę, dzięki której można siędo niejodwoływać. Przed pierwszym użyciem zmienną należy zadeklarować, a więc po-informować kompilator, że pod taką nazwą kryje się PROBLEMY KRYMINALISTYKI 288(2) 2015
zmienna danego typu. Składnia deklaracji zmiennej wygląda następująco:
I
typ nazwa_zmiennej=
wartość_zmiennej;
Typokreślarodzaj informacji,jakiemożna
przecho-wywaćw zmiennej.Mogą to byćnp. liczby całkowite,
rzeczywiste, tekst (czyli łańcuchy znaków, strings). Nazwa zmiennejpowinna dobrze określaćjej znacze-nieispełniaćpewne kryteria.Otonajważniejszez nich: • nazwa zmiennej powinna być słowem lub
skró-tem,określającymjej przeznaczenie
• nazwamoże się składaćzmałychiwielkich liter, atakżecyfr i znakupodkreślenia. Należy pamię tać, że nazwa zmiennej nie może zaczynać się
od cyfry. W odróżnieniu od innychjęzyków pro-gramowania w nazwie zmiennej można używać
znaków narodowych, np. literćczyŹ.
JęzykEnScript obsługuje różnetypy danych natyw-nie,co oznacza,żekonwersjepomiędzyróżnymi typa-mi danych wykonywane sąautomatycznie orazużycie
danej określonego typu dopuszczalne jest w każdym
kontekście. Przykład: class MainClass {
void Main(CaseClass c) {
II
deklaracja zmiennej "i"II
przypisanie wartości 1 do zmiennej int i=
1;II
wyświetlenie zawartości zmiennej "i"Console.WriteLine("i
= "
+ i);II
dodanie wartości 1 do uprzednioII
zdefiniowanej zmiennej i=
i + 1; Console.WriteLine("i=
"
+ i); } } Wynik:Podstawowe typy danych
Typy danych określają sposób użycia parruęci w programie. Określając typ danych, przekazuje się
kompilatorowi informację,jakutworzyć określony frag-ment pamięci, atakżew jaki sposób wykonać na nim operacje. Dane różnych typów różnią się szybkością
działania,rozmiarem zajmowanej pamięciioczywiście
funkcjonalnością, np. są dane, które wolno mnożyć
przez siebie, ale i takie, dla których operacja mnożenia
nie istnieje - choćbyteksty.
char
Zmienna typu char przechowuje jeden znak. Do zmiennejtego typu można przypisaćznaki UNICOOE
o kodach od O do 65535. Zmienne typu char mogą
być przypisane do zmiennych typu całkowitego int i odwrotnie, zmienne typu całkowitego mogą być
przypisane do zmiennych znakowych. W przypadk u
takiego zabieguEnScriptdokonujekonwersji znaków
zgodnie z kodowaniem ASCII. W kodzieASCII mała
litera "a" ma przypisanąwartość97.Gdy do zmiennej
typu char zostajeprzypisanyznak,to wrzeczywistości
jest on liczbą z zakresu od O do 255. Należy jednak
zdawać sobie sprawę z różn icy pomiędzy wartością
a znakiem,np.:5i ,,5" nie jest tym samym,ponieważ5
jestwartością,natomiast,,5"jest znakiemi mawartość
53, tak jak w przypadku litery"a", która mawartość97.
Przykład:
clas s Ma i nClas s {
voi d Mai n(CaseClass c) {
II
Przypisanie liczby 82 do zmiennej intint i
=
82;II
Wyświetlenie zawartości zmiennej 'i'Cons ol e.Wr it eLin e ("i = " + i);
II
Przypisanie zmiennej 'i' do zmiennejII
typu charchar a
=
i;II
Wyświetlenie zawartości zmiennej 'a' Console. WriteL i ne("a=
"
+ a);II
Przypisanie znaku do zmiennej typu charchar b
=
'v';II
Wyświetlenie zawartości zmiennej 'b' Console.WriteLine("b = " + b);II
Przypisanie zmiennej 'b' do zmiennej 'j'int j = b;
II
Wyświetlenie zawartości zmiennej 'j' Console. WriteLine("j=
"
+ j) ; } } Wynik: i 82 a=
R b=
v j = 118 StringZmienna typu String przechowuje ciągi znaków
(tekst), na których można wykonywać wiele operacji.
Ciągiznaków mogą byćzesobą łączone zapomocą
operatora,,+".
Przykład:
class MainCl ass {
void Main(Case Cla s s c) {
II
Usunięcie zawartości konsoli Sys t emC l ass: :Cl ea rConso le ( ) ;II
Przypisanie wartoścido zmiennej 51 St r i ng 51 = "Hel lo";II
Przypisanie wartoścido zmiennej s2 St r i ng s2=
"
World";II
Zmienna 51 uzyskuje wartość "Hello World"51 = 51 + 52;
II
Zmienna 51 uzyskuje wartość "Hello World." 51=
51 + ".";II
Przejście do nowego wierszasI =sI + '\n';
II
Wyświetlenie wyników konsoliConsole.Write(sl);
}
}
Wynik:
I
Hello Wor Id.Ciągi znaków mogą zawierać znaki specjalne.
W celu wykorzystaniaznaków specjalnych w tekście
należy posłużyćsięznakiemukośnika(backslash).Do
grupy znaków specjalnych zaliczamy: tabulator, uko
-śnik, pojedynczy cudzysłów, znak końcalinii.
Przykład:
class MainClass {
void Main(CaseClass c) {
SystemClass::ClearConsole();
String 51
=
"Tabul at or \t, ukośnik \\, ~pojedynczy cudzys łów \", ~
znak końca linii. \n";
Console.Write(5 1) ;
} }
Wynik:
Tabulator , ukośnik \, pojedynczy cudzysłów
", znak końca lini i
Istnieje również możliwość umieszczeniawtekście
dodatkowych znaków specjalnychz tablicyUNICOOE,
np. znaku towarowego ®. Znak ten należy zapisać
z ukośnikiemw postaci szesnastkowe]'.
Tablica UNICODE dostępna jest m.in. pod adresem:
Przykład:
class MainClass {
void Main(CaseClass c) { SystemClass::ClearConsole()j
String si
=
"To jest znak towarowy: \xeeAE"j Console.Write(sl)jString s2
=
"Litera alfabetu rosyjskiego: ~\xe414"j Console.Write(s2)j
} }
Wynik:
To jest znak towarowy: ~ Litera alfabetu rosyjskiego:
A
Ponieważ wszystkie znaki w cudzysłowie są
zna-czące, w tym również białeznaki, niemożna wstawić
nowego wiersza wśrodku łańcucha.
Przykład:
class MainClass {
void Main(CaseClass c) { SystemClass::ClearConsole()j
II
Nieprawidłowy sposóbsi
=
"To jest bardzo długi tekst,którego nie można zapisywać w ten sposób. Próba uruchomienia skryptu zakończy się błędem" j
} }
Abypołączyćbardzodługie ciągiznaków, wystarczy
umieścić je w cudzysłowie, jeden pod drugim. Ciągi
znaków zostaną połączone w czasie kompilacji
pro-gramu. W przypadku bardzo długich ciągów znaków
nie należy używać operatora łączenia ,,+", ponieważ
spowoduje to niepotrzebne wydłużenie czasu
kompi-lacji programu.
Przykład:
class MainClass {
void Main(CaseClass c) { SystemClass::ClearConsole()j
II
Prawidłowe połączenie bardzo długich znakówsi
=
"To jest bardz o długi tekst, ""kt ór y został zapisany prawidłowo. \n"
"Ur uchomi enie skryptu zakończy się sukcesem."j Console.WriteLine(sl)j
}
}
PROBLEMY KRYMINALISTYKI 288(2) 2015
Wynik:
To jest bardzo długi tekst, który został zapisany prawidłowo.
Uruchomienie skryptu zakończy się sukcesem.
Ciągi znaków mogą być traktowane jako
tabli-ca znaków i adresowane indywidualnie. Uwaga:
Indeksowanie tablicy odbywasięzawsze odO.Ostatni element ma indeks równy rozmiarowi tablicy - 1.
Przykład: class MainClass { void Main(CaseClass c) { SystemClass::ClearConsole()j String s
=
"12345678ge"j Console.Writeline("Pi erwotny ci ąg: " + s)jII
Wyświetlenie liczby 1Console.WriteLine("Pi erwszy znak ciągu: " + ~ s(e]
=
'X'jII
Pusta liniaConsole.WriteLine(" ") j
II
Wstawienie znaku·
x·
na pierwszą pozycję s(e]=
·x·
jII
s=
X2345678geConsole.WriteLine("Nowy ciąg: " + sj ;
Console.WriteLine("Pi erwot ny ci ą g: " + s)j
} }
Wynik:
Pierwotny ciąg: 12345678ge Pierwszy znak ciągu: 1 Nowy ciąg: X2345678ge Pierwszy znak ciągu: X
Numeryczne typy danych
W języku EnScript dostępnych jest siedem typów
numerycznych. Typy numeryczne mają stały rozmiar,
niezależnie od procesora i platformy. Część typów
numerycznych ma podobne nazwy, różnią się one
jedynie pierwszą literąu. Wjęzyku EnScript jest to tak
zwany modyfikator, przy użyciu którego można nieco
wpływać na zakres danych, które można zapisywać
w zmiennych. Modyfikator to nic innego jakokreślenie
różnych odmian jednego typu. Modyfikator u
okre-śla, że dany typ reprezentuje jedynie dane dodatnie.
Wszystkie numeryczne typy danych języka EnScript
zostały przedstawione w postaci tabelarycznej i
po-sortowane wg rozmiaru danych, jakie mogą
przecho-wywać(tab. 1).
Tabela 1 Zestawienie numerycznych typów danych
_.
Typ RozJ!ltar(B) Min. wartość Max. wartość
Short 2 -32768 32767 Ushort 2 O 65535 Int 4 -2147483648 2147483647 Uint 4 O 4294967295 Long 8 -9223372032559808513 9223372032559808512 Ulong 8 O 18446744065119617025
Double 8 -1.79*1E+308 1.79*1E+308
Przykład: class MainClass {
void Main(CaseClass c) {
II
Usunięcie zawartości konsoli SystemClass::ClearConsole()jII
Zmienna typu shortshort short_min_value -32768j
short short_max_value
=
32767jConsole. WriteLine("Min. wart. zmiennej typu (j)
'short' wynosi: 00 + short_min_value)j
Console .WriteLine(ooMax. wart. zmiennej typu (j)
'short' wynosi: 00 + short_max_value)j
Console.WriteLine(OO - - - --- - -- - - -- -OO)j
II
Zmienna typu ushort ushort ushort_min_value=
ej ushort ushort_max_value=
65535jConsole.WriteLine("Mi n. wart. zmienn ej typu (j)
'us hort' wynosi: " + ushort_min_value)j
Console.WriteLine(OOMax. wart. zmi ennej typu (j)
'ushort' wynosi: " + ushort_max_value)j
Console.WriteLine("--- - -- - --- --- - - --- - - - - OO)j
II
Zmienna typu intint int_min_value -2147483648j
int int_max_value
=
2147483647jConsole.WriteLine(OO Mi n. wart . zmiennej typu (j)
'int' wynosi: " + int_min_value)j
Console.WriteLine(OO Max. wart. zmiennej typu (j)
'int' wynosi: 00 + int_max_value)j
Console.WriteLine(" - -- ---- - - -- - --- - - --- - -- -")j
II
Zmienna typu unit unit unit_min_value ejunit unit_max_value
=
4294967295jConsole. WriteLine("Min. wart . zmiennej typu (j)
'unit' wynosi : " + unit_min_value)j
Console.WriteLine("Max . wart. zmiennej typu (j)
'uni t ' wynosi : 00 + unit_max_value)j
Console.WriteLine(OO--- -- - - -- -- - - - ---- -- --OO)j
Wynik:
Min. wart. zmiennej typu 'shorf' wynosi: -32768 Max. wart. zmiennej typu 'short' wynosi: 32767 Min. wart. zmiennej typu 'ushort' wynosi: e Max. wart. zmiennej typu 'ushort' wynosi: 65535 Min. wart. zmiennej typu 'int' wynosi:
-2147483648
Max. wart. zmiennej typu 'int' wynosi: 2147483647
Min. wart. zmiennej typu 'uint' wynosi: e Max. wart. zmiennej typu 'uint' wynosi: 4294967295
void
Ten specjalny, tzw. pusty, typ danych używanyjest do wskazania,żefunkcja nie zwracażadnegowyniku.
Przykładzastosowania ww. typu został również przed-stawiony podczas omawiania funkcji.
Przykład:
class MainClass {
void Main(CaseClass c) {
II
Usunięcie zawartości konsoli SystemClass::ClearConsole()jII
Wywołanie funkcji NoData()jNoData()j
II
Wywołanie funkcji ReturnData()II
i przypisanie zwróconej wartości doII
zmiennej 'text'String test
=
ReturnData()j Console.WriteLine(text)j}
} }
Console.WriteLine(sl)j
II
II
wartościFunkcja typu void - nie zwraca żadnych void NoDataO {Console.WriteLine(OO Funkcj a NoReturn() nie (j) zwraca żad n ej wartoś ci . ") j
II
Funkcja typu String - zwraca tekstString ReturnData(){
String msg
=
"Funkcja ReturnData() zwraca ~ wartość zmiennej typu String.";return msg; }
}
Wynik:
Funkcja NoReturn() nie zwraca żadnej wartości.
Funkcja ReturnData() zwraca wartość zmiennej typu String.
variant
Zmienna typuvariantprzechowuje dane dowolnego typu. Zawiera również odniesienie do obiektu repre-zentującego przypisaną wartość, który jest dostępny zapomocąfunkcji TypeO.
Przykład: class MainClass {
void Main(CaseClass c) {
II
Usunięcie zawartości konsoliSystemClass::ClearConsole();
II
Deklaracja zmiennych typu variantvariant vl
=
"Witaj", v2=
lee,
v3=
2.5;Console.WriteLine("Zmi enna typu " ~
+ vl. TypeO .NameO + " " + vl); Console. WriteLine("Zmienna typu " ~
+ v2.TypeO.NameO + " " + v2); Console.WriteLine("Zmi enna typu " ~
+ v3. TypeO . Name O + " " + v3);
}
}
Wynik:
Zmienna typu String
=
Witaj Zmienna typu int =lee
Zmienna typu doubLe
=
2,5bool
Najprostszym, ale bardzoczęsto używanym typem danych jest typ logiczny. Do jegookreślenia służy sło wo kluczowe bool(skrót od Boolean - boole'owski, logiczny). Do zmiennej typu logicznego możemy
przy-pisać wyłącznie wartośćtrue(1) lubfalse (O).Zmienną
tego typu najczęściej stosuje się do określenia, czy jest coś włączone czy wyłączone, prawdziwe lub fałszywe.
PROBLEMY KRYMINALISTYKI 288(2) 2015
Przykład: class MainClass {
II
Metoda, która zmienia wartośćII
zmiennej 'b' na false void Zmien(bool &b) {b
=
false;}
void Main() {
II
Klasa MainII
Usunięcie zawartości konsoliSystemClass::ClearConsole();
II
Przypisanie wartości 'true' do zmiennej b bool b=
true;Console. WriteLine(" Wa rt o ś ć zmniennej ~
logicznej b
=
"
+ b);Zmien(b);
II
Zmiana wartości zmiennej 'b' Console.WriteLine(" Wa rto ś ć zmniennej b ~po zmianie: " + b);
II
Jeżeli warunek jest prawdziwy zostanieII
wyświetlony komunikati f (b
==
9) {Console.WriteLine("War unek 'b
=
e'
jest ~prawdziwy") ; }
} }
Wynik:
Wartość zmiennej logicznej b = 1
Wartość zmiennej b po zmianie:
e
Warunek 'b=
e' jest prawdziwyZmiennezłożone
Typ wyliczeniowy
Wyliczeniowy typ danych umożliwia powiązanie
nazw z liczbami. Wyliczenie deklaruje sięza pomocą słowa kluczowego enum (pochodzącego zjęzyka C),
które automatycznie numeruje listę stałych, nadając
imwartości:O, 1,2 itd.Deklaracja typu wyliczeniowe-go przypomina deklaracjęstruktury.
I
enum nazwa_typu (staŁa_l
[ =wartość],
...JDomyślna wartość pierwszej stałej w zbiorze typu wyliczeniowego wynosi O. Wartość każdej następnej stałej przyjmujewartość większąo 1 odwartości stałej poprzedzającej. Każdazestałych może zostać zdefi-niowana z określoną wartością. Jeżeli któraśz
warto-ści nie zostanie podana, to zostanie ona wyliczona na podstawie wartościpoprzedniej.
Nazwa stałej: Jeden
Nazwa stałej: Dwa
Nazwa stałej: Trzy
Nazwa stałej: Cztery
Nazwa stałej: Pięć
Wynik: } }
Console.WriteLine("Nazwa stałej: " ~
+ LiczbY::SourceText(28»j
Console.WriteLine("Nazwa stałej: " ~
+ Liczby::SourceText(21»j
Console .WriteLine("Nazwa stałej: " ~
+ Liczby::SourceText(38»j
=
8=
1 28 21 38II
WartośćII
WartośćII
WartośćII
Wartość =II
Wartość =II
Deklaracja typu wyliczeniowegoenum Liczby {
II
Nazwy stałych Jeden, Dwa, Trzy = 28, Cztery, Pięć = Trzy + 18 } Przykład: void Main(CaseClass c) {II
Usunięcie zawartości konsoliSystemClass::ClearConsole()j class MainClass { Console.WriteLine(" Wa rtoś ć = " ~ + Liczby::Jeden)j Console.WriteLine(" Wa rt o ś ć = " ~ + Liczby: :Dwa)j Console.WriteLine(" Wa rt o ś ć = " ~ + Liczby:: Trzy) j
Console. WriteLine("Wartość = " ~
+ Liczby::CzterY)j
Console.WriteLine(" Wa rto ś ć = " ~
+ Liczby::Pięć)j
Tablice
Tablica jest strukturą złożoną z określonej liczby elementów tego samego typu. Wszystkie elementy tablicy umieszczanesą w pamięci komputera razem w jednym miejscu i do każdego elementu można odwołać się za pomocą nazwy tablicy oraz indeksu
określającegonumer danego elementu.
} } Wynik: Wartość = 8 Wartość =1 Wartość = 28 Wartość
=
21 Wartość = 38Tablicę tworzy się za pomocą słowa kluczowe-go typedef, po którym określa się rodzaj danych przechowywanych w tablicy. Po utworzeniu tablicy
można zadeklarować oraz zainicjować zmienną typu tablicowego.
typedef typ_tabLicy StringArrayj Nazwę stałejtypu wyliczeniowegomożna uzyskać
poprzez jej wartość. W tym celu należy posłużyć się statyczną funkcjąo nazwie souroetexu).
Przykład: Przykład: class MainClass { void Main(CaseClass c) { class MainClass { enum Liczby { Jeden, Dwa, Trzy
=
28, Cztery, Pięć=
Trzy + 18 }II
Wartość = 8II
Wartość=
1II
Wartość = 28II
Wartość 21II
Wartość =38II
Utworzenie dwóch tablic typedef String[] StringArrayjtypedef int[ ] IntArrayj
void Main(CaseClass c) {
II
Deklaracja zmniennej tablicowej 'nazwisko'StringArray nazwisko(3)j
I
I
Przypisanie wartości nazwisko[8] "Kowalski"j nazwisko[l] = "Nowak"j nazwisko[2] = "Mikulski"jII
Us u n i ę c i e zawartości konsoli SystemClass::ClearConsole()jConsole.WriteLine("Nazwa stałej: u ~
+ Liczby::SourceText(8»j
Console.WriteLine("Nazwa st a ł ej : " ~
+ Liczby::SourceText(l»j
II
Deklaracja zmniennej tablicowej 'l i czba'IntArray liczba(3)j
II
Przypisanie wartościliczba[8] = 1j
liczba [1] 2j
•
"
II
Wyświetlenie zawartości tablicy foreach (String,s in nazwisko){Console. Writeline (s); , }
Console.WriteLinę(U lic zba [ 2 ] u + liczba[il); }
}
Wynik:
o
1 25
Istnieje możliwość inicjalizacji tablicy
w
momencie jej deklaracji. Po nazwie tablicy należy w nawiasach klamrowych ({}) podać wariośĆ kolęjnych elementów tablicy. Na podstawie liczbywartości inicjalizujących ko.mpilatorautomatyczhiezdefiniuje rozmiar,tablicy.Przy/cład:
class MainClass {
II
Utworienie tablicytypedef St r i ng[ ] StringArray';
void Main(CaseClass c) {
II Deklaracja zmniennej tablicowej
II
Inicjalizacja zmniennejStringArray nazwisko,{UKowalskiuJ "NowakuJ '~ UMikulskiu; } '
II Wyświetlenie zawartościtablicy fóreach(Strings in nazwisko) { ,Console. WriteLine( s); " } } } Wynik: Tablice wielowymiarowe
Wjęzyku EnScripfmożna utworzyć tablicęznacznie'
bardziejzłożoną- naprzykład tablicę,dwuwymlarową,
którą można grafi.cznią zobrazować IN następiJjący
~~~~ .
PROBL.ENI'YKRYMINALISTYKI28~(21.2015
Tablip§l, dwuwymiarowa zostanie utworzona za
pomocą instl1lkcjisterującej foreach, którazostahte
ornówiońa w dalszej części, pracy: Rbtmia"rtablicy
dwuwymiaroweiokreślany jest przez'liczbę' wiersży
i kolumn. " '
Przykład:
class MainC1ass {
II
Utworzenie tablicytypedef int[ l IntArray;
II
Utworzenie zmienhej tablicowej 'multiArray'typedef IntArra~[lmultiArray;
void Maii1(CaseClass c) {
II
Określenie rozmiaru tabel i multiArray m(2);II
Utworzenie,trzech tabel, kolejno wkażdejII
'
komórce tabeli 'mul t i Ar r ay 'II Wynik: powstanie tablicy dwuwymiarowej
foreach (IntArraya in m) ,{ a,
=
new IntArray(2); "} " '
II Inicjalizacja tabeli dwuwymiarowej
m[e] [e] = '1 ; m[e][l] ='2; m[l][e] = 3; m[l][l] == 4; int Index = ej drugiIndex= e;
Il ,Wyświetlęnie zawartoŚci tabeli foreach (IntArray a in,m) {
,I i'ldex =e;
foreach (int i in a)
Cóns~le.WriteLine C\tm [ U + Index + U][U <p. + drugiIndex + U] = U+
i);
drugiIhdex++~ } Index++; '} } , Wynik: 23Przykład:
while (i< le) {
I
I
Sprawdzenie warunkuint i
=
ejII
Deklaracja zmiennej 'i'class MainClass { void Main(CaseClass c) {
II
Instrukcja Wynik: Console.Write(i + " n) ; i++j } } }(warunek) zwróci wartośćfa/se. Składnia
ww.
instrukcji jestnastępująca:I
whiLe (warunek) instrukcjaInstrukcjesterujące
Wkażdym językuprogramowaniaistniejąinstrukcje pozwalającenasterowanie wykonywaniem programu. Instrukcje wykorzystuje sięprzy podejmowaniudecy-zji. Koniecznośćstosowania instrukcji wynikastąd,.że kodowane algorytmy tylko w prostychprzypadkachsą czysto sekwencyjne, wykonywane linia po linii w
kolej-ności ich występowania. Bardzo często kolejne kroki
algorytmusą zależneodspełnieniapewnego warunku lub kilku warunków.
Instrukcja warunkowaif
Instrukcja jfpozwala wykonać kod programu tylko wtedy, gdyspełnionyjestokreślonywarunek.Działanie
ww.instrukcji sprowadzasię więcdo sprawdzenia wa-runku i,jeśli zostanie stwierdzona jego prawdziwość, wykonania wskazanego bloku kodu.Dziękipewnej mo-dyfikacji instrukcji jfmożliwejest określenie poleceń, które zostaną wykonane, gdy warunek nie zostanie spełniony. Taką zmodyfikowaną instrukcjęwarunkową
określa sięjako jf•••e/s.e. Najprostsza forma instrukcji
ifwygląda następująco:
Przykład:
class MainClass {
void Main(CaseClass c) {
I
I
Deklara cj a zmiennej 'a'int s
=
2;II
Dekl aracj a zmiennej 's'String s
=
"Wi t aj";Instrukcjado ••• while
Instrukcja do... whi/e jest modyfikacją
ww.
pętliwhi/e.Różnica to moment sprawdzania warunku pętli
- wpętli
white,
warunek jest sprawdzany napoczątku, w pętlido... while - nakońcu. Pętlado..,whj/e wyko-na zawsze co wyko-najmniej jeden przebieg. SkładniawW.instrukcji jestnastępująca:
II
Je ś l i 'a' wykonaj ins t ru k c j ęi f (a)
console'. WriteLine("Wartość zmiennej 4)
'a' równa się 2") ;
II
Jeśli 's' wykonaj instruk cję i f (s) Console,WriteLine(s)j Przykład: class MainClass { void Main(CaseClass c) { Console.Write(i + " O); i--j . if (a==
3)II
Jeśli 'a'=
3 Console.WriteLine(s);else { I I w przeciwnym razi e Console.WriteLine(" Wartoś ć zmiennej 4)
'a' jest rói na od 3") ; } } } int i
=
lej do { } while (i >e);II
Deklaracja zmiennej 'i'I
I
Instrukcja II Sprawd zenie warunku Wynik:Instrukcjawhile
Instrukcja whilejest blokiem instrukcji, które wyko-nywane są aż do momentu, gdy wyrażenie kontrolne
. }
}
Instrukcja for
Instrukcja for łączy w sobie trzy działania pętli: inicjalizację (poprzedzającą pierwszą iterację), spraw-dzenie warunku oraz zmianę wartości. Pierwsza instrukcja to inicjalizacja zmiennej kontrolującej wyko-nywanie pętli. Druga instrukcja to sprawdzenie warun-ku. Trzecia instrukcja to akcja - zazwyczaj umieszcza
się tu inkrementację (++) albo dekrementację (--)
zmiennej kontrolującej pętle. Składnia ww. instrukcji jest następująca:
for (inicjaLizacja; warunek; krok) instrukcja; Przykład: class MainClass { void Main(CaseClass c) { for (i nt i
=
0; i < 10; i++) { Console.Write(i + "") ; II Instrukcja } } } Wynik:I
e
12 3 4 S 6 7 8 9 InstrukcjaforeachInstrukcja foreach pozwala na sekwencyjne
prze-glądanie różnych zbiorów danych, np.: tablic, list.
Składnia ww. instrukcji jestnastępująca:
foreach (typ_eLementu nazwa in koLekcja) instrukcja
Przykład:
class MainClass {
enum Tydzień { II Wyliczeniowy typ danych
Poniedziałek = 1; Wtorek, Środa, Czwartek, Piątek, Sobota, Niedziela } void Main(CaseClass c) {
foreach (Tydzień d) { II Pętla foreach Console.WriteLine(Tydzień::SourceText(d)~ + Ił
=
Ił + d)j } } } PROBLEMY KRYMINALISTYKI 288(2) 2015 Wynik: Poniedziałek=
1 Wtorek=
2 Środa=
3 Czwartek=
4 Piątek=
S Sobota = 6 Niedziela=
7 InstrukcjaforaliInstrukcja foralI pozwala na sekwencyjne przeglą
danieróżnychzbiorów danych,podobnie jak instrukcja
foreach. Różnica pomiędzy
ww
.
instrukcjamiwystępu je podczas przetwarzania zbiorów danych w postaci struktury drzewa, które w języku programowania EnScriptsą obiektami NodeClass. DziałanieinstrukcjiforalI zostanie przedstawione w dalszej części pracy, podczas omawiania różnic w języku EnScript zdefi-niowanego w wersji 6 i 7 programu EnCase.Składnia
instrukcji foralI jest następująca:
foraLL (typ_eLementu nazwa in kpLekcja) instrukcja
Instrukcje:break, continue
Wewnątrz dowolnej konstrukcji tworzącej pętlę,
można sterowaćjej przebiegiem za pomocąinstrukcji
break i continue. Instrukcja break powoduje opusz-czenie pętli, bez wykonywania pozostałych zawar-tych w niej instrukcji. Natomiast instrukcja continue zatrzymuje wykonanie aktualnej iteracji, powodując
powrót do początku pętli w celu rozpoczęcia nowej iteracji. PrzYk,ład: class MainClass { void Main(CaseClass c) { for (i nt i = 1; i < 11; i++) { Console.WriteLine(i); if (i
==
4) {Console.WriteLine("Zat r zymani e bie~ącej ~
iteracji i powrót do początku") ;
continue;
}
if (i
==
6) {Console.WriteLine(" Pęt l a została ~
przerwana i dalsze cyfry: 7,8,9,10 ~
nie zostaną wyświetlone") ;
break; } } } } 25
Operacje na zmiennych
Operacje na zmiennych dokonywane są przy uży
cłuoperatorów. Operator działa na jednym lub kilku
argumentach, a wynikiem jego działaniajest zupełnie
nowawartość:Argumentymają inną postać niż zwykłe
wywołaniafunkcji, alerezultat jest wobu przypadkach
taki sam. Operatory wjęzyku EnScript można
podzie-lićna dwie grupy zewzględunaliczbęargumentów, na których działają. Wyróżnia się więc operatory unarne
- wymagające jednego argumentu - oraz binarne
-wymagającedwóch.arqurrtentów,
Operatoryuilarne
Operatory unarne występujące w języku progra-mowania EnScript, przedstawione zostanąw formie tabeli. Regułąjest, żeoperatory te znajdują się przed
wyrażeniem. Wyjątek stanowią opęratory ,,++" i ,,__", które również mogą występowaćpowyrażeniu.
Wynik: iteracji i powrótj:l() Wynik:
I
Zmienna 'liczba' ,4 Przykład: class MainClass { void Main(Casetlass c) { int liczba = 4; switch( l i czba) {case
e:
Console.Write("Zmi enna ma wartość:e"
);
break; case 1: C6nsol~.Write(" Zm i e nn ama wartość: 1") ; break; case 2: Console.Write("Zmi enna
ma wartość: 2") ; break; case 3: Console.Write("Zmi enna
ma wartość: 3") ; break;
~a s e 4: C6nsole.Write("Zmi enna ma wartość: 4") ; b r ~ a k ; } } } 'liczba' <Jj 'liczba' <Jj 'liczba' <Jj 'liczba' <) 'liczba' <Jj
Tabela 2 Zestawienieoperatorówunarnych
Operator Qpi~
.
--New' Tworzenienowego~obiektu
typeofO Określenie typu,obiektu
! Negacja logiczna - zwracazanegowaną.
wę.rtąśę WYr~eni~ .
", "',,' !, ++ Inkrementacja - zwięksiawartość
zmiennej
Dekrementacja - zmniejszawartość
zmiennej
-
wyrażeniaUnarńyminus-służydo zmianyinaku~. Negacja bitowa - zwracazmienną
z zanegowanymibitami Operatory binarne
Operatory binarne występujące w języku proqra-mowania EnScript, również przedstawione zostaną w formie tabeli. Operatory binarne występują pomię
dzy wyrażeniami. Operatory binarne można podzielić
na operatory: arytmetyczne, bitowe, logiczne, relacji, przypisania oraz zasięgu.
Tabela 3 Zestawienie operatorówzasięgu
'Operator
."
OpisDereterencla,czyliwyłuskanie,uzyskanie ,dostępu dąpe'v'łnej ~~~C?$.9i ' .
.
.
Służydouzyskaniadostępudo funkcji..
Tabela 4 Zestawienie operatorów arytmetycznych Operator I' Opis + Dodawanie
-
Odejmowanie * Mnożenie / Dzielenie% Operator reszty z dzielenia
Tabela 5 Zestawienie operatorów bitowych
Operator Opis
« Przesunięciebitowe w lewo
» Przesunięciebitowe w prawo
&
Iloczyn bitowy1\ Różnicabitowa
1 Suma bitowa
Tabela 6 Zestawienie operatorów logicznych
Operator Opis
&&
Iloczyn logiczny II Suma logicznaTabela 7 Zestawienie operatorów relacji
Operator Opis
< Oznacza: mniejsze od ...
> Oznacza:większeod ...
<= Oznacza: mniejsze lub równe z... >= Oznacza:większelub równe z...
--
Oznacza: równe z...1= Oznacza:różneod ...
Tabela 8 Zestawienie operatorów przypisania
Operator Opis
= Przypwartość wyrażeniaisujezmiennej po lewej stronieprawej strony *=
/= %=
+=
-= Służądo skrócenia zapisu operacji, które
można zapisaćprzyużyciuoperatorów
«= arytmetycznych oraz bitowych »= &= 1\= 1= PROBLEMY KRYMINALISTYKI 288(2) 2015 Programowanie obiektowe
Każdy program (skrypt) programu EnCaseskłada się z jednej lub wielu klas. W dotychczasowych
przy-kładach byłato tylko jedna klasa o nazwieMainCIass.
class MainClass {
void Main(CaseClass c) {
Console.WriteLine("Hello Wor ld") ;
} }
Klasy
Klasy są opisami obiektów, czyli bytów progra-mistycznych, które mogą przechowywać dane oraz
wykonywać polecone przez programistę zadania. Schematyczny szkielet klasywygląda następująco:
cLass nazwa_kLasy {
l/treść kLasy
}
Obiekt, któryzostał stworzony na podstawie danej klasy nazywany jest jej instancją. Obiekt tworzy się
przy użyciu operatora
new.
Klasa jest jak gdybyma-trycą służącą do tworzenia obiektów. Informuje ona
wirtualną maszynę, jak należy utworzyć obiekt kon-kretnego typu. Każdy obiekt utworzony na podstawie klasy może mieć unikalne wartości składowych. Na
przykład można użyć klasy o nazwie Pies, do stwo-rzenia kilku różnych obiektów, z którychkażdy będzie
np. innej rasy.
Przykład:
class MainClass {
void Main(CaseClass c) {
IlUtworzenie nowych obiektów typu Pies
Pies pies_l
=
new Pies () ;Pies pies_2
=
new PiesO;
Pies pies_3
=
new PiesO;II Składowe obiektów - informacje o obiektach
pies_l.wielkość
=
58;pies_l. rasa
=
"Husky";pies_l. nazwa = "Bor ys ";
pies_2.wielkość
=
48;pies_2.rasa
=
"Bokser";pies_2.nazwa
=
"Kol ec";pies_3.wielkość
=
38;pies_3.rasa
=
"Beagle";pies_3.nazwa
=
"Rewin";}
II Utworzenie klasy 'Pies'
class Pies { int wielkość; String rasa; String nazwa; } } 27
Powyższy przykładzawiera trzy zmienne referen-cyjne o nazwach: pies_1, pies_2 i pies_3 . Zmienne referencyjne zawierają bity reprezentujące sposób dotarcia do danego obiektu. Można użyć operatora kropki (.) wraz zezmienną referencyjną, aby uzyskać
dostęp do składowych obiektu. Użycie operatora
kropkiwraz zezmiennąreferencyjnąmożna wyobrazić sobie jako naciskanie przyciskuna pilocie sterującym konkretnym obiektem.
Funkcje
Klasy,oprócz pól przechowującychdane,zawierają
także funkcje, które wykonują zapisane przez
pro-gramistę operacje. Funkcjemogą modyfikować dane
i zwracać różne wartości. Wywołanie funkcji polega
na wpisaniu jej nazwy w programie. W momencie napotkania wywołania funkcji program przechodzi do wykonania kodu funkcji. Kiedy funkcja się kończy,
program wraca do miejsca jej wywołania. Składnia deklaracji funkcjiwygląda następująco:
typ nazwa (dekLaracja argumentów) {
instrukcje; }
Przykład: cIa ss MainClass {
II
Deklaracja pierwszej funkcji bezargumentowejvoid Wyświetl() {
Console.WriteLine("Hel l o World") ;
}
II
Deklaracja drugiej funkcji z argumentemvoid PobierzTekst(String text) {
Console.WriteLine(text); }
II
Deklaracja trzeciej funkcji z 2 argumentamiII
zwracająca wartość całkowitąint Suma(i nt a, int b){
int c
=
a + bj return Cj }void Main(CaseClass c){ IIFunkcja główna 'Main'
II
Wywołanie kolejno wszystkich funkcjiWyświetl()j
PobierzTekst("Tekst prz ekazywa ny do funkcj i ~
jako argument") j int d
=
Suma(3,7)j Console.WriteLine(d)j } } Wynik: Hello WorldTekst przekazany do funkcji jako argument 10
Funkcje określają również czynności, jakie obiekt jest w staniewykonać.
Przykład: class MainClass {
void Main(CaseClass c) {
IlUtworzenie obieku
Pies pies_l
=
new Pies();II
Składowe obiektu - informacjepies_l.wielkość
=
S0jpies_l. rasa
=
"HuskY"jpies_l. nazwa
=
"Borys "jpies_l.szczekaj()j }
II
Utworzenie klasy 'Pies'class Pies { int wielkość;
String rasa; String nazwaj
II
Funkcja - zachowanie obiektuvoid szczekaj() {
Console.WriteLine("Hau! Hau!") j
} } } Wynik:
I
Hau! Hau! Funkcje statyczneFunkcjeskładowe klasy mogą być zadeklarowane jako statyczne. Funkcje temożna wywołaćnawet wte-dy, gdy nie istnieje jeszczeżadenobiekt klasy. Do na-zwy klasy statycznej odwołujemy się poprzez nazwę tej klasy oraz operatora zasięgu (::).Słowo kluczowe
stafie pozwala wywoływać funkcję bez konieczności
posługiwania sięobiektem tej klasy.Funkcja statyczna
umożliwia działanie, które niezależy od składowych,
a zatem nie wymagaużyciaobiektu. Przykład:
class MathClass {
II
Klasa MathClassII
Definicja funkcji statycznejstatic lon g Potęga(l o ng x) { return x
*
Xj} }
class MainClass {
void Main(CaseClass c) {
II
Wywołanie funkcji statycznejConsole. WriteLine("5 do potęg i 2
=
"
~+ MathClass::Potęga(S»j
} }
Wynik:
S do potęgi 2
=
25Konstruktor
Konstruktor jest specjalną funkcją wykonywaną podczas tworzenia obiektu. Konstruktor zawiera kod, który zostaje wykonany w momencie użycia operato-ra new. Innymi słowy, konstruktor zawiera instrukcje wykonywane w momencie tworzenia nowego obiektu. Funkcja będąca konstruktorem nigdy nie zwraca żad nego wynikuimusimieć nazwę zgodnąznazwąklasy.
cLass nazwa_kLasy { nazwa_kLasy(){
II kod konstruktora
} }
Każda tworzona klasa ma konstruktor, nawet jeśli nie zostanie on napisany przez programistę. W takim przypadku konstruktor zostanie stworzony przez kom-pilator. Podstawową cechąkonstruktora jest to, iżjest on wykonywany, zanim obiekt zostanie skojarzony z odwołaniem. Wwiększości przypadków konstruktor używany jest do inicjalizacji stanu obiektu, czyli do określenia wartościjegoskładowych.
Przykład:
class MainClass {
void Main(CaseClass c) {
IlUtworzenie obieku
Pies pies_l
=
new Pies ();II
Wyświetlenie cech obiektuConsole.WriteLine(pies_l.wielkość); Console.WriteLine(pies_l.rasa); Console.WriteLine(pies_l.nazwa); }
II
Utworzenie klasy 'Pi es ' class Pies { int wielkość; String rasa; String nazwa; Pies() {II
KonstruktorII
Określenie wartości obiektuwielkość =
sa;
rasa=
"Husky"; nazwa=
"Borys"; } } void szczekaj() {Console.WriteLine("Hau! Hau!") ; } } } PROBLEMY KRYMINALISTYKI 288(2) 2015 Wynik:
I
~~'kY
Borys DziedziczenieDziedziczenie to jeden z fundamentów progra-mowania obiektowego. Umożliwia sprawne i łatwe
wykorzystanie już raz napisanego kodu czy budowa-nie hierarchii klas przejmujących swoje właściwości. Dziedziczenie polega na budowaniu nowych klas na bazie już istniejących. Każda taka nowa klasa przejmuje zachowanie i właściwości klasy bazowej.
Projektując klasy przy wykorzystaniu
dziedzicze-nia, należy umieścić wspólny kod w klasie bazowej,
a następnie poinformować klasy wyspecjalizowane,
iż konkretna wspólna (bardziej abstrakcyjna) klasa, jest ich klasą bazową. W przypadku, gdy jedna klasa dziedziczy po drugiej, to klasa potomna dziedziczy po klasie bazowej. Potocznie mówisię, żeklasa potomna rozszerza klasę bazową. Relacja dziedziczenia ozna-cza, że klasa potomna dziedziczy po klasie bazowej.
W języku EnScript dziedziczenie wyrażane jest za
pomocądwukropka (:), acaładefinicja schematycznie wygląda następująco:
cLass kLasa_potomna:kLasa bazowa {
II wnętrze kLasy } klasa bazowa Lekarz ~ lednaskładowa 1(ęg~~jęDJ!1U jednametoda klasy potomne
-:
-,<
,
I
ChirurgI
1=1
[oo<t.nową-... l!RP1ł~ Pl'J9U~ II Ilodłjo nową
"-
4
Ilodłjonową_
Ryc. 1.Przykładdziedziczenia.
Przykład:
class MainClass {
void Main(CaseClass c) {
I
I
Utworzenie obiektu lekarza rodzinnegoII
AtrybutyLekarzRodzinny lekarz
=
new LekarzRodzinny(); lekarz.pracujeWDomu=
true;lekarz.pracujeWSzpitalu
=
true;Console.WriteLine("Lekar z rodzinny: ") ; Console.WriteLine("Pr acuj e w domu: " + ~
lekarz.pracujeWDomu); Console.WriteLine("Pr acuj e w szpitalu: " + ~
lekarz.pracujeWSzpitalu);
Console.WriteLine("Por ada lekarza: "l ;
lekarz.podajPorade();
}
II Klasa bazowa 'Lekar z '
class Lekarz {
bool pracujeWDomu;
void leczpacjenta() {
Console.WriteLine("Leczy pacjenta") ;
} }
II Klasy podstawowe: LekarzRodzinny, Chirurg,
II które dziedziczą po klasie Lekarz
class LekarzRodzinny:Lekarz {
bool pracujeWDomu;
void podajPorade() {
Console.WriteLine("Pacj ent musi za2ywa ć ~
witaminę (") ;
} }
class Chirurg:Lekarz {
void zróbNacięcie() {
Console. WriteLine("Wy konuję nacięcie") ; } } } Wynik: Lekarz rodzinny: Pracuje w domu: 1 Pracuje w szpitalu: 1
Porada lekarza: Pacjent musi zażywać witaminę C
Graficzny interfejs użytkownika(GUl)
Wykorzystując obiekty, można tworzyć
zaawan-sowane aplikacje działające w oparciu o graficzny
interfejsużytkownika. Tworzącgraficzny interfejsużyt
kownika, należy pamiętać, że składa się on właśnie
z obiektów: przycisków, etykiet, pól tekstowych itd.,
które mają własne składowe oraz funkcje. W
niniej-szym artykule przedstawione zostaną jedynie dwa
przykładygraficznego interfejsuużytkownika. Przykład:
GroupBoxClass
Dane osobowe
Podaj swojeimię:
OK
I
~ncel
I
Ryc. 2. Przykładoweokno dialogowe (obiekt).
Kodźródłowy wyświetlającyww.okno:
class InputDialogClass: DialogClass {
GroupBoxClass Group;
StringEditClass StringEdit;
InputDialogClass(DialogClass parent,String &5):
DialogClass(parent, "Gro upBoxCl as s Exampl e") , Group(t hi s, "Dane osobowe", START, START, ~
25a, aa, a),
StringEdit(t hi s, "Podaj swoje imię: ", 15, ~
15, 2aa, 12, a, s, 255, a) { } } class MainClass { void MainO { String s; InputDialogClass diag(null, s); diag. ExecuteO; } }
Graficzny interfejs użytkownika związany jest
z przechwytywaniem zdarzeń generowanych przez
użytkownika. W programie EnCase Forensic v.B
za przechwytywanie zdarzeń, np. kliknięcie przez
użytkownika przycisku, odpowiedzialna jest klasa EventC/ass, zaś w wersji 7
ww.
programu klasa Hand/erC/ass.Button Demo
OK
I
<:ancelRyc. 3. Przykładoweokno dialogowe z przyciskiem 'Kliknij'.
Error
[
~ Użytkownikukliknąłeśprzycisk
OK
Ryc. 4. Okno z komunikatemwyświetlonepokliknięciu
Kod źródłowy wyświetlający
ww.
okna iprze-chwytującyzdarzenia:
class ButtonOiagClass: OialogClass {
ButtonClass Buttonj
ButtonOialClass(DialogClass parent
=
null): OialogClass(parent, "Button Demo") , Button(t his, "Kli kni j !", START, START, ~75, 3e, e) II Przycisk
{
}
virtual void ChildEvent(const EventClass ~
&event) {
II Obsługuje zdarzenie kliknięcia
OialogClass::ChildEvent(event)j if (Button.Matches(event» {
II Wyświetla komunikat
ErrorMessage("Ui yt kowni ku kliknąłeś ~
przycisk") j } } } cl as s MainClass { void MainO { ButtonOiagClass bd()j bd. Execute() j } }
zwanym korzeniem (root nade) ipozostałymi węzłami (wierzchołkami)podzielonymina podzbiory,będącymi poddrzewami głównego drzewa. Każde poddrzewo ma swój korzeń, który z kolei ma swoje poddrzewa itd.,a zatemwęzełjest korzeniem pewnego poddrze-wa.Liśćjest to węzeł (element) drzewa,który nie ma potomków, np. plik lub pusty folder.Często liśćmi są
węzłynajbardziej oddaloneod korzenia.
Za przedstawienie danych w programie EnCase w postaci drzewa odpowiada klasa NadeCIass. Większość klas programu EnCase dziedziczy skła dowe i funkcje
ww.
klasy. Wybrane funkcje klasyNadeCIass, tj.: Perenu), FirstChild(), LastChild(),
Next(), umożliwiają przetwarzanie danych w postaci
struktury drzewa. Przykład
class NodeClass {
NodeClass(parent
=
null)j II konstruktor NodeClass FirstChild()jNodeClass LastChild()j NodeClass Next()j NodeClass Parent()j }
EnCase Forensic v.6 i 7 - podstawowe różnice
wjęzyku EnScript
Ryc. 5. Struktura danych w postaci drzewa.
Listypołączone,struktura drzewa
Root ---ł Węzeł główny
(ang.root node)
class MainClass {
void Main(CaseClass c) {
forall (EntrYClass entry in c.EntryRoot(» { Console.WriteLine(entry.Name(»j
} }
}
V6
Język programowania EnScript jest językiem
nie-kompatybilnym, co oznacza, że skrypty napisane
w programie EnCase Forensic v.6 nie będą działały w najnowszej wersji programu. Jedynym wyjściem,
jakie pozostaje użytkownikowi programu EnCasev.7, jest przepisanie skryptów z wersji 6 w taki sposób,
abydziałałyone
w
najnowszej wersjiprogramu. Przed przystąpieniemdo aktualizacji skryptów wartopoznać podstawowe różnice występujące w języku EnScript zdefiniowanym w obydwu wersjach programu EnCase Forensic.Iteracja danych
Podstawowa różnicawjęzyku EnScript zdefiniowa-nym w
ww
.
wersjach programu EnCase Forensic wy-nika ze sposobu przetwarzania danych widniejących w programie w postaci struktury drzewa.W programieEnCase v.6w celu przetworzenia danychnależy użyć jednej z dwóch instrukcjisterujących:foreachlubforaII.
Instrukcja sterująca foreach, pozwala na uzyskanie
dostępu do wszystkich wierzchołków węzła główne
go, natomiast instrukcja foralI pozwala na uzyskanie dostępudo wszystkichelementów struktury drzewa.
Folder (poddrzewo) Plik-liść (ang.lea'nade) Plik2 Plik1 Folder 2 Folder 3 Folder 1
W celu zrozumienia sposobu wyświetlania oraz prze-twarzania danych w programie EnCase pomocne jest zrozumienie struktury drzewa oraz struktury list połączonych.
Listapołączonajest to struktura danychskładająca się z elementów przystosowanych do łączenia sięze
sobą w miarę potrzeb. Elementy listy nazywane są
węzłami (nade). Listy połączone występują w trzech
odmianach: listapołączonapojedynczo, listapołączo na podwójnie oraz drzewo.
Drzewo jest najbardziej złożoną odmianą listy
łączonej orazpodstawową strukturądanych
wykorzy-stywanąw programie EnCasesłużącądo
prezentowa-nia danych w oknie struktury danych (A). Drzewo to
skończonyzbiórwęzłów(nodes) orazliści(/eaf nodes)
z wyróżnionym węzłem głównym (wierzchołkiem)
W przypadku programu EnCase Forensic v.7w celu przetworzenia lub wyświetlenia danych w postaci struktury drzewa należy posłużyć się obiektem typu
ItemlteratorClass. V7 elass MainClass { void Main(CaseClass e) { ItemlteratorClass iter (eJ ItemlteratorClass::NORECURSE ItemlteratorClass::NOPROXYJ ItemlteratorClass::ALL)j
while (EntryClass entry
=
iter.GetNextEntry(»{
Console.WriteLine(entry.Name(»j
} } }
Urządzenie- uzyskaniedostępu
Kolejną różnicąjest sposób uzyskania dostępu do
urządzeniadodanego do sprawy.Wprogramie EnCase Forensicv.6bezpośredni dostępdourządzenia można uzyskaćzapomocąobiektu typu DeviceClass.
V6
elass MainClass {
void Main(CaseClass e) {
foreaeh (DevieeClass dev in e.DevieeRoot(»
{
Console.WriteLine(dev.Name(»j
} } }
W programie EnCase Forensic v.7pomiędzy obiek-tami typu DeviceClassiCaseClass,znajdujesięobiekt
EvidenceClass. Przykłady:
V7
elass MainClass {
void Main(CaseClass e) {
foreaeh (EvideneeClass ev in e.EvideneeRoot(»
{
EvideneeOpenClass evOpen()j
if (DevieeClass dev
=
e.GetDeviee ~(eJ eVOpen» { Console.WriteLine(dev.Name(»j } } } }
Iteracjazawartości urządzenia
V6
elass MainClass {
void Main(CaseClass e) {
foreaeh (DeviceClass dev in e.DevieeRoot(» { foreaeh (EntryClass entry in ~
dev.GetRootEntry(» { Console.WriteLine(dev.Name(»j } } } } V7 elass MainClass { void Main(CaseClass e) {
foreaeh (EvideneeClass ev in e.EvideneeRoot(»
{
EvideneeOpenClass eVOpen()j
if (DevieeClass dev
=
e.GetDeviee ~(eJ eVOpen» { Console.WriteLine(dev.Name(»j ItemlteratorClass iter(dev)j
while (EntryClass entry
=
~iter.GetNextEntry(» { Console.WriteLine(entry.Name(»j } } } } }
Uzyskaniedostępudo pliku
Skrypty programu EnCase pozwalają na uzyska-nie dostępu do pliku, który został zaznaczony przez
użytkownika. Wprogramie EnCasev.6funkcjonalność
ta była ograniczonawyłączniedo elementów prezen-towanych przez obiekty typu EntryClass, widocznych w oknieEntries.
V6
elass MainClass {
void Main(CaseClass e) {
long offset
=
ejlong size
=
2ejif (EntryClass entry
=
e.GetEntry(offset,size){ Console.WriteLine(entry.Name(»j} } }
W wersji 7 funkcjonalność ta została znacznie rozszerzona i możliwe jest uzyskanie dostępu do za-znaczonego obiektu typuEntryClass, BookmarkClass, RecordClassitd.
V7 Zakładki- tworzenie notatek
class MainClass {
void Main(CaseClass c) { V6
lon g of fset
=
ejlong si ze
=
zejif (Ent ry Class ent ry = c.Get Entry:: TypeCast ~
(c.GetCur rentltem(offset ,size») { Conso le.Write Line(ent ry.Name(» j }
}
class MainClass {
void Mai n(CaseClass c) {
BookmarkFolderClass folder ( c . Bookmar kRoot ( ) , ~
"Test")j fol der . AddNot e ("Not at ka", e, 16, ~
BookmarkClass::SHOWREPORT)j
}
Zakładki- tworzeniefolderów
Sposób tworzenia folderów w zakładkach pro-gramu EnCase został zmieniony nieznacznie. W wersji 6 należy posłużyć się obiektem klasy
BookmarkFo/derC/ass,zaśw wersji 7 programu ob iek-tem klasyBookmarkC/ass.
V6
class Mai nClass {
void Main(CaseClas s c) {
Bookmar kFolde rClass folder(c .BookmarkRoot() , ~
"Test")j } } V7 class MainClas s { void Mai n( CaseCla ss c) {
BookmarkCla ss folder(c .BookmarkRoot() , ~
"Test", NodeClass::FOLDER)j
} } } } V7 class MainClass { void Main(CaseClass c) {
Bookma rkClass booknote
=
c.Bookma r kRoot() jBookmarkClas s not e ( booknote, "Notatka") j
note.SetComment(" Z awa rto ś ć notatki") j
} }
EnScriptAPI
Program EnCasejest dystrybuowany wraz z bogatą dokumentacjąw formie plikuHTMLokreślanąjako API (Application ProgrammingInterface).Dokumentacjata jest najlepszym źródłem pozwalającym na zdobycie szczegółowych informacji o klasach, ich składowych
ifunkcjach. DokumentacjaAPIzawierarównież
przy-kładoweprogramy (skrypty), któresąbardzo pomocne podczas tworzeniawłasnych aplikacji.Zawartość API programu EnCase Forensic można wyświetlić za
po-mocą menu programu:He/p->EnScript He/p.
6.18. .'~"r-~
mi ~
Ukryj Wstecz
11j'.
l!P<1'
.>NocIeclass_EB1lDleraUOD.lBsel1ODUOllS""r~f -,
.,;;" in...l4iitloll
NodeClass
,'. ~....; '~',j" :['F' :4;,k:r....H~?~ClissiE..iuneratloBNocIeoDUO....h·_ł
r.:v~.' '. ó;" ,':1.,,". "~:f', Yallle~~" '~ ", ~"":-,,:'''" ••
p.F?:?.~··----~_·~=-·~--~~··~:=)
..
·~--,--·-..
~·--:~~~rf:od~'is a fol~" _. .. .. . - ..-I"'SELECTED i2 _... iSELECTED _nodeis seleeted
r,.>imREPORT -- · --- -· - ---·fl6- - lNREPORt:,_"_Dod_e_is_in_repotI-'--"o:.."'"'-.-"- - - i NodeClassis a generictreedatastructure.
[lnner ClassesJ [EDumeratioD~ [Properti.nJ [Metllodsl [Examples]
-
--
- -
-
- - - -
-
-_._
-_.
_---
_ ._
._-
-
-_._--_
.
_
_
._---_._--
--_
.•_
.
__
._--~--_. r--;:T .:;" ..•' r: ,''(:..r ... ~. Naae :_c' "' If ..:-!.VaI8eC' n,.,'I
II
,
I
I
"
I ' 1=I
-I I~eillodeks W_illkJlli~
~10P01ICI"• • IPClas. • 1PEditOos. • I\oywordCl . .. • l8ng • lcngu<rg.a... • Un.Bt90k0 ... • LislEditOas. • LivelinkS1oreO... • LDcoJFdoO... • l.ocoIModIine • LogicolEvid.nceFilea... • LogRscordCl... . Ioog • LongEdiIO. .. • Mo;n'Mndow • Memorya... • Memo')Mlea..• • MenulluildO... • MonuClen • Mi••ingSedolClos. • NameEd"1lOou • NameUslCI . • NameVeN. a . • NomeVeriontClos. • Netlnterfocea... • N.lU••ra . • N.tworkO .
•
• No<esSlon>Cl... .nuIlRyc. 6. DokumentacjaEnscriptAPI.
Przykładyautorskich rozwiązań
programistycznych
MAC AddressfromLNK PawełOIber
C:\users\User\Desktop\Wyniki.c~
TheMeaning
ThisscriptreadsMAC addressfromlNKfiles.
Programtakesintoconsideration only L'IIKfiles,whichweren'lcopied
or moved by userfrorn/toanotherlogical disk.
That guaranleesmatreadedMACaddressconcerns networkcards
installedin evidencecornputer,
Search resultswillbedisplayedinConsoleview.
Alidetails(for example:filenarne,lastwOltendale.volurneObjectJD_l
willbesavedinCSVfile.
Source documentTheMeaningoflinkfilesInForensicExaminations,
ThisprogramhasbeenwrittenbyPawełOlber
Forensiclaboratory ofRegionalPoliceHeadquartersin Olsztyn
OK
Ryc. 9. Okno pomocy skryptu MAC Address from LNK.
MACAddressfrom lNK
Skrypt MAC Address from LNK powstał w
opar-ciu o dane zawarte w dokumencie The Meaning ot
Unkfiles in Forensic Examination2autorstwa Harry'ego
Parsonage. Dokument zawiera szczegółowy opis
analizy zawartości plików LNK w edytorze szesnast-kowym, z którego skorzystano w trakcie tworzenia skryptu.
Po uruchomieniu skryptu w programie EnCase Forensic v.6wyświetla sięokno dialogowe umożliwia
jące określenie ścieżki dostępui nazwy pliku, w którym
zapisane zostanąwyniki działaniaskryptu.
W lewym górnym rogu
ww.
okna znajduje się przy-cisk Help" Po kliknięciuww.
przycisku wyświetla sięokno zawierającekrótki opis działaniaskryptu.
Unikalne adresy MAC oraz identyfikator dysku twar-dego odczytane z plików LNK,wyświetlane sąw oknie konsoli programu EnCase Forensic v.6.
Szczegółowe dane uzyskane w wyniku działania
ww.
skryptu zapisywane sąw postaci pliku tekstowe-go CSV. Wynikowy plik tekstowy o rozszerzeniu CSV zawiera m.in. listę plików, z których odczytano adresy MAC wraz zeszczegółowymidanymi.SkryptRedundant Remover
Skrypt Redundant Removerpowstałw trakcie wy-konywania badań w ramach opinii kryminalistycznej
dotyczącej skimmera Atmel 45D8321 D. W trakcie
realizacji ww. badańodczytanozawartość urządzenia,
którązapisano w postaci pliku binarnegozawierające
go zapissygnału dźwiękowego.
Odczytany zapis sygnału dźwiękowego zawierał
nadmiarowe dane uniemożliwiające prawidłową
ana-lizęamplitudysygnałui odczyt skopiowanych danych identyfikacyjnych kart płatniczych.
W celu usunięcianadmiarowych danych z ww. pliku
dźwiękowego zawartość dowodowego pliku
binar-nego odczytano za pomocą programu EnCase v.6.
A1001\ atthe pr.let..ic.llvałuetoIcrensic
exannnaucns ofdares and limes. and
objeL"idenlił1c(S in Windows shortrut fiłes.
F orensic Examinations
of
LinldUes OKI
canceJI
~
OutputPath logFilePath:Ryc. 7. Dokument The Meaning of Linkfiles in Forensic
Examinations.
Program MAC Address trom LNK
Skrypt MAC Address from LNK przeznaczony jest do odczytu adresów MAC kart sieciowych zapisanych w plikach o rozszerzeniu LNK,tzw. skrótach utworzo-nych na dysku twardym z systemem plików NTFS.
Każdorazoweutworzenie przezużytkownikaskrótu do
pliku lub programu na dysku z systemem plików NTFS skutkuje zapisaniem w utworzonym pliku adresu MAC karty sieciowej zamontowanej w komputerze. Skrypt
uwzględnia jedynie pliki z rozszerzeniem LNK, które
niezostałyskopiowane lub przeniesione z innego
no-śnikadanych lub partycji.
Przedmiotowy skrypt okazał się niezwykle istotny w sprawie, której celem było m.in.odczytanie adresu MAC karty sieciowej. Materiałem dowodowym w
ww
.
sprawie był notebook oraz nadesłany luzem dysk
twardy. W wyniku działania ww. skryptu z dowodowe -go dysku twarde-go (nadesłanegoluzem) odczytano 2 adresy MAC kart sieciowych.
Ryc. 8. Okno skryptu MAC Address from LNK.
2 http://computerforensics.parsonage.co.uk/downloads/