Blood2: Analiza cracka

14 października 2014

Kolejna część dotycząca mojej starej ulubionej (ostatnio) gry, którą potraktowałem jako narzędzie analizy i zabawy w reverse enginering. Jak wspomniałem w poprzedniej (pierwszej) części, miałem problem ze znalezieniem odpowiedniego programu neutralizującego wymóg posiadania płyty CD. A wszystko na co trafiłem było jednosegmentowymi aplikacjami DOS-a. A jak wiadomo Windowsy 64-bitowe nie posiadają już subsystemu do odpalania 16-bitowych programów. Mimo, iż 64-bitowe procesory w trybie „long mode„, jako tako dałyby radę z takim kodem, o ile nie wymagałby wirtualnego trybu chronionego. Tak, czy inaczej zostałem zmuszony do zabawy w crackera, co w ostatniej notce przedstawiłem. Obiecałem również, że przyjrzę się bliżej temu „comowemu” crackowi z bliska.

16-bitów z sieci

Po diasemblingu, kod programu okazał się bardzo prosty, typowe operacje na plikach, korzystając z funkcji DOS – poprzez przerwanie 21h. Nic odkrywczego i ciekawe tutaj nie znalazłem. Aczkolwiek pewne fragmenty mnie zaciekawiły, bo albo były błędne, albo ja coś do końca nie kontaktowałem za dobrze, kiedy to analizowałem.

W dalszej części, w przedstawianym kodzie pomijam wszelkie nieistotne dla nas informacje i fragmenty kodu, do których mogę zaliczyć informacje i komunikaty identyfikujące autora, grupę, a także inne wyświetlane na ekranie komunikaty. Kod wzbogaciłem o komentarze, opisujące niektóre instrukcje. Niektóre etykiety i nazwy zamieniłem na bardziej czytelne, odpowiednie dla danych fragmentów, co powinno ułatwić czytanie i zrozumienie tegoż, nazbyt prostego kodu.

Początek trywialny, otwieramy plik wykonywalny gry. Jeśli operacja się powiedzie to przechodzimy dalej. W przypadku błędu, wyświetlamy odpowiedni komunikat i zamykamy program z kodem błędu 1.

seg000:014A		mov ax, 3D02h				; otwarcie pliku dyskowego w trybie rw
seg000:014D		mov dx, 152h				; o nazwie spod DS:DX - "blood2.exe"
seg000:0150		jmp short 1015Dh
seg000:0152		db 'blood2.exe',0
seg000:015D		int 21h						; (1)
seg000:015D
seg000:015F		jnb short FileOpen			; jak sie powiedzie to skok
seg000:015F
seg000:0161		mov ah, 9					; wyswietlenie komunikatu na ekran
seg000:0163		mov dx, 168h				; string musi byc zakonczony "$"
seg000:0166		jmp short 1018Eh
seg000:0168		db 'blood2.exe not found or is read-only!$'
seg000:018E		int 21h
seg000:018E
seg000:0190		mov ax, 4C01h				; zakonczenie procesu z kodem wyjscia 1
seg000:0193		int 21h

Miksowanie kodu programu i danych w plikach COM jest rzeczą najzwyklejszą choć czyta się to trochę dziwnie, bo pełno skoków pomijających stringi.

Gdy plik zostanie już poprawnie otwarty, wykonywane jest pobranie jego rozmiaru. Potrzebne jest to do walidacji. Rozmiar pobierany jest za pomocą typowej sztuczki. Polega ona na przesunięciu wskaźnika pozycji w pliku na jego koniec i odczytania bieżącej pozycji zwracanej przez funkcję po poprawnym wykonaniu operacji.

