일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Shell code
- 워게임
- system hacking
- 운영체제
- System
- 해킹
- 네트워크
- webhacking.kr
- PWN
- Spring MVC
- OS
- 정보보안기사
- webhacking
- Payload
- 정보처리기사 실기
- stack overflow
- Pwnable.kr
- Lord of BOF
- 정보보안기사 실기
- hacking
- wargame
- LOB
- Spring
- Buffer Overflow
- Spring Framework
- BOF
- 웹해킹
- SQL
- pwnable
- Operating System
- Today
- Total
DongDD's IT
[LOB] Level14 bugbear 본문
[LOB] Level14 bugbear
Problem
이번 문제에서도 giant 실행 파일과 giant.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 31 32 33 34 35 36 37 38 39 40 41 42 43 | #include <stdio.h> #include <stdlib.h> #include <unistd.h> main(int argc, char *argv[]) { char buffer[40]; FILE *fp; char *lib_addr, *execve_offset, *execve_addr; char *ret; if(argc < 2){ printf("argv error\n"); exit(0); } // gain address of execve fp = popen("/usr/bin/ldd /home/giant/assassin | /bin/grep libc | /bin/awk '{print $4}'", "r"); fgets(buffer, 255, fp); sscanf(buffer, "(%x)", &lib_addr); fclose(fp); fp = popen("/usr/bin/nm /lib/libc.so.6 | /bin/grep __execve | /bin/awk '{print $1}'", "r"); fgets(buffer, 255, fp); sscanf(buffer, "%x", &execve_offset); fclose(fp); execve_addr = lib_addr + (int)execve_offset; // end memcpy(&ret, &(argv[1][44]), 4); if(ret != execve_addr) { printf("You must use execve!\n"); exit(0); } strcpy(buffer, argv[1]); printf("%s\n", buffer); } | cs |
이번 문제의 소스 코드는 앞 문제들과는 많이 달라보였다.
40 bytes의 buffer를 생성해주고 argv를 입력받아야 한다.
그 후에 popen을 통해 파이프라인을 열어준다. fgets를 통해 연 파일에 대한 정보를 받는 것으로보아 파이프라인 실행 결과를 buffer에 저장한 후에 lib_addr이라는 변수에 저장하는 것 같았다.
awk에 대해서는 잘 모르지만 libc를 grep하는 걸로 보아 libc에 대한 시작 주소를 lib_addr에 저장하는 것 같다.
그 후에 새로운 파이프라인을 연다. 이번에는 libc.so.6에서 __execve의 offset을 가져온다. 이것을 buffer로 읽고 execve_offset으로 저장한다.
그 후 execve_addr에 lib_addr+execve_offset을 해 execve함수의 주소를 저장한다.
그 후 argv[1]의 return address가 execve_addr과 일치하는지 확인하여 일치하지 않는다면 종료시키고 아니라면 argv[1]을 buffer에 복사한다.
Solution
1. Return to Library(RTL)
먼저 execve() 함수의 주소를 알아내기 위해 gdb를 통해 main에 break point를 설정하고 execve의 주소를 알아내었다.
execve() 함수의 주소 : 0x400a9d48
그 후에 giant파일로 실행을 해보았지만 "You must use execve!"라는 메시지를 볼 수 있었다. 입력한 return address와 execve()함수의 주소가 다른 것 같았다.
여기서 이 문제점을 해결하기 위해 많은 시간이 들었다. 먼저 프로그램을 하나 작성해 입력한 값과 execve 주소를 비교해보았더니 argv에 입력한 "\x0a"가 "\x00"으로 바뀌어있는 것을 볼 수 있었다. "\0x0a"가 Line feed라 문자열로 인식하지 않는 것 같았다.
hex()등 여러 함수를 써서 시도해보았지만 다 성공하지 못했고 찾아보니 양 끝에 "(double quote)를 입력해주면 입력한 그대로의 문자열로 저장된다는 것을 알게 되었고 "(double quote)를 사용해 제대로 된 주소를 알 수 있었고 giant를 통해 실행해보니 if문을 통과하는 것을 볼 수 있었다.
이후에는 execve()는 함수는 놔두고 system() 함수를 이용하는 방법을 선택했다.
마찬가지로 gdb를 통해 main에 break point를 설정하고 system()함수의 주소를 알아냈다.
system()함수의 주소 : 0x40058ae0
그 후에 프로그램을 작성해 라이브러리 내에 있을 "/bin/sh"의 주소를 알아내었다.
"/bin/sh"의 주소 : 0x400fbff9
Payload를 작성하기 위한 memory는 위와 같다.
먼저 dummy 44 bytes를 넣어주고 if문을 통과하기 위한 execve() 함수의 주소를 넣어준다.
실제로는 execve() 함수는 if문을 통과하기 위한 것이고 사용되지 않는다.
그 후에 execve()함수가 종료됐을 때의 return address에 system()함수의 주소를 넣어준다.
그 후에 dummy(4 bytes, system() 함수 종료 시 return address)를 넣어주고 system() 함수에 사용할 인자인 "/bin/sh"의 주소를 넣어준다.
Payload = dummy(44 bytes, buffer+sfp, "A'*44) + return address1(4 bytes, execve()함수의 주소) + return address2(4 bytes, system()함수의 주소) + dummy(4 bytes, return address3, "A"*4) + system()함수의 argument1(4 bytes, "/bin/sh"의 주소)
위 Payload를 작성해 giant 파일을 실행하니 shell을 얻을 수 있었다.
************** Answer & Flag **************
1. Return to Library(RTL)
Payload = dummy(44 bytes, buffer+sfp, "A'*44) + return address1(4 bytes, execve()함수의 주소) + return address2(4 bytes, system()함수의 주소) + dummy(4 bytes, return address3, "A"*4) + system()함수의 argument1(4 bytes, "/bin/sh"의 주소)
argv[1] = "A"*44 + "\x48\x9d\x0a\x40"+"\xe0\x8a\x05\x40" + "A"*4 + "\xf9\xbf\x0f\x40"
Next ID : giant
Next PW : one step closer
'Wargame > LOB' 카테고리의 다른 글
[LOB] Level16 assassin (0) | 2018.01.31 |
---|---|
[LOB] Level15 giant (0) | 2018.01.30 |
[LOB] Level13 darkknight (0) | 2018.01.26 |
[LOB] level12 golem (0) | 2018.01.25 |
[LOB] Level11 skeleton (0) | 2018.01.24 |