poniedziałek, 26 stycznia 2015

Penetrujemy aplikacje napisane w języku C - narzedzie GDB cz.3

To już ostatni wpis do wstępu z narzędziem GDB. Wydaje mi się, że jest to wiedza po której można ta aplikacje dalej poznawać, bo jest ona naprawde duża.
Wracając do tematu, chciałbym się skupić na tym czy jesteśmy w stanie określić co znajduje się w adresie rip i takim oto sposobem omówię kilka instrukcji, by sprawdzić jak wygląda nasz kod maszynowy, który wcześniej był zapisany w aplikacji C.
 (gdb) x/10i $rip  
 =&gt; 0x400564 <main>:     movl  $0x0,-0x4(%rbp)  
   0x40056b <main>:     jmp  0x40057b <main>  
   0x40056d <main>:     mov  $0x400634,%edi  
   0x400572 <main>:     callq 0x400440 <puts plt="">  
   0x400577 <main>:     addl  $0x1,-0x4(%rbp)  
   0x40057b <main>:     cmpl  $0x9,-0x4(%rbp)  
   0x40057f <main>:     jle  0x40056d <main>  
   0x400581 <main>:     mov  $0x0,%eax  
   0x400586 <main>:     leaveq   
   0x400587 <main>:     retq    
 (gdb)   

Kod robi podwójny skok pamięci do instrukcji
 cmpl  $0x9,-0x4(%rbp)  