seg000:0195 FileOpen:
seg000:0195		push ax
seg000:0196		push cs
seg000:0197		pop  ds
seg000:0198		jmp short 101A2h
seg000:0198
seg000:019A FileSizeL dw 0B800h				; wymagany rozmiar pliku
seg000:019C FileSizeH dw 19h				; 1 685 504 bajtow
seg000:019E CurPosH   dw 0					; zmienne tymczasowe do operacji
seg000:01A0 CurPosL   dw 0					; na pozycji pliku
seg000:01A2
seg000:01A2		pop  bx						; eee?
seg000:01A3		push bx
seg000:01A3
seg000:01A4		mov ax, 4201h				; ustawienie wskaznika pliku wzgledem biezacej pozycji
seg000:01A7		mov cx, CurPosH				; CurPos = 0, czyli na poczatek pliku
seg000:01AB		mov dx, CurPosL
seg000:01AF		int 21h
seg000:01AF
seg000:01B1		mov CurPosH, dx				; zapamietanie biezacej pozycji
seg000:01B5		mov CurPosL, ax				; wzgledem poczatku pliku [DX:AX]
seg000:01B5
seg000:01B8		mov ax, 4202h				; ustawienie wskaznika pliku wzglededm konca
seg000:01BB		xor cx, cx					; zerowanie CX i DX,
seg000:01BD		xor dx, dx					; czyli ustawienie na koniec pliku
seg000:01BF		int 21h						; w istocie pobranie rozmiaru pliku [AX:DX]
seg000:01BF
seg000:01C1		cmp ax, FileSizeH			; porownanie rozmiaru pliku
seg000:01C5		jnz short FileSizeError		; jesli inny niz spodziewany
seg000:01C7		cmp dx, FileSizeL			; to skocz do obslugi bledu
seg000:01CB		jnz short FileSizeError
seg000:01CB
seg000:01CD		mov ax, 4200h				; ustawienie wskaznika w pliku wzgledem poczatku
seg000:01D0		mov cx, CurPosH				; na wartosci poczatkowe
seg000:01D4		mov dx, CurPosL
seg000:01D8		int 21h
seg000:01D8
seg000:01DA		jmp short FilePatch			; i skok do dalszych operacji

W miedzy czasie, przed operacją wyznaczenia rozmiaru pliku, zapamiętywana jest bieżąca pozycja pliku w zmiennej tymczasowej CurPos, aby na koniec ja przywrócić do stanu początkowego. Ten kod może być zastanawiający. Bo czy naprawdę jest to konieczne? Funkcja DOS 3D otwierająca plik, wedle dokumentacji, po poprawnym wykonaniu swojej roboty, ustawia wewnętrzny pointer w pliku na jego początek. Także wydaje mi się, że jest to zbędne.

Prócz tego powyższy kod według mnie nie jest poprawny, jego działanie jest niezdefiniowane. Uchwyt do otwartego pliku przez funkcję 3D przerwania 21h [1], zwracany jest w rejestrze AX. Pozostale funkcje operujące na plikach pod DOS-em spodziewają się uchwytu w rejestrze BX, a tutaj nie ma żadnej interakcji z tym związanej. Jest tylko dziwny kod ze stosem [2], ale nie bardzo rozumiem do czego miałby on tutaj służyć. W dalszych (niżej) fragmentach kodu, uchwyt jest poprawnie przekazywany przez rejestr BX przy operacjach plikowych. Jest to zastanawiające. Może IDA coś pomieszała, ale nie potwierdza tego kod binarny – w HEX-ach jest podobnie, opcody się zgadzają. Może ktoś bardziej doświadczony w 16-bitowcach mógłby rozjaśnić sprawę.

Wracając do kodu, gdy plik ma inny rozmiar niż spodziewany, na przykład w sytuacji próby zcrackowania nie tej wersji pliku (inny patch), wyświetlany zostaje odpowiedni komunikat i proces zostaje zakończony z kodem wyjścia 1, oznaczającym błąd:

seg000:01DC FileSizeError:
seg000:01DC		jmp short 101F4h
seg000:01DE		db 'Incorrect filesize!',0Dh,0Ah,'$'
seg000:01F4		mov ah, 9					; wyswietlenie na ekranie
seg000:01F6		mov dx, 1DEh				; wskazanego komunikatu
seg000:01F9		int 21h
seg000:01F9
seg000:01FB		mov ax, 4C01h				; zakonczenie procesu z kodem wyjscia 1
seg000:01FE		int 21h

