lundi 17 mars 2014

Weird0,

So, I just passed the Offensive-Security Certified Professional exam challenge. It was tough. It was an unforgettable 24 hours, a lot of pressure, and self-deprivation. Enjoyed it!
I am getting ready for the next and even more r0ck'n'r0ll one now, the CTP. 

dimanche 19 janvier 2014

smash the stack

======== let's smash the stack ======




level 01: 

All right, we are set, let's log in, and let's run level01 in /levels/




by entering a random passcode we land in the same shell with level01 privilege, so for  sure, we have to find a way to get the passcode ... let's fire up gdb and disassemble the main() of the program

obviously, all entered passcode will   be pushed into eax then compared to the hex value of $0x10f which in dec is 271. Let's test it by simply entering 271:
and here we go. That's only the entry point, we still got 29 levels remaining.

level02:


let's log out, then reconnect using level02 credentials. By running level02, we got a message stating that "source code is available in level02.c". So let's check out what is in the source code:
let's "read" it line by line in logical way:
  • within the main function, the "if" statement verifies if the argument's amount is not 3 (the reserved one is the executable name) or the atoi(second argument) (which returns an integer) is not zero, if both of these questions are not true the function returns 1
  •  if we provide the correct amount of args (which should be 2), and the first of these 2 (the second of the args if we count the executable name with it) is converted to an integer different than zero, the execution flow continues by setting a signal  handler for the SIGFPE( division by zero) and call the "catcher" function.
  • and then, if everything goes well, we got a returned value which is the absolute value of : convert to integer(first argument) / converted integer(second argument)
  • and if the catcher is executed, it should provide us a new and dandy shell with a new privilege.  Catcher receives an integer as an argument.
the main question is now: how to get catcher executed? Oh, well, we just have to set our input to get a SIGFPE without entering 0 as the second argument. According to the manual: 
"
According to POSIX, the behavior of a process is undefined after it ignores a SIGFPE, SIGILL, or SIGSEGV signal that was not generated by kill(2) or raise(3). Integer division by zero has undefined result. On some architectures it will generate a SIGFPE signal. (Also dividing the most negative integer by -1 may generate SIGFPE.) Ignoring this signal might lead to an endless loop."
 so we got our second argument = -1, but what about the first argument ? we know that a word (int) in C is in the range of −2,147,483,648 to 2,147,483,647. So let's try this out:


and there we go.

level03:


we log out again and log in with he above credentials - and here comes the source code:




so obviously, as per the above source code, a stack based buffer overflow is the way - hence stack smashing ! In fact the memcpy function, which is supposed to copy the user input into the buffer, doesn't provide any bounds checking ! 
in fact - with an input length smaller than 80 chars, we always got the following result 

but at exactly 80 we got EIP overwritten by our 4 last "A"s. The output changes to

so it is even better on gdb :)
Time to exploit this vulnerability. Let's see what happens if we change the last 4 bytes to B
 and the EIP is overwritten by our four "B" (@muts would say: 'Excellent')

and the ESP got pwn3d by our 'A's starting from 0xbffffe3c to 0xbffffe7c  which exactly is our 76  bytes:
0xbffffe3c:    0x41414100    0x41414141    0x41414141    0x41414141
0xbffffe4c:    0x41414141    0x41414141    0x41414141    0x41414141
0xbffffe5c:    0x41414141    0x41414141    0x41414141    0x41414141
0xbffffe6c:    0x41414141    0x41414141    0x41414141    0x41414141
0xbffffe7c:    0x41414141    0x41414141    0x41414141    0x42424241


Great! so let's try to find out how to get to the address of the good() function. Actually, each time we execute (according to the source code) level03 binary executable, with an argument length more than 4, the output is showing where are we in the memory and where we should be if we want to get to the good function. So what happens if we only change the last four bytes to destination address (stated in the output) ?
level3@io:/levels$ ./level03 AAAAAAAA
This is exciting we're going to 0x80484a4


having in my mind the little indian arch, the four last bytes would be "\x74\x84\x04\x08"