27

Mar

by pi3

LKRG 0.2 was just released and the announcement note can be found here:

http://openwall.com/lists/announce/2018/03/27/1

Read more

9

Feb

by pi3

LKRG 0.1 was just released:

http://www.openwall.com/lkrg/

The change log is as follows:
Read more

I’m happy to announce that my moonlight project is finally released. Thanks to Alexander Peslyak (a.k.a. Solar Designer) it is available through Openwall.

Linux Kernel Runtime Guard (LKRG) is a loadable kernel module that performs runtime integrity checking of the Linux kernel and detection of security vulnerability exploits against the kernel. As controversial as this concept is, LKRG attempts to post-detect and hopefully promptly respond to unauthorized modifications to the running Linux kernel (integrity checking) or to credentials (such as user IDs) of the running processes (exploit detection). For process credentials, LKRG attempts to detect the exploit and take action before the kernel would grant the process access (such as open a file) based on the unauthorized credentials. You can download the current experimental version of LKRG at its brand new homepage:

http://www.openwall.com/lkrg/

LKRG has been in (re-)development for a couple of years, and builds upon one of my prior’s experience with a related project in 2011 (for CERN).

Official announcement had been made by Openwall and it can be read here:
http://www.openwall.com/lists/announce/2018/01/29/1

A lot of useful technical information about LKRG can be found on Openwall wiki page:
http://openwall.info/wiki/p_lkrg/Main

If you would like to support LKRG, you are very welcome to do so 😉 It can be done via Patreon website here:
https://www.patreon.com/p_lkrg

Best regards,
Adam ‘pi3’ Zabrocki

23

Sep

by pi3

Linux kernel programming is always a challenge. Especially, when you are playing with very low-level functionality (like manually sending IPI between the CPUs/cores). Unfortunately, this specific functionality kept making troubles for me for a couple of weeks and I haven’t found ANY information on the internet regarding the issue which I hit/met. That’s why I decided it could be useful for other people if I describe my journey with the APIs like smp_call_function_single() / on_each_cpu(), NMI watchdog which can kill correct task and do not inform about problematic CPU/core etc. I’ve been discussing this issue with Alexander (Solar Designer) and he has started a discussion about that on Linux Kernel Mailing List (LKML) which you can find here:

http://lkml.iu.edu/hypermail/linux/kernel/1609.2/03265.html

Thanks,
Adam

Hi,

The journey into CVE-2014-9322 is not straightforward but it is worth to spend some time on it and analyze all available information. I will try my best…

Read more

At the beginning I want to inform all my blog readers this post is in polish language because it refers to the situation in Poland.

Na wstępie chciałbym zaznaczyć, że czuję się osobą kompetentną do napisania poniższej analizy. Dla osób, które nie mają zielonego pojęcia, kim jestem przedstawię swój skrócony życiorys zawodowy. Pracuje w branży bezpieczeństwa informatycznego od 2004 roku. Moimi pracodawcami były takie firmy / instytucje jak Hispasec (pracowałem razem z Gynvael Coldwind, Mateusz ‘j00ru’ Jurczyk, Marcin ‘Icewall’ Noga), Europejska Organizacji Badan Jądrowych w Szwajcarii (m.in. pracowałem przy projektach zabezpieczania i rozwijania technologii GRID (np. WLCG, EGEE) oraz projektów takich jak LHC i zajmowałem się m.in. hardeningiem jądra systemu Linux na potrzeby owej organizacji), wykonywałem pentesty i byłem konsultantem dla sporej liczby banków w Polsce jak i za granicą. Byłem architektem bezpieczeństwa w jednym z największych banków inwestycyjnych. Wrocławskie Centrum Sieciowo-Superkomputerowe również dało mi możliwość pracy i uczestniczenia w ciekawych projektach naukowych gdzie starałem się dołożyć swoją cegiełkę bezpieczeństwa. Obecnie pracuje dla Microsoftu w teamie MSRC (grupa Detection & Defence), wcześniej byłem w teamie Science. To tak w dużym skrócie, ponieważ nie jest to temat owego wpisu.

Chciałbym również zaznaczyć, że nie jestem lingwistą, nigdy nie byłem, oraz jestem świadom tego, że popełniam wiele błędów ortograficznych jak i gramatycznych. Nie jest to odpowiednie miejsce na wypominanie mi tego typu pomyłek, ponieważ zaznaczam, że nie jest to nijak związane z tematem, który chcę tutaj poruszyć. Jeżeli masz jakieś kompleksy lingwistyczne to udzielaj się na forach językowych bądź przeprowadzaj konsultacje z prof. Miodkiem. Nie bardzo mnie to interesuje – więc nie wylewaj tu swoich żali językowych.

 

W sobotę (6 kwietnia) miała miejsce nietypowa sytuacja. Otóż bardzo popularny serwis informacyjny (nie techniczny) niebezpiecznik.pl został pośrednio “zhackowany” (świadomie używam cudzysłowu). Otóż z technicznego punktu widzenia, cytując w/w serwis:

“(…) nikt nie przełamał zabezpieczeń Niebezpiecznika, ale włamał się na serwery jednej z firm, z którą współpracujemy i do której to (nie tylko my) odwołujemy się poprzez załączenie skryptu (…)”.

Konsekwencją tego działania było automatyczne przekierowanie na stronę Pastebin zaraz po załadowaniu się serwisu. Zostało to natychmiast zauważone przez polską społeczność internetowa i całe zdarzenie stało się bardzo medialne. Taka sytuacja wynika z wielu czynników. Otóż niebezpiecznik.pl jest blogiem/serwisem niezwykle popularnym. Właśnie ze względu na swój informacyjny (nie techniczny) charakter. Serwis stał się na tyle popularny, że często jest cytowany w mediach głównego nurtu. Zarówno na stronach internetowych jak i poza nimi.

Dodatkowo ekipa projektu niebezpiecznik.pl (w szczególności jego twórca Piotr Konieczny) organizuje wiele szkoleń (płatnych) z zakresu bezpieczeństwa (rożna tematyka). Sprzedaje usługi związane z bezpieczeństwem (testy penetracyjne, audyty, consulting), oraz często jest zapraszany na konferencje gdzie prowadzi wykłady.

Wyżej wymienione czynniki spowodowały swoistą “eksplozję emocji” na temat zaistniałej sytuacji. Jak to się ma do wizerunku serwisu samego w sobie? Swoiste “guru” bezpieczeństwa oraz “wpadka” ze “zhackowanym” serwisem? Dodatkowo strona, na którą było przekierowanie zawierała kontrowersyjny “manifest”. Znajduje się w nim wiele krytyki oraz kontrowersyjnych wniosków.

Moim celem nie jest analizowanie tego manifestu, ani szukaniu potwierdzenia czy też zaprzeczenia postawionych tez, lecz analiza faktu “podważenia społecznego zaufania” do serwisu. Chciałbym się skupić na czymś zupełnie innym. Na czymś, co mnie, jako osobę, która stara się trzymać od tego typu gierek (tak, to są wg mnie gierki) z daleka. Chodzi mi o próbę zbagatelizowania zaistniałej sytuacji przez twórców serwisu i nie przedstawieniu, jakie mogłyby być potencjalne (i zarazem poważne) skutki dokładnie tego ataku. To, że autorzy ataku ich nie zastosowali, lecz wykorzystali do pokazania światu swojego manifestu w cale nie jest wystarczającym powodem by minimalizować zaistniałą sytuację!

 

Skutki ataku