A ddy walidacja rozmiaru pliku zakończyła się poprawnie, lecimy dalej…

seg000:0200 FilePatch:
seg000:0200		pop  ax						; pobranie uchwytu pliku (3)
seg000:0201		mov  bx, ax
seg000:0203		push ax
seg000:0203
seg000:0204		mov ah, 42h					; ustawienie wskaznika w pliku
seg000:0206		mov al, 0					; wzgledem poczatku
seg000:0208		mov cx, 0					; na pozycje 1086
seg000:020B		mov dx, 43Eh
seg000:020E		int 21h
seg000:020E
seg000:0210		pop  ax						; pobranie uchwytu pliku
seg000:0211		mov  bx, ax
seg000:0213		push ax
seg000:0213
seg000:0214		mov ah, 40h					; zapisywanie do pliku
seg000:0216		mov cx, 2					; 2 bajtow
seg000:0219		mov dx, 21Eh				; z tego miejsca
seg000:021C		jmp short 10220h
seg000:021E		dw 9090h					; NOP NOP (4)
seg000:0220		int 21h

Tutaj bez problemów wyłaniają się fragmenty kodu związane z uchwytem pliku, przez kooperacje na rejestrach AX i BX [3]. Kod ten można byłoby uprościć wrzucając do jakieś zmiennej w pamięci uchwyt do pliku lub trzymać go w rejestrze BX od razu po jego otwarciu. To drugie tylko w sytuacji, gdy żadne inne operacje nie modyfikują tego rejestru. Nie pamiętam, czy jakieś funkcje IO na plikach zwracają coś w tym rejestrze.

Wskaźnik w pliku przesuwany jest na pozycję odpowiadającą 1086 bajtowi, pod która zapisywane są 2 bajty danych. Te zapisywane dane to dokładnie 2 opcody instrukcji NOP, a pozycja, pod która są zapisywane – 0x043E, to znany z pierwszej części offset do miejsca wystąpienia instrukcji jz short loc_401050.

Ciekawą uwagą wartą wspomnienia, jest fakt, że miejsce przechowywania danych do zapisania w pliku [4] IDA w pełni świadomie i inteligentnie potraktowała jako operacje NOP, uznając że następuje wyrównanie pamięci do 4-ki. Wstawiając w tym miejscu stosowną informacje:

seg000:021E		align 4

W rzeczywistości znajdują się tam dane, jak zaprezentowano w kodzie powyżej.

Na koniec zamykany jest plik, wyświetlamy stosowny komunikat mówiący o pomyślnej modyfikacji pliku i następuje zakończenie procesu z kodem wyjscia równym 0, który świadczy o pozytywnym zadziałaniu.

seg000:0222		pop ax						; pobranie uchwytu pliku
seg000:0223		mov bx, ax
seg000:0225		mov ah, 3Eh					; zamkniecie pliku
seg000:0227		int 21h
seg000:0227
seg000:0229		mov ah, 9					; wyswietlenie komunikatu na ekranie
seg000:022B		mov dx, 230h
seg000:022E		jmp short 10241h
seg000:0230		db 'Patch applied.',0Ah, 0Dh,'$'
seg000:0241		int 21h
seg000:0241
seg000:0243		mov ax, 4C00h				; zakonczenie procesu z kodem wyjscia 0
seg000:0246		int 21h

Podsumowując powyższą analizę, kod bardzo prosty. Mówiąc prosto z mostu, szalu nie ma.
Modyfikuje kod binarny gry, w taki sam sposób, jaki zrobiłem to ręcznie w pierwszej części. Bo jak wspomniałem w tamtej notatce, jest to najprostsze i najszybsze rozwiązanie, które działa i rozwiązuje problem. A przy tym nie wymaga zbytniej ingerencji i głębszej analizy innych fragmentów kodu.

