31C3 CTF writeups

I’m writing about challenge writeups which I’ve finished during the competition. 31c3 is awesome CTF as always ;).


Please replace {nullbyte} into \0 in urlencode.
Since older PHP versions parse "09" as octal numbers. so "9" is not legit.

curl -ik "http://works.90.31c3ctf.aachen.ccc.de/passwd"\
-H "Host: ../../../../../../etc/"\
-H "Host: works.90.31c3ctf.aachen.ccc.de"
HTTP/1.0 200 OK



Since it filterd some keywords to prevent SQLi attacks, such as: “or”,”union”,”schema”,…

so we could not inject “password”,”information_schema” or anything like that to extract column name which contains password of those users.Now what ?!

Idea come from my friend (nurfed) ;). We could leak column password via error-based.

python web30.py "select * from (select * from users join users b using(id_user,Us3rN4m3,Em4iL4dr3Szz,S4cR3dT3xT0Fm3,MyPh0N3NumB3RHAHA,Addr3Zz0F_tHi5_D3wD,CHAR_LOL))c"
Duplicate column name 'P4sWW0rD_0F_M3_WTF'

Login with that password = > failed!. Ah, i guessed that error-based has been limited characters. So we need to blind-sqli to recover an entire password. I used locate.

Dracula / ZD456ddssd65456lksndoiNzd654sdsd654zd65s4d56489zdz

After you login successfully, you could see the directory traversal vulnerability easily.

Explore it, we will be able to get source-code of whole site. But it was not useful, where is flag ? how i get it ?

Dig more, and i saw something which is pretty interesting.

In /home/devilish.local/

It is another source-code with a bit different from /var/www/html/.

So, how we can go surf devlish.local ? we may change Host header ? Probably!.

curl -ik "" -H "Host: devilish.local"

INDEX (devilish.local):

LOGIN_HEAD (devilish.local):

…Hm Is there another way to set our $_SESSION[‘is_ExclusiveMember’]=1 ?. Yes, it is.

Back to /var/www/html/ to find useful things. I saw:


We could set $_SESSION at here. and get back to devlish.local with anything we want.




Let’s play a game!
nc 2000

Solution: casino.py



orbb running on

This binary used  libnetfilter_queue which provide an API verdict or reinject packets to kernel nfnetlink_queue subsystem.


nfq_get_payload is the function that parse our message (packet) to pointer of pointer which pass into $rsi.

At 0x4011F5: It get 1 byte at 9th bytes of our message.

As above definition, 9th bytes is PROTOCOL numbers (tcp,udp…).

At 0x40121A: The binary check whether PROTOCOL equals 16.

You can search it  in list of IP protocol numbers.

It shows us that protocol 16 is CHAOSNET (?!). I’ve never heard it before :D.

A bit later, it leads us to function “check_crc32” (0x400FFA) which pass our raw data in packet as 1st argument.


So our raw data must have 9bytes and start with ‘cha0s‘. Moreover, CRC32(our raw data) has to be 0xCCCAC. hm…read this post.

I’ve used that tools to reverse crc32.

Cool !

sub_400F58: If your payload is legit, It will send the FLAG to our IP with port 3276 as UDP payload. well, just enable netcat to listen on that port. nc -ulv 3276

I used scapy for generating payload with proto number = 16.

And you would be able to receive your flag ;).

Ah one last thing, If you wanna debug on your own localhost. Just run:
iptables -A INPUT -p 16 -j NFQUEUE --queue-num 0






It was off-by-one vulnerability in add_comment function. So you could overwrite type of struct (1st byte) as above defination.



manhluat Written by:


  1. tianxianbaobao
    January 2, 2015

    Hi. I have read your cfy’s exp.You said “I leaked strings from libc and determined the version of libc.” ……But I want to know the process you detemined the glibc’s version in detail. Thank you for your kind help! 😉 Sorry for my poor english~

    • manhluat
      January 2, 2015

      I’ve used leak() to read approximate 0x5000 bytes from specific address. Then I had to search some strings like “GNU C Library (Ubuntu ******) stable release version 2.19, by Roland McGrath” 🙂

  2. no_name_for
    January 3, 2015

    Hi, i just want to ask about the ida version you are using. the struct are presented here with their real names, are you using a king of plugin for IDA ? or what ?

    • manhluat
      January 3, 2015

      It’s not real name. I defined that struct myself by reversing those functions.

  3. olaus
    January 4, 2015

    thanks for the writeups!

    • manhluat
      January 4, 2015

      you’re welcome! 😀

  4. 天线宝宝
    January 4, 2015

    Sorry for my stupid. But I also have a trouble to leak string.(“GNU C Library (Ubuntu GLIBC 2.19-10ubuntu2.1) stable release”),Well ,you said we can use leak() to leak string。But the “2 function” Only give us dec number and hex number.How to find char(string)?Thanks for your kind help 😉

    • manhluat
      January 4, 2015

      notice that in my leak(), it has 2nd optional argument ;). If ret_str = 1, it shall return a string through get_hex(). Basically, I’ve just extract a string from hex return value by pack,unpack :).

    January 4, 2015

    so you used the 3rd option to dump some stack address, then converted it to string ? cuz during the CTF i brute forced some stack address, i got some strings but not the wanted one 🙁

  6. Mars
    January 5, 2015

    eh~~ I’ve read your cfy’s exp but still have some trouble determing the version of libc. You said:” I’ve used leak() to read approximate 0x5000 bytes from specific address. ” Could you please tell me the specific address ? Thanks a lot. 😀

    • manhluat
      January 5, 2015

      Hm. You have to determine that address.
      I used libc_start_main+0x6000 (I dont remember extactly) as start address to leak.
      Basically, It’s likely that you have to leak whole a libc until you get some useful string :). I tried to calculate that offset many times.
      You should try it yourself to get some experience :D.

  7. Droal
    January 5, 2015

    Hey thank you for the great writeups! Always good to learn from you guys.
    A question about the PcrapP challenge. I have setup the same environment as the CTF challenge with PHP/Ubuntu.
    You wrote that when using 09, PHP will treat it as octet and will fail.
    However, when I try passing b=09, json_decode manage to convert it to 9 and does not fail. Any idea?

    • manhluat
      January 5, 2015

      It depends on your PHP version. It didnt work on my own localhost also, but it worked on CTF challenge host.
      curl -ik
      Server: Apache/2.4.10 (Ubuntu)
      X-Powered-By: PHP/5.5.12-2ubuntu4.1

  8. Droal
    January 5, 2015

    It seems like 01, 02, 03… , 09 works too on the challenge host.
    So i’m not sure if it’s relate to the octal error. mystery..

  9. January 17, 2015

    at Devilish “So we need to blind-sqli to recover an entire password. I used locate”
    what blind-sqli parameter to get the username+password and u say can’t extract data from information_schema or other ” so we could not inject “password”,”information_schema” or anything like that ”
    how that blind-sqli ? with locate

Leave a Reply

Your email address will not be published. Required fields are marked *