Z punktu widzenia końcowego użytkownika, (czyli zwykłego zjadacza chleba, który odwiedza stronę niebezpiecznik.pl) atak miał takie same skutki jak podmiana strony, czy tez idąc dalej, takie jak atak na serwery DNS. Otóż użytkownik w konsekwencji odwiedził nie ten zasób, który chciał, pomimo że spełnił wszystkie wymagane od niego, z punktu widzenia bezpieczeństwa, zalecenia. Otóż użytkownik NIE BYŁ zainfekowany żadnym złośliwym oprogramowaniem (rootkit / malware), miał prawidłowo poustawiane serwery DNS, prawidłowo wpisał domenę (nie było żadnych literówek, czy też przekłamań bajtów/bitów nawet z tak abstrakcyjnych przyczyn jak promieniowanie kosmiczne). Z tych właśnie powodów użytkownik UFA odwiedzonym zasobom. Pomimo tego, zaufanie zostało złamane i całkowicie inne treści zostały przesłane. Atakujący wybrał proste i niegroźne dla użytkownika przekierowanie na jego manifest, ale wcale nie musiał tego zrobić. Mógł być bardziej złośliwy…

Z mojego punktu widzenia, poważna sytuacja jest, tak na prawdę bagatelizowana. Czy w sytuacji, gdy ktoś podmieni wpisy w DNS (tudzież wykona udany atak DNS Poisoning) również będziemy mówić o niegroźnej sytuacji, jeśli wpisy w DNS również przekierują na manifest w serwisie Pastebin? Jeśli ktoś przełamie zabezpieczenia serwera (nie ważne czy zdobędzie konto administratora czy nie) i podmieni stronę fizycznie na serwerze, która będzie przekierowywać na manifest w serwisie Pastebin, również będziemy bagatelizować? Czy też nawet porównując absurdalnie do ataków typu phishing (absurdalnie, ponieważ w atakach typu phishing zazwyczaj potrzeba zmusić użytkownika do wykonania specyficznej operacji, w tym ataku wszystko było automatyczne), które przekierują na Pastebin z manifestem też to zbagatelizujemy? Otóż wg mnie NIE! Konsekwencje wszystkich z wyżej opisanych ataków są dokładnie takie same! Użytkownik łączy się z serwerem z “czystej”, niezainfekowanej maszyny, prawidłowo wpisuje domeny i prawidłowo inicjalizuje połączenie, w każdym z w/w ataków otrzymałbym inną treść niż spodziewana…

 

W takim razie, jeśli nie przekierowanie na Pastebin, to co?

Otóż atakujący miał ogrom możliwości. Ponieważ serwis niebezpiecznik.pl jest serwisem niezwykle popularnym, naturalną rzeczą jest zaatakowanie wszystkich jego użytkowników. Można to zrobić na różne sposoby. Atakujący mógł wstrzyknąć kod JavaScript, który serwowałby nieznane ataki na aplikacje (0day) np. Java, Flash, etc i wówczas taki exploit po udanym ataku może ściągnąć złośliwe oprogramowanie (rootkit / malware) i zainstalować na maszynie ofiary. Taki scenariusz ataku nosi nazwę drive-by-download i jest dość popularny właśnie ze względu na zaufanie, jakie mają serwery wśród użytkowników. W ciągu paru sekund taki scenariusz mógłby stworzyć niezły botnet z komputerów użytkowników odwiedzających serwis niebezpiecznik.pl. Nie ma tu żadnej różnicy, jaką metodą byłby serwowany złośliwy kod JavaScript. Każdy z opisywanych ataków (włączając ten, który dotyczył serwisu niebezpiecznik.pl) miałby ten sam skutek!

Inny scenariusz, który mógłby zaistnieć, to stworzenie dokładnej kopi 1: 1 serwisu niebezpiecznik.pl na kontrolowanej przez atakującego maszynie i tam przekierować odwiedzających. Również takie działanie ma ogromne konsekwencję! Ponieważ strona jest całkowicie i w każdym detalu kontrolowana przez atakującego, więc mógłby na przykład podmienić przycisk “like” facebook’a w taki sposób by przekierowało na fałszywą stronę logowania do serwisu facebook i ukraść dane z formularza logowania. Oczywiście są różne inne opcje wykorzystania tej sytuacji – ten jest jednak najbardziej obrazowy dla szarego użytkownika.

Innym wartościowym atakiem jest zaatakowanie odnośników na stronie niebezpiecznik.pl., Jakie? Przyjrzyjcie się odnośnikowi “Kontakt”, “Audyty & Pentesty” oraz “Reklama”. Najpierw “Kontakt”:

kontakt

Serwis informuje, że potrafi chronić tożsamość swoich informatorów. Jeżeli przekierujemy połączenie na stronę całkowicie kontrolowaną przez atakującego, wówczas można stworzyć 1: 1 kopie tego formularza, który wysyłałby wszystkie informacje do atakującego zamiast do serwisu. Wówczas informator myślałby, że jest chroniony przez serwis niebezpiecznik.pl, a w konsekwencji nic takiego nie miałoby miejsca. Tylko w kwestii atakującego byłoby to, czy poinformować serwis, że takie zgłoszenie było (poprzez forwardniecie tego, co przechwycił) czy tez nie. A komu on te dane by ujawnił, to już decyzja atakującego.

O wiele gorsza sytuacja mogłaby zaistnieć w pozostałych odnośnikach. Najpierw “Audyty & Pentesty”:

pentest

Mając kontrole nad tym formularzem, atakujący miałby możliwość wykradzenia wszystkich potencjalnych klientów serwisowi niebezpiecznik.pl. Przechwytując takie dane i informacje o chęci uczestnictwa w szkoleniu, można przedstawić konkurencyjną i lepszą (finansowo) ofertę, oraz przy okazji zrobić czarny PR dla serwisu, że firma sprzedająca usługi bezpieczeństwa nie potrafi zadbać o swoje własne. Takie działanie miałoby katastrofalne skutki dla serwisu niebezpiecznik.pl. De facto takie samo zagrożenie istnieje dla zakładki “Szkolenia”:

szkolenia

Mało tego, występują tutaj komentarze od zadowolonych klientów. Kontrolując tę stronę, można również zastosować czarny PR i opublikować wpisy niekorzystne serwisowi.

Jeżeli chodzi o odnośnik “Reklama”:

reklama

Atakujący mógłby zrobić psikusa poprzez podmianę cennika oraz adresu email kontaktowego na całkowicie arbitralny…

Nie muszę wspominać, że jeśli była możliwość stworzenia niewidzialnego <iframe> na oryginalnej stronie niebezpiecznik.pl i “przesłonić” oryginalne przyciski, wówczas atak mógłby być praktycznie niezauważony przez długi czas i byłby tragiczny w skutkach dla serwisu.

 

 

Dlaczego powstał ten wpis? Jaki miał cel?

Nie mam nic przeciwko serwisowi niebezpiecznik.pl ani jego właścicielowi (Piotrowi). De facto znamy się i kojarzymy. Nie mam zamiaru oceniać manifestu, który został zamieszczony, ani samej przyczyny ataku. Nie mniej jednak próba bagatelizowania zaistniałego problemu z mego punktu widzenia jest niewłaściwa. Miedzy innymi z tego względu, że osoby nieobeznane w temacie mogą sobie nie uświadamiać, jakie potencjalne skutki może nieść nawet taki atak, jaki dotknął serwis niebezpiecznik.pl. Jest to o tyle zgubne, że takie osoby mogą uwierzyć w to, że tak naprawdę nic się nie stało i nigdy nie będą na to uczulone. Takie zachowanie jest błędne! Atak miał miejsce i wg mnie mógł mieć bardzo wymierne i poważne skutki (zarówno finansowe dla serwisu niebezpiecznik.pl). Dodatkowo na samym początku tytuł wpisu na serwisie (niebezpiecznik.pl) poruszający zaistniały atak brzmiał następująco:

“Dołączyliśmy do grona największych :-) -- Niebezpiecznik.pl –“

W treści postu było ewidentne bagatelizowanie zaistniałej sytuacji i próba uwypuklenia, że nie zostało nic złamane po stronie serwera niebezpiecznik.pl i nie są oni za nic odpowiedzialni w tej sytuacji. Jednak prawdopodobnie po paru nieprzychylnych komentarzach na serwisach społecznościach temat postu został zmieniony na:

“Mogło być gorzej, czyli zastanów się do których skryptów się odwołujesz”

Natomiast w treści postu został dodany element humorystyczny:

“Można dowcipnie powiedzieć, że dołączyliśmy do grona najlepszych ;)”

Została więc ewidentnie zmieniona retoryka wypowiedzi, natomiast dalej nie zauważyłem merytorycznego wyjaśnienia potencjalnych skutków ataku, a jedynie zmniejszenie uwypuklenia bagatelizowania problemu.

 

Właśnie merytoryczne wyjaśnienie potencjalnych skutków jest jedyną przyczyną napisania tego długiego postu. Jeszcze raz chcę podkreślić ze nie mam nic przeciwko opisywanemu serwisowi…

 

Ps. Cytat kolegi na temat postu w serwisie niebezpiecznik.pl poruszający włamanie:

 “Dostałem dziś w pysk dołączając tym samym do grona najlepszych, którzy dostali kiedyś w pysk: Mike Tyson, Andrzej Gołota, Evender Holyfield i sam Muhammad Ali.”

 

Pozdrawiam,

Adam ‘pi3’ Zabrocki

20

Feb

by pi3

As some of you know I am(was) active developer in ERESI project. ERESI stands for The ERESI Reverse Engineering Software Interface, its web page stands at: www.eresi-project.org.

eresi-logo

 

For those who do not know the project, The ERESI Reverse Engineering Software Interface is a multi-architecture binary analysis framework with a domain-specific language tailored to reverse engineering and program manipulation.

  • Feature both user-mode and kernel-mode support for instrumentation, debugging and program analysis
  • Handle INTEL and SPARC machine programs (partial support for ARM, MIPS and ALPHA processors).
  • Designed for analysis of Operating Systems based on the Executable & Linking Format (ELF) in particular on the Linux OS.
  • Support many features on *BSD, Solaris, HP-UX, IRIX and BeOS.
  • Trace into any OS in a virtual machine or emulator using the GDB serial protocol.
  • Construct and display program graphs in native code as well as Intermediate Representation (IR) code
  • Does not need symbols or debug info to operate most of its features (but will use them if available in ELF/DWARF/STABS)
  • Inject or debug code that runs without executable data segment (PaX, Openwall, etc)
  • Prone modularity and reuse of code.

Here are the main programs that compose the ERESI framework:

  • elfsh : An interactive and scriptable static program instrumentation tool for ELF binary files.
  • kernsh: An interactive and scriptable runtime kernel instrumentation tool for live code injection, modification and redirection.
  • e2dbg : An interactive and scriptable high-performance process debugger that works without standard OS debug API (without ptrace).
  • •etrace : A scriptable runtime process tracer working at full frequency of execution without generating traps.
  • kedbg: An interactive and scriptable OS-wide debugger interfaced with the GDB server, VMware, Qemu, Boches and OpenOCD (JTAG) via the GDB serial protocol.
  • Evarista: A work-in-progress static binary program transformer entirely implemented in the ERESI language.

Beside those top-level components, ERESI contains various libraries that can be used from one of the previously mentioned tools, or in a standalone third-party program:

  • libelfsh : the binary manipulation library used by ELFsh, Kernsh, E2dbg, and Etrace.
  • libe2dbg : the embedded debugger library operating within the debuggee program.
  • libasm : the smart disassembling engine (x86, sparc, mips, arm) that gives both syntactic and semantic attributes to instructions and their operands.
  • libmjollnir : the control flow analysis and fingerprinting library.
  • librevm : the Runtime ERESI virtual machine, that contains the central runtime environment implementation of the framework.
  • libstderesi : the standard ERESI library containing more than 100 built-in analysis commands.
  • libaspect : the aspect library brings its API to reflect code and data structures in the ERESI language.
  • libedfmt : the ERESI debug format library which can convert dwarf and stabs debug formats to the ERESI debug format.
  • libetrace : the ERESI tracer library, on which Etrace is based.
  • libkernsh : the Kernel shell library is the kernel accessibility library on which Kernsh is based.
  • libgdbwrap : The GDB serial protocol library, for compatibility between ERESI and GDB/VMware/Boches/QeMu/OpenOCD.