Moje 32 bity

Jako uzupełnienie analizy, postanowiłem napisać własnego cracka, oczywiście w 32 bitach i w asemblerze. Czemu tak? Bo w końcu to tylko kilka wywołań funkcji, a fajnie czasem jest cos napisać na niskim poziomie. W tworzonym programie nie chciałem uzależniać się od jakiejkolwiek biblioteki (np. C run-time), więc skorzystałem jedynie z API systemowego. Dzięki temu kod wynikowy wynosi dokładnie 1 KB.

format PE GUI 4.0
include 'win32a.inc'
 
	push 0
	push FILE_ATTRIBUTE_NORMAL
	push OPEN_EXISTING
	push 0
	push FILE_SHARE_READ or FILE_SHARE_WRITE
	push GENERIC_READ or GENERIC_WRITE
	push FileName
	call [CreateFile]
 
	cmp eax, INVALID_HANDLE_VALUE
	jne FileOpen
 
	mov eax, FileNotFound
	jmp short ErrorExit
 
FileOpen:
	mov ebx, eax
 
	push NULL
	push ebx
	call [GetFileSize]
 
	cmp eax, [FileSize]
	jz FilePatch
 
	mov eax, IncorrectSize
	jmp short ErrorExit
 
FilePatch:
	push FILE_BEGIN
	push 0
	push [PatchPos]
	push ebx
	call [SetFilePointer]
 
	push 0
	push tmp
	push [PatchSize]
	push PatchData
	push ebx
	call [WriteFile]
 
	push ebx
	call [CloseHandle]
 
	push MB_OK
	push MessageTitle
	push PatchAppiled
	push 0
	call [MessageBox]
 
	mov eax, 0
	ret
 
ErrorExit:
	push MB_OK
	push MessageTitle
	push eax
	push 0
	call [MessageBox]
 
	mov eax, 1
	ret
 
tmp				dd 0
FileSize		dd 19B800h
PatchPos		dd 43Eh
PatchSize		dd 2h
PatchData		db 90h,90h
 
FileName		db "blood2.exe", 0
MessageTitle	db "Blood2: Crack me!", 0
FileNotFound	db "The blood2.exe file not found!", 0
IncorrectSize	db "Incorrect filesize!", 0
PatchAppiled	db "Patch applied!", 0
 
data import
 
	library \
		kernel32, 'kernel32.dll', \
		user32, 'user32.dll'
 
	import user32, \
		MessageBox, 'MessageBoxA'
 
	import kernel32, \
		CreateFile, 'CreateFileA', \
		GetFileSize, 'GetFileSize', \
		SetFilePointer, 'SetFilePointer', \
		WriteFile, 'WriteFile', \
		CloseHandle, 'CloseHandle'
 
end data

Po składni, niektórzy mogą się domyślić, że użyłem FASM-a. Nigdy nie miałem z nim styczności, ale trafiwszy na niego w sieci, uznałem, ze warto spróbować, i tak się potoczyło. Ja głownie swoje zabawy wykonuję w NASM-mie lub MASM-ie, a najwięcej to w debugerze z VS, czy IDA.

Kod jest poprawny i działający, ale można byłoby go ulepszyć. Przede wszystkim podzielić na sekcje danych, kodu, itd. Do tego FASM udostępnia makra i ciekawą składnie, usprawniająca tworzenie programów w tym niskopoziomowym języku. Głównie mam tutaj na myśli operacje invoke, która pozwoliłaby na zamianę standardowych wywołań funkcji przez zrzucanie na stos argumentów i skoku do procedury poprzez call, do prostej linii:

invoke func, arg1, arg2, arg3, ...

Na pewno skróciłoby to znacznie kod źródłowy, ale tak się składa, że bardziej jestem przyzwyczajony przez różnego rodzaju zabawy z re do ‘normlanej’ metody, więc trzymałem się własnych przyczajeń.

