본문 바로가기

Study/BOF

setreuid function tracking

2012.05.01


$ cat test.c
#include<stdio.h>
#include<unistd.h>
main(){
setreuid(500,500);
execl("/bin/sh","sh",0);
}
테스트할 프로그램은 다음과 같다.

추적하기 수월하도록 gdb에서 실행후 disp/i $pc를 이용해보자.

ebp값 +8 한곳에서 setreuid 인자 참조 확인
ebp값 +12 한곳에서도 setreuid 인자 참조 확인

1: x/i $pc  0x7d9869 <setreuid+9>:    mov    0x8(%ebp),%edx
(gdb) info reg eax ebx ecx edx
eax            0x10    16
ebx            0x83eff4    8646644
ecx            0x1    1
edx            0x84119c    8655260
(gdb) ni
0x007d986c in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d986c <setreuid+12>:    call   0x730c71 <__i686.get_pc_thunk.bx>
(gdb) info reg eax ebx ecx edx
eax            0x10    16
ebx            0x83eff4    8646644
ecx            0x1    1
edx            0x1f4    500

ebp+8한곳의 값을 edx에 넣었다.

(gdb) info reg ebp
ebp            0xfeedb898    0xfeedb898
(gdb) x/12bx 0xfeedb898
0xfeedb898:    0xc8    0xb8    0xed    0xfe    0xce    0x83    0x04    0x08
0xfeedb8a0:    0xf4    0x01    0x00    0x00
(gdb) ni
0x007d9871 in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d9871 <setreuid+17>:    add    $0x65783,%ebx
(gdb) info reg eax ebx ecx edx
eax            0x10    16
ebx            0x7d9871    8231025
ecx            0x1    1
edx            0x1f4    500
(gdb) ni
0x007d9877 in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d9877 <setreuid+23>:    mov    %esi,0xfffffffc(%ebp)
(gdb) info reg eax ebx ecx edx
eax            0x10    16
ebx            0x83eff4    8646644
ecx            0x1    1
edx            0x1f4    500
(gdb) info reg esi
esi            0xfeedb954    -17974956
(gdb) x/16bx 0xfeedb954
0xfeedb954:    0x2f    0xdc    0xf6    0xfe    0x00    0x00    0x00    0x00
0xfeedb95c:    0x3f    0xdc    0xf6    0xfe    0x58    0xdc    0xf6    0xfe
(gdb) x/s 0xfeedb954
0xfeedb954:     "/俯"
(gdb) x/16bx $ebp-4
0xfeedb894:    0xf8    0x94    0x71    0x00    0xc8    0xb8    0xed    0xfe
0xfeedb89c:    0xce    0x83    0x04    0x08    0xf4    0x01    0x00    0x00
(gdb) x/i 0x7194f8
0x7194f8:    add    %al,(%eax)
(gdb) x/x 0x7194f8
0x7194f8:    0x00
(gdb) x/4bx 0x7194f8
0x7194f8:    0x00    0x00    0x00    0x00
(gdb) ni
0x007d987a in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d987a <setreuid+26>:    mov    0xc(%ebp),%ecx
(gdb) info reg esi
esi            0xfeedb954    -17974956
(gdb) x/16bx $ebp-4
0xfeedb894:    0x54    0xb9    0xed    0xfe    0xc8    0xb8    0xed    0xfe
0xfeedb89c:    0xce    0x83    0x04    0x08    0xf4    0x01    0x00    0x00
(gdb) x/4bx $ebp+12
0xfeedb8a4:    0xf4    0x01    0x00    0x00
(gdb) info reg eax ebx ecx edx
eax            0x10    16
ebx            0x83eff4    8646644
ecx            0x1    1
edx            0x1f4    500
(gdb) ni

ebp+12한곳의 값을 ecx로 넣어준다.

Breakpoint 3, 0x007d987d in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d987d <setreuid+29>:    xchg   %edx,%ebx
(gdb) info reg eax ebx ecx edx
eax            0x10    16
ebx            0x83eff4    8646644
ecx            0x1f4    500
edx            0x1f4    500

edx의 값을 ebx와 바꾼다.(결과적으로 아까 가져온 500이 ebx에 들어간다.)