ERESI is quite famous project. Many technical articles about ERESI was published on the phrack (#61, #63). In 2007 ERESI team gave a talk at Blackhat European Conference. In 2008 we gave invited talk at the SSTIC conference.

ERESI active development has restart as of February 2013. Most of our developers was very busy for last few years and unfortunately project wasn’t on the top of our priority. I hope now we will be able to finish our ideas and make up for lost time…

 

Best regards,

Adam

29 of November 2011 was the date of public disclosure interesting vulnerability in lighttpd server. Xi Wang discovered that mod_auth for this server does not propely decode characters from the extended ASCII table. The vulnerable code is below:

"src/http_auth.c:67"
--- CUT ---
static const short base64_reverse_table[256] = ...;
static unsigned char * base64_decode(buffer *out, const char *in) {
    ...
    int ch, ...;
    size_t i;
    ...

        ch = in[i];
        ...
        ch = base64_reverse_table[ch];
    ...
}
--- CUT ---

Because variable ‘in’ is type ‘char’, characters above 0x80 lead to negative indices. This vulnerability may lead out-of-boud read and theoretically cause Segmentation Fault (Denial of Service attack). Unfortunately I couldn’t find any binaries where .rodata section before the base64_reverse_table table cause this situation.

I have added some extra debug in the lighttpd source code to see if this vulnerability is executed correctly. Here is output for one of the example:

--- CUT ---
ptr[0x9a92c48] size[0xc0] used[0x0]
127(. | 0 | 0)
-128(t | 1 | 0)
-127(e | 2 | 1)
-126(' | 3 | 2)
-125(e | 4 | 3)
-124(u | 5 | 3)
-123(r | 6 | 4)
-122(' | 7 | 5)
-121(s | 8 | 6)
-120(c | 9 | 6)
-119(i | 10 | 7)
-118(n | 11 | 8)
-117(i | 12 | 9)
-116(  | 13 | 9)
-115(a | 14 | 10)
-114(t | 15 | 11)
-113(. | 16 | 12)
-112(e | 17 | 12)
-111(u | 18 | 13)
-110(r | 19 | 14)
-109(' | 20 | 15)
-108(f | 21 | 15)
-107(i | 22 | 16)
-106(e | 23 | 17)
-105(: | 24 | 18)
-104(= | 25 | 18)
-103(o | 26 | 19)
-102(t | 27 | 20)
-101(o | 28 | 21)
-100(  | 29 | 21)
-99(a | 30 | 22)
-98(g | 31 | 23)
-97(. | 32 | 24)
-96(d | 33 | 24)
-95(g | 34 | 25)
-94(s | 35 | 26)
-93(: | 36 | 27)
-92(u | 37 | 27)
-91(s | 38 | 28)
-90(p | 39 | 29)
-89(o | 40 | 30)
-88(t | 41 | 30)
-87(d | 42 | 31)
-86(b | 43 | 32)
-85(c | 44 | 33)
-84(e | 45 | 33)
-83(d | 46 | 34)
-82(( | 47 | 35)
-81(n | 48 | 36)
-80(y | 49 | 36)
-79(h | 50 | 37)
-78(d | 51 | 38)
-77(g | 52 | 39)
-76(s | 53 | 39)
-75(  | 54 | 40)
-74(r | 55 | 41)
-73(p | 56 | 42)
-72(a | 57 | 42)
-71(n | 58 | 43)
-70(. | 59 | 44)
-69(. | 60 | 45)
-68(d | 61 | 45)
-67(g | 62 | 46)
-66(s | 63 | 47)
-65(: | 64 | 48)
-64(( | 65 | 48)
-63(d | 66 | 49)
-62(- | 67 | 50)
-61(e | 68 | 51)
-60(s | 69 | 51)
-59(  | 70 | 52)
-58(i | 71 | 53)
-57(s | 72 | 54)
-56(n | 73 | 54)
-55(  | 74 | 55)
-54(i | 75 | 56)
-53(l | 76 | 57)
-52(. | 77 | 57)
-51(. | 78 | 58)
-50(k | 79 | 59)
-49(0 | 80 | 60)
-48(% | 81 | 60)
-47(] | 82 | 61)
-46(p | 83 | 62)
-45(r | 84 | 63)
-44(0 | 85 | 63)
-43(% | 86 | 64)
-42(] | 87 | 65)
-41(s | 88 | 66)
-40(z | 89 | 66)
-39([ | 90 | 67)
-38(x | 91 | 68)
-37(x | 92 | 69)
-36(  | 93 | 69)
-35(s | 94 | 70)
-34(d | 95 | 71)
-33(0 | 96 | 72)
-32(% | 97 | 72)
-31(] | 98 | 73)
-30(. | 99 | 74)
-29(. | 100 | 75)
-28(d | 101 | 75)
-27(c | 102 | 76)
-26(d | 103 | 77)
-25(i | 104 | 78)
-24(g | 105 | 78)
-23(b | 106 | 79)
-22(s | 107 | 80)
-21(6 | 108 | 81)
-20(- | 109 | 81)
-19(t | 110 | 82)
-18(i | 111 | 83)
-17(g | 112 | 84)
-16(f | 113 | 84)
-15(i | 114 | 85)
-14(e | 115 | 86)
-13(. | 116 | 87)
-12(. | 117 | 87)
-11(. | 118 | 88)
-10(. | 119 | 89)
-9(. | 120 | 90)
-8(. | 121 | 90)
-7(. | 122 | 91)
-6(. | 123 | 92)
-5(. | 124 | 93)
-4(. | 125 | 93)
-3(. | 126 | 94)
-2(. | 127 | 95)
-1(. | 128 | 96)
k[0x60] ptr[0x9a92c48] size[0xc0] used[0x0]
ptr[0x9a92c48] size[0xc0] used[0x60]
string [.Yg.\...n.Xt.]r.ze.....g.Y..\..Yb.Y(..d..r.[..Y...-.xi..i.]
--- CUT ---

First column is the offset so vulnerability is executed like it should be (negative offsets). Second column is byte which is read out-of-bound.

How to run this very primitive Proof of Concept?

$ gcc p_cve-2011-4362.c -o p_cve-2011-4362
$ ./p_cve-2011-4362 

    ...::: -=[ Proof of Concept for CVE-2011-4362 (by Adam 'pi3' Zabrocki) ]=- :::...

    Usage: ./p_cve-2011-4362 <options>

        Options:
             -v <victim>
             -p <port>
             -d <remote_dir_for_auth>

$ ./p_cve-2011-4362 -h 127.0.0.1 -p 81 -d dupa

    ...::: -=[ Proof of Concept for CVE-2011-4362 (by Adam 'pi3' Zabrocki) ]=- :::...

        [+] Preparing arguments... OK
        [+] Creating socket... OK
        [+] Connecting to [127.0.0.1]... OK
        [+] Sending dirty packet... OK

        [+] Check the website!

$

Lighttpd will log this situation probably in error-log file like this:

--- CUT ---
...
...
2011-12-xx xx:xx:11: (http_auth.c.887) : is missing in ÇYg\§ÎúnöXt¾]rzeëÛô¾gYóï\ðÿYbîY(¿dßørÖ[YóúÙ-·xiþèi°kÂWpË    ]߶øò\äÂ×@VØä¦xóúÝize
--- CUT ---

Maybe you can find vulnerable binary?

Best regards,
Adam ‘pi3’ Zabrocki


http://pi3.com.pl
http://site.pi3.com.pl/exp/p_cve-2011-4362.c
http://blog.pi3.com.pl/?p=277

Second level of GCHQ ‘canyoucrackit’ challenge requires to implement own Virtual Machine(!). This VM must emulate segmented memory model with 16-byte segment size (notation seg:offset). For details please read this link:

http://www.canyoucrackit.co.uk/15b436de1f9107f3778aad525e5d0b20.js

I wrote quick overview about this challenge, how to solve it and some tips. It can be found here:

http://blog.pi3.com.pl/?p=213

Anyway, I am impressed how many people saw this post and how fast this link was shared in community 🙂 Of course I’m happy of that but also a bit terrified. Anyway, in this short post I didn’t put much details about how to implement this VM, if there is any difficulties, etc. This was one of the reason I received a few emails asking some help to solve it. This is the reason why I decide finally write this second post. I want to share with my VM which i wrote in pure C (I love this language). To be honest I didn’t implement it at the beginning like it is here. I found some implementation in the http://pastebin.com webpage in python language. Unfortunately it has some mistakes (in fact serious mistakes). This was the reason why this machine didn’t work properly and in fact after a few instruction put exceptions and of course whole VM stops. I spend some time to fix it and I did it. After rewriting this machine, python VM starts working. This machine had a few problems like doesn’t correct  implement the most important instructions (JMP and JMPE). Also there was mistakes in take care about MOD flag. Another bug was that CS and DS register can be used in operations like ADD via normal operand argument as register. Also operations which use addressing [seg:off] must especially take care if the arguments are inside of the SEGMENT, if not make them fix. In fact this was critical bugs.

Anyway because of that I rewrote almost whole program so after all I decide, OK let’s do that in my way and this was the point why I implement everything again in C. Here you have got my VM in pure C:

http://site.pi3.com.pl/exp/pi3_VM.c

 

Btw. In fact this challenge is NOT finished yet… Maybe it was mistake to publish solution BEFORE end of it? I feel a bit guilty.

 

Best regards,

Adam Zabrocki

Yesterday I read in one of the polish portal (with news) an  information about interesting challenge organized by the Government Communications Headquarters (GCHQ). This is a British intelligence agency responsible for providing signals intelligence (SIGINT) and information assurance to the UK government and armed forces. Based in Cheltenham, it operates under the guidance of the Joint Intelligence Committee. CESG (originally Communications-Electronics Security Group) is the branch of GCHQ which works to secure the communications and information systems of the government and critical parts of UK national infrastructure.

GCHQ, is aiming to attract the next generation of web-savvy spies by running an ad campaign that challenges computer hackers to crack a code to get an interview.

Ok so let’s look at it closer 🙂

 

First level

I will not analyze the security of webpage and server. I will try to discuss about pure challenge. OK so first question is what does this hexcode means? Let’s look it closer:

0xeb 0x04 0xaf 0xc2 0xbf 0xa3 0x81 0xec   0x00 0x01 0x00 0x00 0x31 0xc9 0x88 0x0c
0x0c 0xfe 0xc1 0x75 0xf9 0x31 0xc0 0xba   0xef 0xbe 0xad 0xde 0x02 0x04 0x0c 0x00
0xd0 0xc1 0xca 0x08 0x8a 0x1c 0x0c 0x8a   0x3c 0x04 0x88 0x1c 0x04 0x88 0x3c 0x0c
0xfe 0xc1 0x75 0xe8 0xe9 0x5c 0x00 0x00   0x00 0x89 0xe3 0x81 0xc3 0x04 0x00 0x00
0x00 0x5c 0x58 0x3d 0x41 0x41 0x41 0x41   0x75 0x43 0x58 0x3d 0x42 0x42 0x42 0x42
0x75 0x3b 0x5a 0x89 0xd1 0x89 0xe6 0x89   0xdf 0x29 0xcf 0xf3 0xa4 0x89 0xde 0x89
0xd1 0x89 0xdf 0x29 0xcf 0x31 0xc0 0x31   0xdb 0x31 0xd2 0xfe 0xc0 0x02 0x1c 0x06
0x8a 0x14 0x06 0x8a 0x34 0x1e 0x88 0x34   0x06 0x88 0x14 0x1e 0x00 0xf2 0x30 0xf6
0x8a 0x1c 0x16 0x8a 0x17 0x30 0xda 0x88   0x17 0x47 0x49 0x75 0xde 0x31 0xdb 0x89
0xd8 0xfe 0xc0 0xcd 0x80 0x90 0x90 0xe8   0x9d 0xff 0xff 0xff 0x41 0x41 0x41 0x41

For the first quick view we can say there is some interesting bytes. With red color I sign this bytes which can be a dump of x86 assembler instructions (of course there is more but this can be typical for shellcodes) and with the blue color I sign interesting bytes for me 🙂 – 0x41414141 and 0x424242 for me always will be connected with exploiting 😉

OK so let’s try to analyze this bytes as x86 instructions:

   0x0804a040 <+0>:    jmp    0x804a046 <shellcode+6>
   0x0804a042 <+2>:    scas   %es:(%edi),%eax
   0x0804a043 <+3>:    ret    $0xa3bf
   0x0804a046 <+6>:    sub    $0x100,%esp
   0x0804a04c <+12>:    xor    %ecx,%ecx
   0x0804a04e <+14>:    mov    %cl,(%esp,%ecx,1)
   0x0804a051 <+17>:    inc    %cl
   0x0804a053 <+19>:    jne    0x804a04e <shellcode+14>
   0x0804a055 <+21>:    xor    %eax,%eax
   0x0804a057 <+23>:    mov    $0xdeadbeef,%edx
   0x0804a05c <+28>:    add    (%esp,%ecx,1),%al
   0x0804a05f <+31>:    add    %dl,%al
   0x0804a061 <+33>:    ror    $0x8,%edx
   0x0804a064 <+36>:    mov    (%esp,%ecx,1),%bl
   0x0804a067 <+39>:    mov    (%esp,%eax,1),%bh
   0x0804a06a <+42>:    mov    %bl,(%esp,%eax,1)
   0x0804a06d <+45>:    mov    %bh,(%esp,%ecx,1)
   0x0804a070 <+48>:    inc    %cl
   0x0804a072 <+50>:    jne    0x804a05c <shellcode+28>
   0x0804a074 <+52>:    jmp    0x804a0d5 <shellcode+149>
   0x0804a079 <+57>:    mov    %esp,%ebx
   0x0804a07b <+59>:    add    $0x4,%ebx
   0x0804a081 <+65>:    pop    %esp
   0x0804a082 <+66>:    pop    %eax
   0x0804a083 <+67>:    cmp    $0x41414141,%eax
   0x0804a088 <+72>:    jne    0x804a0cd <shellcode+141>
   0x0804a08a <+74>:    dec    %eax
   0x0804a08b <+75>:    cmp    $0x42424242,%eax
   0x0804a090 <+80>:    jne    0x804a0cd <shellcode+141>
   0x0804a092 <+82>:    pop    %edx
   0x0804a093 <+83>:    mov    %edx,%ecx
   0x0804a095 <+85>:    mov    %esp,%esi
   0x0804a097 <+87>:    mov    %ebx,%edi
   0x0804a099 <+89>:    sub    %ecx,%edi
   0x0804a09b <+91>:    rep movsb %ds:(%esi),%es:(%edi)
   0x0804a09d <+93>:    mov    %ebx,%esi
   0x0804a09f <+95>:    mov    %edx,%ecx
   0x0804a0a1 <+97>:    mov    %ebx,%edi
   0x0804a0a3 <+99>:    sub    %ecx,%edi
   0x0804a0a5 <+101>:    xor    %eax,%eax
   0x0804a0a7 <+103>:    xor    %ebx,%ebx
   0x0804a0a9 <+105>:    xor    %edx,%edx
   0x0804a0ab <+107>:    inc    %al
   0x0804a0ad <+109>:    add    (%esi,%eax,1),%bl
   0x0804a0b0 <+112>:    mov    (%esi,%eax,1),%dl
   0x0804a0b3 <+115>:    mov    (%esi,%ebx,1),%dh
   0x0804a0b6 <+118>:    mov    %dh,(%esi,%eax,1)
   0x0804a0b9 <+121>:    mov    %dl,(%esi,%ebx,1)
   0x0804a0bc <+124>:    add    %dh,%dl
   0x0804a0be <+126>:    xor    %dh,%dh
   0x0804a0c0 <+128>:    mov    (%esi,%edx,1),%bl
   0x0804a0c3 <+131>:    mov    (%edi),%dl
   0x0804a0c5 <+133>:    xor    %bl,%dl
   0x0804a0c7 <+135>:    mov    %dl,(%edi)
   0x0804a0c9 <+137>:    inc    %edi
   0x0804a0ca <+138>:    dec    %ecx
   0x0804a0cb <+139>:    jne    0x804a0ab <shellcode+107>
   0x0804a0cd <+141>:    xor    %ebx,%ebx
   0x0804a0cf <+143>:    mov    %ebx,%eax
   0x0804a0d1 <+145>:    inc    %al
   0x0804a0d3 <+147>:    int    $0x80
   0x0804a0d5 <+149>:    nop
   0x0804a0d6 <+150>:    nop
   0x0804a0d7 <+151>:    call   0x804a079 <shellcode+57>
   0x0804a0dc <+156>:    inc    %ecx
   0x0804a0dd <+157>:    inc    %ecx
   0x0804a0de <+158>:    inc    %ecx
   0x0804a0df <+159>:    inc    %ecx
   0x0804a0e0 <+160>:    add    %al,(%eax)

So this is it. This code make sense and this was good way of analyzing. I sign by read color this instruction which always cause exit() syscall and half of the code won’t be executed (as we will see further even more). But first, at the beginning this code jump over 2 next instruction (so they are never executed) and than allocate memory which is filled by natural numbers. Next they are converted to some more interested values and finally there is static jump to the code which cause syscall exit() – red colour. That’s all, so what next? As we can see directly after jump instruction, the program tries to get the new value for the stack pointer exactly from the stack. It gaves us an information that smth should be changed there 😉 Also as we can see further (blue colour) from the stack is popped also value for %%eax register and compared with the 0x41414141 value. Next this value is decremented by one and again compared but now with the 0x42424242 value. Logically it makes no sense. If first compare will be true than next will be bad – 0x41414141 – 1 = 0x41414140 so it will never be 0x42424242. If we want to pass all this checks and executed further code we must change a lot 😉

First change

Ok let’s come back to the syscall exit(). We don’t want to stop the execution flow but continue, and we know that further code expect the new stack pointer in the stack. Also we know that after this operation program tries to get new value for %%eax register from the new stack and compare with the value 0x414141. As we can see in the end of the shellcode we have instructions:

   0x0804a0dc <+156>:    inc    %ecx
   0x0804a0dd <+157>:    inc    %ecx
   0x0804a0de <+158>:    inc    %ecx
   0x0804a0df <+159>:    inc    %ecx

this is exactly the value 0x414141:

(gdb) x/x 0x0804a0dc
0x804a0dc <shellcode+156>:    0x41414141
(gdb)

so here we go with answer 😉 Like in the oldschool technique of getting current stack pointer used in viruses – let’s change syscall exit() to the call which gave us back the flow to the shellcode. Old code:

   0x0804a0d5 <+149>:    nop
   0x0804a0d6 <+150>:    nop
   0x0804a0d7 <+151>:    call   0x804a079 <shellcode+57> # value: 0x80cd

New code:

   0x804c095:    nop
   0x804c096:    nop
   0x804c097:    call   0x804c039 # value: 0x45eb

OK – works. First compare is passed but of course second is not and again game over. But If we think again about it, decrementing instruction can be also overwrite to ours and as we know the new stack pointer is now _after_ the shellcode. We are able to add new bytes after this shellcode and change the assembler instruction which decrements value in register %%eax to pop new value from the stack 🙂 This is in fact the answer 😉

Second change

Old instruction:

   0x0804a08a <+74>:    dec    %eax  # byte: 0x48

New instruction:

   0x804c04a:    pop    %eax  # byte: 0x58

Perfect. Now we have another problem – which data should be added in the end of shellcode? We can manually add 0x42424242 value to pass the compare check but what about further code? Maybe this 0x42424242  is a tip? In further code the value for %%edx register is also popped from the stack. And next bytes are used to copy in temporary place and manipulate them. So of course all of this is a tip. Lets come back again to the main page of the crack site. Bytes which we used to create shellcode are not in the site as text but as image. We were frustrating to rewrite them manually not just simply copying. But wait a minute why this is an image?

Steganography

Analyzing image can be hard 😉 But I’m lazy buster and usually before I move to real hard job like analyze or full RE I try to get as much information as I can in as simple way as it can be. So let’s run strings command 😉 There is 983 lines (not small image) but one line from the top is very interesting:

$ strings cyber.png |head
IHDR
sRGB
    pHYs
tIME
]iTXtComment
QkJCQjIAAACR2PFtcCA6q2eaC8SR+8dmD/zNzLQC+td3tFQ4qx8O447TDeuZw5P+0SsbEcYR
78jKLw==2
IDATx
.^cwuW
$

Here you go 😉 First impression is – this is base64. Let’s check in one of the online sites if there is logic in this string. After decoding to the ASCII we see that hexdump should be done _but_ look for the first 4 bytes in this string:

BBBB2∅∅∅Øñmp :«gÄûÇfüÍÌ´ú×w´T8
ëÃþÑ+ÆïÈÊ/?ÿØ∅∅

Yes, this is exactly 0x42424242 value.  So probably this is what we need 😉 After adding this hex in the end of the shellcode and all of our changes and adding the code for dumping the memory after whole process of executing shellcode (this dump function write by yourself) we will see this beautiful message from the memory:

GET /15b436de1f9107f3778aad525e5d0b20.js HTTP/1.1

Interesting, isn’t it? 🙂 Yep the first level is done.

 

Second level

What does this link have?

//--------------------------------------------------------------------------------------------------
//
// stage 2 of 3
//
// challenge:
//   reveal the solution within VM.mem
//
// disclaimer:
//   tested in ie 9, firefox 6, chrome 14 and v8 shell (http://code.google.com/apis/v8/build.html),
//   other javascript implementations may or may not work.
//
//--------------------------------------------------------------------------------------------------

var VM = {

  cpu: {
    ip: 0x00,

    r0: 0x00,
    r1: 0x00,
    r2: 0x00,
    r3: 0x00,

    cs: 0x00,
    ds: 0x10,

    fl: 0x00,

    firmware: [0xd2ab1f05, 0xda13f110]
  },

  mem: [
    0x31, 0x04, 0x33, 0xaa, 0x40, 0x02, 0x80, 0x03, 0x52, 0x00, 0x72, 0x01, 0x73, 0x01, 0xb2, 0x50,
    0x30, 0x14, 0xc0, 0x01, 0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

    0x98, 0xab, 0xd9, 0xa1, 0x9f, 0xa7, 0x83, 0x83, 0xf2, 0xb1, 0x34, 0xb6, 0xe4, 0xb7, 0xca, 0xb8,
    0xc9, 0xb8, 0x0e, 0xbd, 0x7d, 0x0f, 0xc0, 0xf1, 0xd9, 0x03, 0xc5, 0x3a, 0xc6, 0xc7, 0xc8, 0xc9,
    0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
    0xda, 0xdb, 0xa9, 0xcd, 0xdf, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
    0x26, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
    0x7d, 0x1f, 0x15, 0x60, 0x4d, 0x4d, 0x52, 0x7d, 0x0e, 0x27, 0x6d, 0x10, 0x6d, 0x5a, 0x06, 0x56,
    0x47, 0x14, 0x42, 0x0e, 0xb6, 0xb2, 0xb2, 0xe6, 0xeb, 0xb4, 0x83, 0x8e, 0xd7, 0xe5, 0xd4, 0xd9,
    0xc3, 0xf0, 0x80, 0x95, 0xf1, 0x82, 0x82, 0x9a, 0xbd, 0x95, 0xa4, 0x8d, 0x9a, 0x2b, 0x30, 0x69,
    0x4a, 0x69, 0x65, 0x55, 0x1c, 0x7b, 0x69, 0x1c, 0x6e, 0x04, 0x74, 0x35, 0x21, 0x26, 0x2f, 0x60,
    0x03, 0x4e, 0x37, 0x1e, 0x33, 0x54, 0x39, 0xe6, 0xba, 0xb4, 0xa2, 0xad, 0xa4, 0xc5, 0x95, 0xc8,
    0xc1, 0xe4, 0x8a, 0xec, 0xe7, 0x92, 0x8b, 0xe8, 0x81, 0xf0, 0xad, 0x98, 0xa4, 0xd0, 0xc0, 0x8d,
    0xac, 0x22, 0x52, 0x65, 0x7e, 0x27, 0x2b, 0x5a, 0x12, 0x61, 0x0a, 0x01, 0x7a, 0x6b, 0x1d, 0x67,
    0x75, 0x70, 0x6c, 0x1b, 0x11, 0x25, 0x25, 0x70, 0x7f, 0x7e, 0x67, 0x63, 0x30, 0x3c, 0x6d, 0x6a,
    0x01, 0x51, 0x59, 0x5f, 0x56, 0x13, 0x10, 0x43, 0x19, 0x18, 0xe5, 0xe0, 0xbe, 0xbf, 0xbd, 0xe9,
    0xf0, 0xf1, 0xf9, 0xfa, 0xab, 0x8f, 0xc1, 0xdf, 0xcf, 0x8d, 0xf8, 0xe7, 0xe2, 0xe9, 0x93, 0x8e,
    0xec, 0xf5, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

    0x37, 0x7a, 0x07, 0x11, 0x1f, 0x1d, 0x68, 0x25, 0x32, 0x77, 0x1e, 0x62, 0x23, 0x5b, 0x47, 0x55,
    0x53, 0x30, 0x11, 0x42, 0xf6, 0xf1, 0xb1, 0xe6, 0xc3, 0xcc, 0xf8, 0xc5, 0xe4, 0xcc, 0xc0, 0xd3,
    0x85, 0xfd, 0x9a, 0xe3, 0xe6, 0x81, 0xb5, 0xbb, 0xd7, 0xcd, 0x87, 0xa3, 0xd3, 0x6b, 0x36, 0x6f,
    0x6f, 0x66, 0x55, 0x30, 0x16, 0x45, 0x5e, 0x09, 0x74, 0x5c, 0x3f, 0x29, 0x2b, 0x66, 0x3d, 0x0d,
    0x02, 0x30, 0x28, 0x35, 0x15, 0x09, 0x15, 0xdd, 0xec, 0xb8, 0xe2, 0xfb, 0xd8, 0xcb, 0xd8, 0xd1,
    0x8b, 0xd5, 0x82, 0xd9, 0x9a, 0xf1, 0x92, 0xab, 0xe8, 0xa6, 0xd6, 0xd0, 0x8c, 0xaa, 0xd2, 0x94,
    0xcf, 0x45, 0x46, 0x67, 0x20, 0x7d, 0x44, 0x14, 0x6b, 0x45, 0x6d, 0x54, 0x03, 0x17, 0x60, 0x62,
    0x55, 0x5a, 0x4a, 0x66, 0x61, 0x11, 0x57, 0x68, 0x75, 0x05, 0x62, 0x36, 0x7d, 0x02, 0x10, 0x4b,
    0x08, 0x22, 0x42, 0x32, 0xba, 0xe2, 0xb9, 0xe2, 0xd6, 0xb9, 0xff, 0xc3, 0xe9, 0x8a, 0x8f, 0xc1,
    0x8f, 0xe1, 0xb8, 0xa4, 0x96, 0xf1, 0x8f, 0x81, 0xb1, 0x8d, 0x89, 0xcc, 0xd4, 0x78, 0x76, 0x61,
    0x72, 0x3e, 0x37, 0x23, 0x56, 0x73, 0x71, 0x79, 0x63, 0x7c, 0x08, 0x11, 0x20, 0x69, 0x7a, 0x14,
    0x68, 0x05, 0x21, 0x1e, 0x32, 0x27, 0x59, 0xb7, 0xcf, 0xab, 0xdd, 0xd5, 0xcc, 0x97, 0x93, 0xf2,
    0xe7, 0xc0, 0xeb, 0xff, 0xe9, 0xa3, 0xbf, 0xa1, 0xab, 0x8b, 0xbb, 0x9e, 0x9e, 0x8c, 0xa0, 0xc1,
    0x9b, 0x5a, 0x2f, 0x2f, 0x4e, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  ],

  exec: function()
  {
    // virtual machine architecture
    // ++++++++++++++++++++++++++++
    //
    // segmented memory model with 16-byte segment size (notation seg:offset)
    //
    // 4 general-purpose registers (r0-r3)
    // 2 segment registers (cs, ds equiv. to r4, r5)
    // 1 flags register (fl)
    //
    // instruction encoding
    // ++++++++++++++++++++
    //
    //           byte 1               byte 2 (optional)
    // bits      [ 7 6 5 4 3 2 1 0 ]  [ 7 6 5 4 3 2 1 0 ]
    // opcode      - - -
    // mod               -
    // operand1            - - - -
    // operand2                         - - - - - - - -
    //
    // operand1 is always a register index
    // operand2 is optional, depending upon the instruction set specified below
    // the value of mod alters the meaning of any operand2
    //   0: operand2 = reg ix
    //   1: operand2 = fixed immediate value or target segment (depending on instruction)
    //
    // instruction set
    // +++++++++++++++
    //
    // Notes:
    //   * r1, r2 => operand 1 is register 1, operand 2 is register 2
    //   * movr r1, r2 => move contents of register r2 into register r1
    //
    // opcode | instruction | operands (mod 0) | operands (mod 1)
    // -------+-------------+------------------+-----------------
    // 0x00   | jmp         | r1               | r2:r1
    // 0x01   | movr        | r1, r2           | rx,   imm
    // 0x02   | movm        | r1, [ds:r2]      | [ds:r1], r2
    // 0x03   | add         | r1, r2           | r1,   imm
    // 0x04   | xor         | r1, r2           | r1,   imm
    // 0x05   | cmp         | r1, r2           | r1,   imm
    // 0x06   | jmpe        | r1               | r2:r1
    // 0x07   | hlt         | N/A              | N/A
    //
    // flags
    // +++++
    //
    // cmp r1, r2 instruction results in:
    //   r1 == r2 => fl = 0
    //   r1 < r2  => fl = 0xff
    //   r1 > r2  => fl = 1
    //
    // jmpe r1
    //   => if (fl == 0) jmp r1
    //      else nop

    throw "VM.exec not yet implemented";
  }

};

//--------------------------------------------------------------------------------------------------

try
{
  VM.exec();
}
catch(e)
{
  alert('\nError: ' + e + '\n');
}

//--------------------------------------------------------------------------------------------------

As we can read this level is completely different from the previous 🙂 Short overview:

  • We must implement own Virtual Machine(!)
  • VM must emulate segmented memory model with 16-byte segment size (notation seg:offset)
  • There is defined own assembler with own simple architecture
  • CPU have 8 registers: 4 general-purpose registers (r0-r3), 2 segment registers (cs, ds equiv. to r4, r5), 1 flags register (fl), and of course IP register (Instruction Pointer)
  • We know how instruction encoding looks like.
  • We know how to manipulate flags register.
  • 8 instructions are defined
  • Memory dump is available which must be used to execute our emulator

To solve this level we must know that segment-offset architecture has always shifted memory etc. If we look closer we can find that emulated %%ds register has value 0x10 (because its 16 bits architecture).

I won’t post here my implementation of this VM, but after all again we must dump the memory how it is changed. Here it is:

1^D3<AA>@^B<80>^CR^@r^As^A<B2>P0^T<C0>^A<80>^@^P^P^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@2^@u^L32@^B<80>^CR^@r^As^C<B2>^@ð^@0C0>^A<FF>^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@u^P^A^@^@^@^@^@^@^@^@^@^@^@<CC>^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@}^_^U`MMR}^N'm^PmZ^FVG^TB^N<B6><B2><B2><E6>봃<8E><D7><E5><D4><D9><C3><F0><80><95><U+4209A><BD><95><A4><8D><9A>+0iJieU^\{i^\n^Dt5!&/`^CN7^^3T9溴<A2><AD><A4>ŕ<C8><C1><E4><8A><EC>璋<E8><81><U+2D624><D0><C0><8D><AC>"Re~'+Z^Ra
^Azk^]gGET /da75370fe15c4148bd4ceec861fbdaa5.exe HTTP/1.0^@^@^@^@^@^@^@^@^@^@^@^@^@^@7z^G^Q^_^]h%2w^^b#[GUS0^QB<F6><F1><B1><E6><C3><CC><F8><C5><E4><CC><C0>Ӆ<FD><9A><E3>恵<BB><D7>͇<A3><D3>k6oofU0^VE^   t\?)+f=^M
^M^B0(5^U        ^U<DD><EC><B8><E2><FB><D8><CB><D8>ыՂٚ<F1><92><AB><E8><A6><D6>Ќ<AA>Ҕ<CF>EFg }D^TkEmT^C^W`bUZJfa^QWhu^Eb6}^B^P"B2<BA><E2><B9><E2>ֹ<FF><C3>銏<C1><8F>Ḥ<96><U+4F071><8D><89><CC><D4>xvar>7#Vsqyc^Q iz^Th^E!^^2'Y<B7>ϫ<DD><D5>̗<93><F2><E7><C0><EB><FF>飿<A1><AB><8B><BB><9E><9E><8C><A0><C1><9B>Z//NN^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@

As we can see there is hidden link for the next level 😉 Now we must probably play with binary 😉

Btw. to be sure that our emulator is correct, last instruction must be ‘hlt’ – halt.

 

Third level (last)

First of all, this is Windows binary so I will use VM to play with it (I use VirtualBox with Win XP SP3 + IDA of course ;p). We need to install cygwin to run the binary because of the libcrypt which was used to compile the binary. After all when we run the binary we will be asked to give an argument

usage: keygen.exe hostname

Let’s look inside of the binary…

        mov    [esp+78h+var_74], offset aR ; "r"
        mov    [esp+78h+var_78], offset aLicense_txt ;    "license.txt"
        call    _fopen64
        mov    [ebp+var_4C], eax
        cmp    [ebp+var_4C], 0
        jnz    short loc_401120
        mov    [esp+78h+var_78], offset aErrorLicense_t ; "error: license.txt not found\n"
        call    printf
        mov    [ebp+var_50], 0FFFFFFFFh
        jmp    loc_401204

So program is looking for the license.txt file

        lea    eax, [ebp+var_38]
        mov    [esp+78h+var_70], eax
        mov    [esp+78h+var_74], offset aS ; "%s"
        mov    eax, [ebp+var_4C]
        mov    [esp+78h+var_78], eax
        call    fscanf

Get the string from this file (here is by the way stack overflow bug :D). Next:

        cmp    [ebp+var_38], 71686367h
        jnz    short loc_4011CF

program checks the first 4 bytes if they are equal to 0x71686367 which in fact is equal to the string “gchq” – so the pattern of The Government Communications Headquarters 🙂 Next:

        mov    eax, dword_402000
        mov    [esp+78h+var_74], eax
        lea    eax, [ebp+var_38]
        add    eax, 4
        mov    [esp+78h+var_78], eax
        call    crypt
        mov    edx, eax
        mov    eax, dword_402000
        mov    [esp+78h+var_74], eax
        mov    [esp+78h+var_78], edx
        call    strcmp
        test    eax, eax
        jnz    short loc_4011A5

Here is small trick 🙂 For me very clever, so we can see call for the crypt() function and next compare and jump. If we analyze it closer we can see that argument for the crypt() is the same like one argument for the strcmp() function. So crypt() must return exactly the same value like one which was passed as argument. Pseudocode can look like:

char *tmp="hqDTK7b8K2rvw";
if (strcmp(crypt(bufor+4, tmp), tmp)) {
   ...

This is very interesting situation because we must find string which after pass it to the crypt() function with the salt “hqDTK7b8K2rvw” will be encrypted to exactly the same value as salt (“hqDTK7b8K2rvw”) 🙂

Two ways can be used to find this string – bruteforce and rainbow tables. I’ve done both 😀 In fact bruteforcing won’t take as much time. Anyway the answer is….

cyberwin

🙂 Yes, we have it 🙂 Now we know that license key should looks like:

gchqcyberwin

Whatever we add after this string it won’t change the value of encrypted string (because of the salt). So let’s try to run the code with exactly this license.txt file:

_> da75370fe15c4148bd4ceec861fbdaa5.exe www.canyoucrackit.co.uk

keygen.exe

loading stage1 license key(s)...
loading stage2 license key(s)...

request:

GET /hqDTK7b8K2rvw/0/0/0/key.txt HTTP/1.0

response:

HTTP/1.1 404 Not Found
Content-Type: text/html; charset=us-ascii
Server: Microsoft-HTTPAPI/2.0
Date: Thu, 01 Dec 2011 23:55:05 GMT
Connection: close
Content-Length: 315

<HTML body>

So what we know now… File tries to connect to the server given as the argument in command line and tries to GET a key.txt file from the URL:

/hqDTK7b8K2rvw/0/0/0/key.txt

So again we have some question. Why there is three values of 0 (zero) number? Is the server given in command line is correct? When the program is running it prints:

loading stage1 license key(s)...
loading stage2 license key(s)...

Why he do that? If we look again to the java script code from the previous level we can read:

// stage 2 of 3

Is it somehow connected to this string? OK so… if we add anything after the magic string in license.txt file program tries to dump it as hex value and put in the URL, so:

_> da75370fe15c4148bd4ceec861fbdaa5.exe www.canyoucrackit.co.uk

keygen.exe

loading stage1 license key(s)...
loading stage2 license key(s)...

request:

GET /hqDTK7b8K2rvw/41414141/42424242/43434343/key.txt HTTP/1.0

response:

HTTP/1.1 404 Not Found
Content-Type: text/html; charset=us-ascii
Server: Microsoft-HTTPAPI/2.0
Date: Thu, 01 Dec 2011 23:58:05 GMT
Connection: close
Content-Length: 315

<HTML body>

Again we cannot put too long string because we can make stack overflow bug 😉 Of course we do not need to do that 😉 What is interesting we must find correct three 4bytes values and this is the main goal – find a correct path for the key.txt file – as I said in first level there is unused 4 bytes – use it + in 2 stage there was also 2 unused bytes but written directly in the .js file 😉

UPDATE: Some ppl didn’t believe I know what bytes should be used. But as I said in previous sentence – all bytes are in previous stages. Here is the correct link:

http://www.canyoucrackit.co.uk/hqDTK7b8K2rvw/a3bfc2af/d2ab1f05/da13f110/key.txt

So first value as I pointed in all previous sentence (when I described first level also I point it specially) is from the unused code from the shellcode. Two next bytes are the firmware from the second stage.

Ending

When we solve all problems and enter correct string in the main page which is:

Pr0t3ct!on#cyber_security@12*12.2011+

you will be redirect to this page:

http://www.canyoucrackit.co.uk/soyoudidit.asp

Here is screenshot:

After you click the button you are going to be redirected here:

http://www.gchq-careers.co.uk/cyber-jobs/

Here is screenshot:

and final redirection is here:

https://apply.gchq-careers.co.uk/fe/tpl_gchq01ssl.asp?newms=jj&id=35874

Here is some screenshot with salary:

Conclusion

This is very nice challenge and requires in fact huge skills. Very nice training for our brains 😉 Anyway few points which I must write now:

  • To apply for this job you must have English citizen – I don’t have so automagically I can’t apply even when I finished this challenge 😉
  • This challenge requires a lot of skills and the salary(!) is very low for the ppl with this skills so I understand why they cannot find good ppl 😉
  • I’m living and working now in London and I can say its quite nice place 😉

 

UPDATE 2: More information about second level + my implementation of VM can be found here:

http://blog.pi3.com.pl/?p=268

 

Best regards,

Adam Zabrocki