Słowem zakończenia…

Mimo prostego kodu, analiza była bardzo ciekawa, poznając funkcje DOS-owe przerwania 21h, trochę frajdy z tym było. Osobiście nigdy w życiu nie miałem okazji napisania w asemblerze 16 bitowego kodu pod DOS-a, więc wydało mi się to fajną zabawą i poniekąd nauką. Choć mimo wszystko to już trochę leciwa technologia. Ale zawsze cos ciekawego człowiek się dowie. Mimo iż to tylko analiza.

Napisanie wersji 32-bitowej w asemblerze, też było ciekawym doświadczeniem. Mimo prostoty (jak wyżej), stworzenie całego programu w asemblerze, a nie tylko krótkie wstawki, czasami jest dobrym pomysłem. Na pewno szare komórki się przewietrzą.

Jedna mała uwaga, w czasie pisania tego tekstu, udało mi się znaleźć jeszcze kilką programów łamiących zabezpieczenie blooda. I niekoniecznie były to dosowe aplikacje, trafiła się jedna nawet z 32-bit GUI. No ale, w międzyczasie już skupiłem się na tym problemie i osobistym udziale, postanowiłem się trzymać planu.

Pozostało jeszcze trochę ciekawych rzeczy do sprawdzenia i przeanalizowania w kodzie gry, dotyczących zabezpieczenia i mechanizmu wykrywania nośnika w napędzie. O tym wkrótce w kolejnej (prawdopodobnie ostatniej) części.

Podobnie, jak w pierwszej części, wszystkie przedstawione materiały służą jedynie celom poznawczym i edukacyjnym.

Blood2: Crack me!

10 października 2014

Jak zapewne niektórzy zauważyli na moim twitterze, (który staje się mini blogiem), ostatnio – tweet – uruchamiałem taką starą, wspaniałą grę z przełomu milenium, jaką jest Blood2: The Chosen. W młodości trochę w nią grywałem, jakiś sentyment pozostał. A że chciałem się trochę zrelaksować w weekend, a przy okazji spróbować skonteneryzować i uruchomić tą gierkę […]

czytaj całość »

Portfel akcji 3Q 2014

1 października 2014

Kolejny kwartał za nami, pora na krótkie przedstawienie wyników moich akcyjnych portfeli, małą analizę i być może jakieś trafne wyciagnięcie wniosków, które mogą pomoc skonkretyzować plan działania na najbliższy czas. Może od razu przejdźmy do meritum. Sytuacja na GPW Nastroje na GPW umiarkowane, momentami Ukraina i Rosja nadal lubią postraszyć inwestorów polskiego rynku, ale nie […]

czytaj całość »

Portfel akcji 2Q 2014

1 lipca 2014

Kolejny kwartał moich zmagań na rynku akcji za nami wymaga chociażby małego podsumowania. Niestety wciąż napięta sytuacja na wschodzie Ukrainy odciska piętno na GPW. Co skutkuje takimi, a nie innymi wynikami. Ale główny cel, jakim jest staranie się wyjść, w najgorszym przypadku, w okolicach zera, a najlepiej oczywiście nad nim, udało jako tako się spełnić. […]

czytaj całość »

Sezon dywidendowy rozpoczęty

13 kwietnia 2014

Jedna z inspiracji dla mojego prywatnego funduszu emerytalnego było oparcie części aktywów akcyjnych na strategii dywidendowej. Szerzej o tym pisałem w memo odnośnie ukierunkowania się i spróbowania swoich sił na rynku GPW. Strategia oparta na stabilnych spółkach dzielących się swoimi zyskami z akcjonariuszami, wydaje się być jedną z głównych strategii, jakie można spotkać w długoterminowej […]

czytaj całość »

Metodologia wyceny portfela

5 kwietnia 2014