(gdb) ni
0x007d987f in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d987f <setreuid+31>:    mov    $0xcb,%eax
(gdb) info reg eax ebx ecx edx
eax            0x10    16
ebx            0x1f4    500
ecx            0x1f4    500
edx            0x83eff4    8646644

setreuid의 시스템호출넘버인 0xcb(203)을 eax에 넣는다.
$ cat /usr/include/asm/unistd.h |grep setreuid32
#define __NR_setreuid32        203

(gdb) ni
0x007d9884 in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d9884 <setreuid+36>:    call   *%gs:0x10
(gdb) info reg eax ebx ecx edx
eax            0xcb    203
ebx            0x1f4    500
ecx            0x1f4    500
edx            0x83eff4    8646644
(gdb) info reg gs
gs             0x33    51
(gdb) si
0x007037a0 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
1: x/i $pc  0x7037a0 <_dl_sysinfo_int80>:    int    $0x80
(gdb) info reg eax ebx ecx edx
eax            0xcb    203
ebx            0x1f4    500
ecx            0x1f4    500
edx            0x83eff4    8646644
(gdb) si

_dl_sysinfo_int80함수에 진입하여 인터럽트 0x80과 ret 수행

0x007037a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
1: x/i $pc  0x7037a2 <_dl_sysinfo_int80+2>:    ret   
(gdb) si
0x007d988b in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d988b <setreuid+43>:    xchg   %edx,%ebx
(gdb) ni
0x007d988d in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d988d <setreuid+45>:    cmp    $0xfffff000,%eax
(gdb) info reg eax ebx ecx edx
eax            0x0    0
ebx            0x83eff4    8646644
ecx            0x1f4    500
edx            0x1f4    500

아까 ebx와 edx를 바꾼것을 되돌린다.
eax는 0으로 초기화시킨다.

(gdb) ni
0x007d9892 in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d9892 <setreuid+50>:    mov    %eax,%esi
(gdb) info reg eax ebx ecx edx
eax            0x0    0
ebx            0x83eff4    8646644
ecx            0x1f4    500
edx            0x1f4    500
(gdb) info reg esi
esi            0xfeedb954    -17974956
(gdb) ni
0x007d9894 in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d9894 <setreuid+52>:    ja     0x7d98d5 <setreuid+117>
(gdb) info reg esi
esi            0x0    0

esi에 0이된 eax를 옮긴다.

(gdb) ni
0x007d9896 in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d9896 <setreuid+54>:    test   %eax,%eax

eax를 서로 비교한다.(널값체크인가)

(gdb)
0x007d9898 in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d9898 <setreuid+56>:    jne    0x7d98a4 <setreuid+68>
(gdb)
0x007d989a in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d989a <setreuid+58>:    mov    0x3b98(%ebx),%eax
(gdb)
0x007d98a0 in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d98a0 <setreuid+64>:    test   %eax,%eax
(gdb)
0x007d98a2 in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d98a2 <setreuid+66>:    jne    0x7d98b0 <setreuid+80>
(gdb)
0x007d98a4 in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d98a4 <setreuid+68>:    mov    %esi,%eax
(gdb)
0x007d98a6 in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d98a6 <setreuid+70>:    mov    0xfffffff8(%ebp),%ebx
(gdb)
0x007d98a9 in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d98a9 <setreuid+73>:    mov    0xfffffffc(%ebp),%esi
(gdb)
0x007d98ac in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d98ac <setreuid+76>:    mov    %ebp,%esp
(gdb)
0x007d98ae in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d98ae <setreuid+78>:    pop    %ebp
(gdb)
0x007d98af in setreuid () from /lib/tls/libc.so.6
1: x/i $pc  0x7d98af <setreuid+79>:    ret   
(gdb)
여기까지가 setreuid()이다 반환후 메인으로 돌아간다.
0x080483ce in main ()
1: x/i $pc  0x80483ce <main+46>:    add    $0x10,%esp




결론 : setreuid 함수호출후 ebp+8, ebp+12에 리틀엔디언 방식으로 인자를 넘기면 된다.

0xf4    0x01    0x00    0x00

재미있는것은 disp/i $pc를 이용해보니까 leave같은것도 분리해서 보여준다는점ㅎㅎ



ps : system 함수는 달고나님 문서{

buffer_overflow_foundation_pub.pdf

}에서 확인해보자.