Jest to instrukcja porównawcza, która sprawdza czy warunek jest spełniony, jeśli wartości są mniejsze lub równe to jest ponowy skok do pamięci 0x40056d, a w przeciwnym wypadku idzie do kolejnej instrukcji. Nasŧepnie możemy wykonywać kolejne instrukcje i zauważyć, że w pewnym momęcie zobaczymy instrukcje puts.
 (gdb) nexti   
 0x000000000040056b     5          for(i = 0; i < 10; i++) {   
 (gdb) x/i %rip  
 A syntax error in expression, near `%rip'.  
 (gdb) x/i $rip  
 => 0x40056b <main+15>:     jmp  0x40057b <main+31>  
 (gdb) nexti   
 0x000000000040057b     5          for(i = 0; i < 10; i++) {   
 (gdb) x/i $rip  
 => 0x40057b <main+31>:     cmpl  $0x9,-0x4(%rbp)  
 (gdb) nexti   
 0x000000000040057f     5          for(i = 0; i < 10; i++) {   
 (gdb) x/i $rip  
 => 0x40057f <main+35>:     jle  0x40056d <main+17>  
 (gdb) nexti   
 6               puts("Hello, world!\n");   
 (gdb)   

Teraz sprawdzę na jaki adres pamięci wskazuje teraz program:
 (gdb) i r rip  
 rip      0x40056d     0x40056d <main+17>  
 (gdb) x/2i $rip  
 => 0x40056d <main+17>:     mov  $0x400634,%edi  
   0x400572 <main+22>:     callq 0x400440 <puts@plt>  
 (gdb)   

Ciekawe co kryje edi i mogę to spokojnie także podglądnąć:
 (gdb) i r edi  
 edi      0x1     1  
 (gdb) x/6cb $0x400634  
 Value can't be converted to integer.  
 (gdb) x/6cb 0x400634  
 0x400634:     72 'H'     101 'e'     108 'l'     108 'l'     111 'o'     44 ','  
 (gdb)   
Znalazłem Hello world, aby wygadało lepiej można wydrukować to tak:
 (gdb) x/12cb 0x400634  
 0x400634:     72 'H'     101 'e'     108 'l'     108 'l'     111 'o'     44 ','     32 ' '     119 'w'  
 0x40063c:     111 'o'     114 'r'     108 'l'     100 'd'  
GDB to wspaniałe narzędzie, gdzie ja nie pokazałem jego wszystkich możliwości i aby się lepiej go nauczyć, trzeba popatrzeć jak każda instrukcja wygląda po skompilowaniu na kod maszynowy - czyli życzę miłej zabawy, w analizowaniu programów napisanych w C. Nasŧepny post będzie omawiał wsŧep do projektu jaki z kumplami zaczynamy, a po jego zakończeniu powrócimy do C i może postaramy się zrobić jakiś nabzdurzyć pamięci.

niedziela, 4 stycznia 2015

Penetrujemy aplikacje napisane w języku C - narzedzie GDB cz.2

Ostatnio nie skończyłem omawiać tego narzędzia - to znów będę męczył coś na jego temat. Ostatnio bawiłem się wyświetlaniem rejestru RIP w różnych systemach liczbowych, a dziś będziemy analizować jego zawartość. Poniżej pokazuje instrukcje, która określa liczbę badanych jednostek w docelowym adresie.
 (gdb) x/12x $rip 

 0x400564 <main+8>:     0x00fc45c7     0xeb000000     0x0634bf0e     0xc9e80040 

 0x400574 <main+24>:     0x83fffffe     0x8301fc45     0x7e09fc7d     0x0000b8ec 

 0x400584 <main+40>:     0xc3c90000     0x00841f0f     0x00000000     0x246c8948 


Dodatkowo możemy zmienić rozmiar jednostki, bo aktualnie jest ustawiona na 4bajty i możemy je formatować na pojedynczy bajt, pół słowo(2bajty), słowo o rozmiarze 4 bajtów i słowo podwójne.
 (gdb) x/12x $rip 

 0x400564 <main+8>:     0x00fc45c7     0xeb000000     0x0634bf0e     0xc9e80040 

 0x400574 <main+24>:     0x83fffffe     0x8301fc45     0x7e09fc7d     0x0000b8ec 

 0x400584 <main+40>:     0xc3c90000     0x00841f0f     0x00000000     0x246c8948 

 (gdb) x/8xb $rip 

 0x400564 <main+8>:     0xc7     0x45     0xfc     0x00     0x00     0x00     0x00     0xeb 

 (gdb) x/8xh $rip 

 0x400564 <main+8>:     0x45c7     0x00fc     0x0000     0xeb00     0xbf0e     0x0634     0x0040     0xc9e8 

 (gdb) x/8xw $rip 

 0x400564 <main+8>:     0x00fc45c7     0xeb000000     0x0634bf0e     0xc9e80040 

 0x400574 <main+24>:     0x83fffffe     0x8301fc45     0x7e09fc7d     0x0000b8ec 

 (gdb) x/8xg $rip 

 0x400564 <main+8>:     0xeb00000000fc45c7     0xc9e800400634bf0e 

 0x400574 <main+24>:     0x8301fc4583fffffe     0x0000b8ec7e09fc7d 

 0x400584 <main+40>:     0x00841f0fc3c90000     0x246c894800000000 

 0x400594 <__libc_csu_init+4>:     0x8d48e02464894cd8     0x258d4c002008672d 

Powyżej można zauważyć pewne udziwnienia w danych. Przy zmianie adnotacji ze słowa na pół słowa czy też na pojedynczy bajt, każda adnotacja jakby pokazywała coś innego. Pierwszy wydruk pokazuje jednak, że pierwsze dwa bajty to 0xc7 i 0x45, ale gdy badamy po pół słowie, w tym samym miejscu pamięci, pokazywana jest wartość 0x45c7. Spokojnie jest to tylko odwrócona kolejność bajtów i ten sam efekt jest przy całym słowie. Jest to logiczne z punktu widzenia procesora, bo wartości są przechwytywane w kolejności little endian.
To tyle na ten post, w następnym postaram się troszkę posprawdzać co kryje aplikacja po skompilowaniu i czy rzeczywiście jest to co w niej zawieraliśmy.

niedziela, 28 grudnia 2014

Detektywistyczne anime Detektyw Conan

Rzadkością jest znalezienie dobrego anime, długiego jak rzeka, gdzie nawet fillery mogą wciągać. Taką pozycją to właśnie Detektyw Conan.

Historia moja z tym tytułem jest dość długa. Początkowo te anime widziałem na niemieckim programie, chyba RTL2 (już ponad 20 lat emitują różne anime na swoim kanale), później nastąpiła cisza, ale kreska i postacie zapamiętałem. Przypomnienie było, za czasów studiów, bo Conan pojawił się na AXN Sci-fi - już niestety nie ma nawet i kanału. Po wielu latach odświeżyłem i nadal oglądam ta serie dzięki stronie: www.meitantei-sekai.pl

Ogólnym tematem anime jest znajdowanie sprawcy zabójstwa,  dodatkowo patrząc na główna linie fabularną, nasz główny bohater szuka sposobu i ludzi którzy go odmienili. Dokładniej stał się młodszy. Mógłbym się rozpisywać na ten temat więcej, ale nie robię recenzji anime tylko chce zachęcić was do niego.

Podsumowując anime Detektyw Conan jest ukryta perełką, którą ciężko znaleźć, ale jak już się znajdzie to zabawa jest przednia.

niedziela, 30 listopada 2014

Penetrujemy aplikacje napisane w języku C - narzedzie GDB

Tak jak pisałem ostatnio, dziś będę używał narzędzia GDB. Służy ono do analizowania kodu programów napisanych w C lub C++. Niestety jeżeli chodzi o składnie desasemblera to znam tylko Intela i nim będę się posługiwał i tym programie, co powoduje to że muszę je skonfigurować i to wygląda następująco:

 gdb -q  
 (gdb) set disassembly-flavor intel   
 (gdb) quit  
po skonfigurowaniu, mogę teraz przejść do pracy, tylko jeszcze będę musiał prze-kompilować program przy użyciu gcc z parametrem -g, który jest odpowiedzialny za wprowadzenie dodatkowych informacji jak będę debugował.
 gdb -q ./a.out  
 Reading symbols from /home/domek/c/a.out...done.  
 (gdb) list  
 1     #include <stdio.h>  
 2       
 3     int main() {  
 4          int i;  
 5          for(i = 0; i < 10; i++) {   
 6               puts("Hello, world!\n");   
 7          }  
 8          return 0; // Informuje OS o zakonczeniu programu  
 9     }  
 (gdb) di  
 directory  disable   disassemble disconnect  display     
 (gdb) dis  
 disable   disassemble disconnect  display     
 (gdb) disassemble main  
 Dump of assembler code for function main:  
   0x000000000040055c <+0>:     push  %rbp  
   0x000000000040055d <+1>:     mov  %rsp,%rbp  
   0x0000000000400560 <+4>:     sub  $0x10,%rsp  
   0x0000000000400564 <+8>:     movl  $0x0,-0x4(%rbp)  
   0x000000000040056b <+15>:     jmp  0x40057b <main+31>  
   0x000000000040056d <+17>:     mov  $0x400634,%edi  
   0x0000000000400572 <+22>:     callq 0x400440 <puts@plt>  
   0x0000000000400577 <+27>:     addl  $0x1,-0x4(%rbp)  
   0x000000000040057b <+31>:     cmpl  $0x9,-0x4(%rbp)  
   0x000000000040057f <+35>:     jle  0x40056d <main+17>  
   0x0000000000400581 <+37>:     mov  $0x0,%eax  
   0x0000000000400586 <+42>:     leaveq   
   0x0000000000400587 <+43>:     retq    
 End of assembler dump.   
 (gdb) run  
 Starting program: /home/domek/c/a.out   
 Missing separate debuginfo for /lib64/ld-linux-x86-64.so.2  
 Try: zypper install -C "debuginfo(build-id)=ecb8ef1a6904a2a3ec60a527f415f520c8636158"  
 Missing separate debuginfo for /lib64/libc.so.6  
 Try: zypper install -C "debuginfo(build-id)=bd1473e8e6a4c10a14731b5be4b35b4e87db2af7"  
 Breakpoint 1, main () at zad1.c:5  
 5          for(i = 0; i < 10; i++) {   
 (gdb)   
Widzę, że mam problemy przy uruchomieniu tego programu w debuggerze, ale spokojnie Suse podpowiedział mi co muszę zainstalować i powtórzę tą operacje. Zainstalowałem brakującą bibliotekę i oto wynik:
 (gdb) break mian   
 Function "mian" not defined.  
 Make breakpoint pending on future shared library load? (y or [n]) y  
 Breakpoint 1 (mian) pending.  
 (gdb) run  
 Starting program: /home/domek/c/a.out   
 Hello, world!  
 Hello, world!  
 Hello, world!  
 Hello, world!  
 Hello, world!  
 Hello, world!  
 Hello, world!  
 Hello, world!  
 Hello, world!  
 Hello, world!  
 [Inferior 1 (process 15408) exited normally]  
 (gdb) info registers eip  
 The program has no registers now.  
 (gdb)   
Jak już mam wszystko to mogę omówić co tu robiłem, na początku sprawdziłem jak wygląda kod, później zobaczyłem maina w wersji assemblera i jak można zaobserwować, tutaj podawane są na początku zakresy pamięci, nie jak było to w przypadku objdumpa. Chciałem uzyskać informacje o instrukcji RIP, który wskazuje on na adres pamięci instrukcji deasemmblacji funkcji main i udało mi się uzyskać :
 break main  
 Breakpoint 1 at 0x400564: file zad1.c, line 5.  
Debbuger GDB ma możłiwośc bezpośredniego badania pamięci i jest to polecenie x.Sprawdzanie pamięci jest bardzo ważne dla każdej osoby, która chce poznać dokładnie program, bo możemy zmienić składnie z systemu szesnastkowego na inny. Proponuje każdemu posprawdzanie tego jak to działa bo u mnie wygląda to tak:
 (gdb) x/x $rip  
 0x400564 <main+8>:     0x00fc45c7  
 (gdb) x/u $rip  
 0x400564 <main+8>:     16532935  
 (gdb) x/t $rip  
 0x400564 <main+8>     00000000111111000100010111000111  
Dziś narazie wystarczy i mam nadzieje, wy czytający ten post, dowiedzieliście się czegoś więcej i spokojnie jeszcze do tego postu wrócę by opisać co możemy dalej z tym robić :)

czwartek, 20 listopada 2014

Penetrujemy aplikacje napisane w języku C

Dziś wracam do podstaw programowania w języku C, lecz nie będzie to typowa nauka języka programowania. Aplikacje w języku C są kompilowane i składnia którą piszemy, musi być najpierw przetłumaczona na język maszynowy, gdzie zwykle programiści nie zaglądają. Ja będę tym złym i będę sprawdzał jak moje programy wyglądają od środka.
Początkowo skupie się na instrukcjach warunkowych, pętlach, mechanizmami wejścia i wyjścia itp. i nawet udowodnię moc wskaźników.
Początkowo zaczynam od prostego przykładu:
 #include <stdio.h>  
 int main() {  
      int i;  
      for(i = 0; i < 10; i++) {   
           puts("Hello, world!\n");   
      }  
      return 0; // Informuje OS o zakonczeniu programu  
 }  
Pewnie wszyscy od takiego przykładu zaczynają i można spotkać w wielu kursach do nauki języka C, developerzy - zwłaszcza po ukończonych studiach, myślą, że jak zna płynnie składnie języka, to zna język od deski do deski i takie rozumowanie jest błędne. Kiedyś też tak myślałem, że jak napisze program to znam dobrze C, lecz gdy dowiedziałem się, o tym, że do skompilowanego programu mogę zajrzeć i go troszkę po penetrować, zrozumiałem jak mało wiem o tym języku.
Teraz wracając do przykładu chciałbym pokazać jak można zajrzeć do skompilowanego programu i przeczytać jego zapis w języku maszynowym. Komputer, który użytkuje jest w architekturze x86 i pod tą architekturę będę pokazywał kod asemblera, a do tego posłuży mi narzędzie objdump. I ten prosty program wygląda u mnie tak.
Polecenie:

  objdump -D zad1.o | grep -A20 main.:  
Wynik:

 0000000000000000 <main>:  
   0:  55           push  %rbp  
   1:  48 89 e5        mov  %rsp,%rbp  
   4:  48 83 ec 10       sub  $0x10,%rsp  
   8:  c7 45 fc 00 00 00 00  movl  $0x0,-0x4(%rbp)  
   f:  eb 0e          jmp  1f <main+0x1f>  
  11:  bf 00 00 00 00     mov  $0x0,%edi  
  16:  e8 00 00 00 00     callq 1b <main+0x1b>  
  1b:  83 45 fc 01       addl  $0x1,-0x4(%rbp)  
  1f:  83 7d fc 09       cmpl  $0x9,-0x4(%rbp)  
  23:  7e ec          jle  11 <main+0x11>  
  25:  b8 00 00 00 00     mov  $0x0,%eax  
  2a:  c9           leaveq   
  2b:  c3           retq    
 Disassembly of section .rodata:  
 0000000000000000 <.rodata>:  
   0:  48           rex.W  
   1:  65           gs  
   2:  6c           insb  (%dx),%es:(%rdi)  
Standardowo wartości są podawane w trybie szesnastkowym, lecz zawsze można to odpowiednio zmienić, dodatkowo ta adnotacja kodu maszynowego jest pokazana do architektury AT&T i jeżeli chcemy zmienić adnotacje to wystarczy podać to w parametrze M, co przedstawiam poniżej:
  objdump -M intel -D zad1.o | grep -A20 main.:  
Wynik:
 0000000000000000 <main>:  
   0:     55               push  rbp  
   1:     48 89 e5            mov  rbp,rsp  
   4:     48 83 ec 10          sub  rsp,0x10  
   8:     c7 45 fc 00 00 00 00      mov  DWORD PTR [rbp-0x4],0x0  
   f:     eb 0e             jmp  1f <main+0x1f>  
  11:     bf 00 00 00 00         mov  edi,0x0  
  16:     e8 00 00 00 00         call  1b <main+0x1b>  
  1b:     83 45 fc 01          add  DWORD PTR [rbp-0x4],0x1  
  1f:     83 7d fc 09          cmp  DWORD PTR [rbp-0x4],0x9  
  23:     7e ec             jle  11 <main+0x11>  
  25:     b8 00 00 00 00         mov  eax,0x0  
  2a:     c9               leave   
  2b:     c3               ret    
Początkowo kod jest bardzo trudny do odczytu, lecz od razu mozna zobacyzć, zę na początku jest deklarowane rejestry od akumulatorów, liczników, danych i bazowych. Później polecenia:
  • mov - deklaruje zmienią do pamięci rdp-0x4 == 4, 
  • jmp - służy do przeskoków pamięci, call wykonuje odpowiedni rozkaz w tym przypadku wywołuje polecenie putsa, 
  • add - dodaje nam do zmiennej plus jeden,
  • cmp - jest instrukcją porównania czy zmienna z pamięci rdp-0x4 jest równa 9 i później wykonanie tego warunku, a jak nie to wraca do punktu 0
Teraz można zobaczyć, że porównanie w kodzie maszynowym wygląda inaczej niż ten co zapisałem, w prostym przykładzie w C. 
Objdump jest przydatnym narzędziem, jeśli chcę zobaczyć aplikacje w kodzie maszynowym, ale nie pomoże jeśli aplikacja zawiera błędy, w poszczególnych instrukcjach, czy też jeżeli sprawdzam odpowiedni fragment kodu aplikacji.
Na szczęście jest narzędzie idealne do większej analizy kody, przeznaczonej dla programistów, czy tez testerów penetracyjnych i zwie się gdb i tak to jest debuger, które omówię już w następnym poście. 

środa, 12 listopada 2014

Django + Rest = power cz3

Kolejny post o Django z RESTem, lecz tym razem już będę implementował prosty przykład. Postanowiłem zrobić prosty system wyświetlający pole do wypełnienia o użytkowniku, czyli wziąłem pierwszy i przykład ze stronki o RESTfulu z Django. Jestem w tej sprawie troszkę zielony, więc muszę zaczynać od prostych przykładów.
Początkowo skupie się od razu nad konfiguracją już przygotowanej struktury do tworzenia aplikacji MVC i tak jak już otworzyłem swoje Ninja IDE to przystępie od tworzenia nowego moduły o nazwie: serializers.py, . Poniżej jest pokazany kod tego pliku.

1:  from django.contrib.auth.models import User, Group  
2:  from rest_framework import serializers  
3:  """  
4:  This class define 3 fields  
5:  """  
6:  class UserSerializer(serializers.HyperlinkedModelSerializer):  
7:    class Meta:  
8:      model = User  
9:      fields = ('url', 'username', 'email', 'groups')  
10:  """  
11:  Bext class generate anotger fields ;)  
12:  """  
13:  class GroupSerializer(serializers.HyperlinkedModelSerializer):  
14:    class Meta:  
15:      model = Group  
16:      fields = ('url', 'name')  
Teraz skonfiguruje środowisko by korzystał z frameworka RESTowego, czyli muszę edytować plik settings.py. Na początku do INSTALLED_APPS dodaje:
1:  'rest_framework',   
I jeszcze pod koniec lub w dowolnym miejscu pliku, definiuje odwołanie do odwołanie do resta:
1:  REST_FRAMEWORK = {  
2:    'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAdminUser',),  
3:    'PAGINATE_BY': 10  
4:  }  
Teraz przechodzę do pierwszego testu. Posłużę się poleceniem
1:  python ./manage.py runserver  
Okazało się, że zapomniałe skonfigurowac pliku urls.py, który prawidłowo powinien wyglądac tak:
1:  from django.conf.urls import url, include  
2:  from django.contrib.auth.models import User  
3:  from rest_framework import routers, serializers, viewsets  
4:  # Serializers define the API representation.  
5:  class UserSerializer(serializers.HyperlinkedModelSerializer):  
6:    class Meta:  
7:      model = User  
8:      fields = ('url', 'username', 'email', 'is_staff')  
9:  # ViewSets define the view behavior.  
10:  class UserViewSet(viewsets.ModelViewSet):  
11:    queryset = User.objects.all()  
12:    serializer_class = UserSerializer  
13:  # Routers provide an easy way of automatically determining the URL conf.  
14:  router = routers.DefaultRouter()  
15:  router.register(r'users', UserViewSet)  
16:  # Wire up our API using automatic URL routing.  
17:  # Additionally, we include login URLs for the browseable API.  
18:  urlpatterns = [  
19:    url(r'^', include(router.urls)),  
20:    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))  
21:  ]  
Teraz jeszcze raz uruchamiam test, czyli uruchomienie serwera pythona na porcie 8000 i zależnie od tego jak skonfigurujemy serwer bazy danych to powinniśmy dostać podobny wynik do tego:
Brakuje mi jeszcze widoku, który powinien wyglądac tak:
1:  from django.contrib.auth.models import User, Group  
2:  from rest_framework import viewsets  
3:  from tutorial.quickstart.serializers import UserSerializer, GroupSerializer  
4:  class UserViewSet(viewsets.ModelViewSet):  
5:    """  
6:    API endpoint that allows users to be viewed or edited.  
7:    """  
8:    queryset = User.objects.all()  
9:    serializer_class = UserSerializer  
10:  class GroupViewSet(viewsets.ModelViewSet):  
11:    """  
12:    API endpoint that allows groups to be viewed or edited.  
13:    """  
14:    queryset = Group.objects.all()  
15:    serializer_class = GroupSerializer  
Teraz jest już wszystko i jestem gotowy do rozpoczęcia przygody z RESTem na poważnie, czyli od razu pójdę na głęboką wodę i rozpocznę z moimi kumplami/kumpelą od razu aplikacje RESTową i ps. zacznę pracować na Linuxie, bo ja nie lubię troszkę Windowsa. Następny post będzie o tym jak zagłębić się w podstawy języka C i poznać go troszkę od środka, a następny post tego o Django + REST pojawi się tylko jak wymagania rozbite będą na zadania.

wtorek, 4 listopada 2014

Poznawanie PERLa

Trochę mi to trwało, by znów coś napisać - spowodowane to było ilością pracy. Teraz chciałbym napisać krótką niedzielo-poniedziałkową przygodę z językiem PERL i przerobiłem tylko podstawy by dowiedzieć i jak znajdę chwilę czasu to przejdę do obiektowej wersji tego języka i zbuduje jakiś mały serwis internetowy.
Przejdę teraz do języka PERL, jest o językiem skryptowym a w składni przypomina PHP, BASHa i nie upodabniał bym go do języków Python i Ruby, bo mają one znaczącą różnice (Python i Ruby są typowo obiektowymi językami, a PERL nie). Posiada tez pewne cechy języka C, ale nie będę się za wiele w tym wypowiadał i przejdę od razu do pokazania składni.
Pierwsze co rzuciło mi się w oczy to komentarze zbudowane z wielu linii. 
 =comment  
  to jest długi komwntarz  
 =cut  
Jest trochę podobny to Adnotacji w języku Ruby, ale rozpoczęcie komentarza jest długie i pewnie męczące - pewnie mało kto tego komentarza używa w kodzie, zwłaszcza, że podstawowy komentarz jest identyczny co ten z Basha.
Następnie bez czytania, na temat PERLa przeszedłem do praktykowania z nimi tak oto powstały poniższe programy - wybrałem tylko dwa, bo sprawdzałem też i CGI w PERlu, ale to opisze następnym razem.
Program1:

 #!/usr/bin/perl  
 use warnings; use strict;  
 =comment  
  to jest długi komwntarz  
 =cut  
 print "Start programu\n";  
 print "Podaj liczbe całkowita niejuemną:";  
 my $zm = <STDIN>;  
 &bity($zm);  
 print "Podaj dzielnik:";  
 my $zm1 = <STDIN>;  
 my $ans = &nwd($zm,$zm1);  
 print $ans;  
 sub bity {  
      my $zmCal = $_[0];  
      my $i =0;  
      for(; $i < $zmCal; $i++) {  
           $i = 2*$i + $zmCal%2;  
      }  
      print "Odwrotna kolejnosc bitów to: ", $i;  
      print "\n";   
 }  
 # nwd  
 sub nwd {  
      my $m = $_[0];  
      my $n = $_[1];  
      my $r; # tmp memory  
      # lets play  
      while($n) {  
           $r = $m % $n;  
           $m = $n;  
           $n = $r;  
      }  
      return $m;  
 }  
Po zapoznaniu się z podstawową składnią, jak wyglądają pętle, komentarze i funkcje zrobiłem drugi program:
 #!/usr/bin/perl  
 =comment  
  Aplikacja będzie przeliczac z liczby calkowitej dodatniej na adnotacje rzymską.  
  Do tego wykorzystam petle  
 =cut  
 use warnings; use strict;  
 #użyje tego :P  
 my @liczby = (1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1, 0) ;  
 #hmmm, teraz zrobię do tego algorytm  
 #na poczatku trzeba podac jakąs wartość :)  
 print "Podaj liczbe całkowita niejuemną:";  
 my $zm = <STDIN>;  
 =comment  
  zastanawiam sie nad sensownym rozwiazaniem   
  dajmy liczby: 1410, 2525  
  1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1  
   1        1        1  
   2     1             2   1  
  Wygląda na to, że trzeba to zrobić, przez dzielenie całkowite :)  
 =cut  
 print wylicz(\@liczby, $zm);  
 #ale to nie optymalne :(  
 sub wylicz {  
      my %rzymskie = (1000 => 'M', 900 => 'CM', 500 => 'D', 400 => 'CD', 100 => 'C',  
                90 => 'XC', 50 => 'L', 40 => 'XL', 10 => 'X', 9 => 'IX',   
                5 => 'V', 4 => 'IV', 1 => 'I');  
      # tak wyglada referencja o.O => dobrze, że perl nie ma wskazników :D  
      my $liczby2 = shift;  
      pop @$liczby2;  
      my $liczba = $_[0];  
      my $rest = 0;   
      my $rzym = "";  
      foreach my $zmienna (@$liczby2) {  
           $rest = int($liczba / $zmienna);  
           if($rest > 0) {  
                $liczba -= ($rest* $zmienna);  
                for(my $i = 0; $i < $rest; $i++) {  
                     $rzym .= $rzymskie{$zmienna};  
                }       
           }  
      }  
      return $rzym;  
 }  
Także nie jest on skomplikowany, a dodatkowo jest on nie optymalny - trudno. Przejdę teraz do krytykowania języka. Pierwsze co mnie zdziwiło to jak wygląda referencja, troszkę według mnie jest skomplikowana i mało kto by się kapnął że "\" oznacza referencję i nie ma tutaj utrapienia ze wskaźnikami, które występują w C i C+. Patrząc dalej można zauważyć dziwną zmienną:
 my %rzymskie
Jest to nic innego jak taka lita, zwana hashem i powiem, ma dużo zalet, ale też ma wadę - nie można jej sortować, a dane są rozmieszczone inaczej niż jak one były wprowadzane do hasha.
Kończę te narzekanie i stwierdzam, że mimo wielu dziwnych wynalazków PERL jest prostym w opanowaniu językiem to że nie ma wielu rozwiązań problemów, które możemy znaleźć w innych językach, nie oznacza że nie napiszemy porządnej, wydajnej i funkcjonalnej aplikacji. Niestety kończę moje wywody na temat języka PERL i jak znajdę chwilę, to pewnie znów coś o nim napisze.