Jednym z kluczowych problemów dotyczących inwestowania jest pomiar i ocena wyników zarządzania portfelem inwestycji. Pierwszym i najbardziej popularnym sposobem jest wyznaczenie stopy zwrotu i porównanie jej do benchmarku. O ile wyznaczenie stopy zwrotu ze stałych, czy jednorazowych inwestycji jest sprawą prostą, to problemem może być określenie stopy zwrotu z portfela, w którym ciągle coś się […]

czytaj całość »

Portfel akcji 1Q 2014

1 kwietnia 2014

Mam już za sobą pierwszy, pełny kwartał bojów na GPW, więc niejako wymusza to szybką analizę działania wraz z podsumowaniem i oceną wyników, jakie udało mi się osiągnąć w tym czasie na warszawskim parkiecie. W istocie moje „zabawy” i eksperymenty z rynkiem akcyjnym zacząłem pod koniec zeszłego roku, ale dopiero miniony kwartał wydaje się bardziej […]

czytaj całość »

Agresja NATO, czy Rosji, na tle Ukrainy

9 marca 2014

Starałem się odcinać od polityki, ale czasami niestety nie udawało mi się do dobrze, czego przykładem może być kilka wpisów na blogu, będące jakiegoś rodzaju komentarzem lub wynurzeniem własnych myli i poglądów. Przez długi czas żyłem poza tym co dzieje się wokół mnie w kraju na świecie, poniekąd ignorancja, a także z powodu braku do […]

czytaj całość »

Co słychać w nadchodzącym C++14

5 marca 2014

Powolnymi, acz zdecydowanymi krokami zbliża się nowy standard języka C++14.Niektorzy jeszcze nie oswoili się z C++11, a biznes ciągle w epoce kamienia łupanego – C++98/03, bądź „C z klasami”, a wkrótce kolejna dawka nowości i emocji. Od czasu wejścia obecnego standardu, komitet nieźle przyspieszył, można powiedzieć, że wreszcie chce nadążać za rynkiem i potrzebami, planując […]

czytaj całość »

Portfel inwestycyjny

16 lutego 2014

Przyszedł taki czas, aby trochę mocniej zastanowić się nad składem swojego portfela i zrewidować poglądy na ten temat. A wszystko to za sprawą trafienia niedawno na kilka artykułów w sieci, choć jakiekolwiek akcję wywołał podcast WNOP019 na temat budowania portfela i strategii inwestycyjnej, opublikowany przez Michała i Zbyszka, w ramach serii artykułów i eksperymencie przez […]

czytaj całość »

miniBlog

malcom.pinger.pl
23:24:40 27/03/2014
Po dluzszej przerwie, dzisiejszy wypiek chleba, mozna zaliczyc do najlepszego ;)
00:04:03 08/01/2013
Taki tu spokoj.... sialala...
23:37:56 16/09/2012
A gdzie C64?... :(
http://www.youtube.com/watch?&v=3qaF9-W2Dvg
14:45:25 15/09/2012
Moze czas znalezc jakies inne miejsce na mini-bloga? A moze dodac cos do samego devbloga... a moze czas na blipa, twittera? Bo cos tutaj zycie zamarlo...
20:00:55 01/09/2012
Powrot w blasku i chwale na MaldevBlogu ;)
11:54:50 02/06/2010
Wreszcie kilka dni odpoczynku w domku ;)
22:15:23 07/03/2010
Powrot do zycia ;)
19:32:00 04/01/2010
first day on a new job ;)
18:33:32 14/12/2009
Popularnosc jezykow programowania
http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
17:54:43 02/12/2009
Moge powiedziec poki co tylko tyle ze intro i muzyka z #Paradox mi sie wybitnie podoba ;p
01:35:01 02/12/2009
Lin Xu przedstawia nowe usprawnienia optymalizacyjne w VC2k10:
http://blogs.msdn.com/vcblog/archive/2009/12/01/gl-and-pgo.aspx
13:35:46 01/12/2009
Secret #Perl Operators
http://www.catonmat.net/blog/secret-perl-operators/
15:58:58 30/11/2009
Interlocked* Win32 - ciekawe zadanie dla chetnych ;p
http://groups.google.pl/group/pl.comp.lang.c/browse_thread/thread/c4ccf09a972ed50d
11:23:06 26/11/2009
W ostatnich dniach troche moich patchy do wxWidgets sie "przeforsowalo"...
23:00:04 22/11/2009
Troche sie rozczarowalem, mialem nadzieje, ze bedzie kontynuacja watku z ostatniego odcinka Stargate Universe...
22:14:56 21/11/2009
Pwtornie motyw "Polscy chłopcy w językach obcych" w Strefa rokendrola wolna od angola na "trocjce" ;)
14:35:39 17/11/2009
"People often write less readable code because they think it will produce faster code. Unfortunately, in most cases, the code will not be faster."
Krotka prezentacja o tym co potrafia wspolczesne kompilatory (odnosnie optymalizacji):
http://www.linux-kongress.org/2009/slides/compiler_survey_felix_von_leitner.pdf
01:10:43 17/11/2009
The Pirate Movie - swietny film z swietnym soundtrackiem, szczegolnie utwor (Song of) Victory.
Dla odmiany nieco metalowa wersja, cover Mayhayrona
http://www.youtube.com/watch?v=Ud8uAKW3U4o
00:11:46 08/11/2009
Bezstykowe karty Mifare sa bardzo wygodne w uzyciu. Gorzej jak ma sie ich kilka np. w portfelu (legitymacja, karta miejska) i chce sie jednej uzyc bez wyjmowania... co ostatnio doswiadczylem przy bramkach na WAT-cie. Zapewne przy metrze i kasownikach bedzie podobnie ;p
01:14:00 06/11/2009
Dziwny swiat, dziwni ludzie, teraz beda dublowoac wszelkie swoje "smieci" w sieci.
Moze warto zintegrowac rowniez wiekszosc for dyskusyjnych i wysylajac na jedno, wysylac na pol sieci?
23:10:46 20/10/2009
Ostatnio babralem sie z COM i XPCOM przy embedowaniu #IE i #Gecko do prostej aplikacji. Moze w xime oprze API na czyms podobnym... Latwe i przyjemne uzywanie spod C++ i C, czyli zewszad ;)
20:48:44 13/10/2009
Musialem napisac co mysle o nowym #tlen, bo nie potrafilem dluzej sie powstrzymac, przepraszam.
http://ekipa.tlen.pl/forum/index.php?showtopic=11310
10:38:53 12/10/2009
Kolumna "This Week in Boost" na "C++Next" mam nadzieje, ze bedzie ciekawa ;p
http://cpp-next.com/archive/2009/10/introducing-%e2%80%9cthis-week-in-boost%e2%80%9d/
13:53:47 06/10/2009
Polskie brzmienia w lacisnkim rocku - Amaryllis ;)
Mi szczegolnie przypadl do gustu utwor "Magnificat".
12:03:14 06/10/2009
Podazajac kierunkiem ostatniej wolnej strefy - "Polscy chłopcy w językach obcych", dzisiejsze poludnie sponsoruje Percival Schuttenbach ;)
http://www.youtube.com/watch?v=uQvvE5qNxi4
http://www.youtube.com/watch?v=Gb36Qyq8DyY
09:15:37 06/10/2009
Paskudny ten #tlen na #qt, kontrolki takie bleee, emulwoane/malowane nijak maja sie do natywnych.
18:22:56 29/09/2009
s2s @ #tlen jest online [via kaworu]
19:50:34 25/09/2009
Maly bug w wx'ach, a juz chcialem klnac na MS...
13:26:02 23/09/2009
Dla tych, ktorzy wciaz nie wiedza, ze jabber != xmpp ;p
http://forum.jabberpl.org/index.php?showtopic=7380
23:05:32 22/09/2009
Na USiu tez mnie "chca", ale zostane przy WAT, tylko 2x drozej ;p