일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- function scope
- 개인정보안전성
- 한국정보보호산업협회
- 마감임박
- 곱셈 암호
- 개인정보보호
- 호이스팅
- 개인정보보호위원회
- package-lock.json
- pwnable.tw
- 확장 유클리드 알고리즘
- 한국산업인력공단
- 무료교육
- 가명정보처리
- 웹 프레임워크
- 덧셈 암호
- 개인정보보호교육
- 한국정보보호산업협회기자단
- package.json
- 모듈러 연산
- 동적타이핑
- 유클리드_알고리즘
- Writeup
- 국가인적자원개발컨소시엄
- 포너블
- 백엔드입문
- arrow function
- 백엔드
- 디오판투스 알고리즘
- node.js
- Today
- Total
짱짱해커가 되고 싶은 나
[start] write up 본문
파일 분석
start 파일을 실행해보면 다음과 같이 무언가를 입력받고 종료된다.
file과 checksec로 봤을 때도 특별히 신경써야 하는 부분은 보이지 않는다. (nc 서버에는 ASLR 걸려있음ㅜ)
not stripped이기 때문에 objdump로 어셈블리어를 우선 확인해본다.
_start함수와 _exit함수가 있는 것을 확인할 수 있다.
여기서 int 명령어는 처음 보는 명령어였는데 int는 x86 CPU를 위한 어셈브리어로 인터럽트를 발생시킨다고 한다.
예를 들어 int 21h는 0x21(33)의 인터럽트를 생성하는데 이는 인터럽트 테이블의 34번째 벡터를 가리키고 이 함수를 실행시킨다.
여기서 int를 사용하는 부분을 보면 모두 0x80이다.
검색해보니 int 0x80은 시스템 콜을 의미한다고 한다. 그리고 eax에 저장된 함수를 호출한다고 한다.
_start에서 0x804808f의 int는 0x4번, 0x8048097의 int는 0x3번이 al에 저장되어 있다.
시스템 콜 번호표를 보고 확인해보니 0x4는 sys_write, 0x3은 sys_read 였다.
즉 첫번째로 wirte 함수를 호출하고 두번째로 read 함수를 호출하는 것이다.
아마도 write함수는 처음 파일이 실행되고 나오는 문구일테고 read함수는 우리가 입력하는 부분일 것이다.
또, read함수위에 0x3c는 입력받을 수 있는 숫자에 해당할 것이다.
_exit의 주소인 0x804809d가 _start에서 처음에 push하는 것을 보아 add 0x14로 _exit를 남겨놓고 ret으로 호출하는 것을 확인할 수 있다.
스택의 크기는 0x14(20)인데 입력은 0x3c(60)만큼 받기 때문에 _exit주소가 저장된 스택을 read를 통해 덮을 수 있다.
read(fd, buf, 0x3c)이기 때문에 이 buf의 주소를 넣으면 된다.
한 번 실제로 eip가 덮이는지 gdb로 확인해보자.
eip가 AAAA로 덮인 것을 확인할 수 있다.
Exploit
1. write를 통해 stack 주소 leak하기
2. read를 통해 쉘코드로 ret 덮기
(우리가 leak한 스택 주소에서 +0x14만큼하고 그 위치에 쉘코드를 넣으면 된다.)
자! 일단, 우리는 stack주소를 leak해야하는데 write에서 ecx에 esp 값(stack 주소)를 넣는다. 우리는 이 값을 출력해야하기 때문에 _exit의 주소가 들어있던 스택을 mov %esp %ecx의 주소로 덮는다.
그렇게 되면 read가 호출되고 입력을 받아서 값이 덮어지게 될것이다. 그 다음 원래였다면 exit를 호출했겠지만 주소가 wirte를 하기 전으로 돌아갔으니까 다시 write를 실행하는데 이때 해당 주소(ecx)에 있는 값은 esp이기 때문에 스택 주소를 출력한다.
이렇게 스택 주소를 얻었다면 다시 read함수를 통해 쉘코드로 ret를 덮을 것이다.
원래는 _exit가 저장되어있던 위치에 해당 스택의 주소(read의 버퍼 주소)를 넣고 그 곳에 셀을 작성한다.
그러면 read가 끝나고 셀이 저장된 스택의 주소를 실행시키기 때문에 셀이 실행된다.
근데 나는 이제 여기서 좀 막혔다.
내가 생각할때는 "A"*0x14 + "esp+0x14 주소" + "셀코드"를 했으면 이때 셀코드의 주소는 esp+0x18이라고 생각했다.
이런식으로 덮힐 거라고 예측했기 때문이다.
gdb로 한번 어떻게 되는지 봤다.
BBBB즉 셀코드가 입력되는 곳이 esp에 저장되어 있었다. 띠용???
아 저 덮힌 스택에는 원래 esp가 들어있는데 esp의 값이 덮힌 것이다. 그래서 뭐..
아~ 아니다. 지금 esp는 esp+0x14를 한 상태다! 그런데 그 esp가 BBBB를 가리키고 있다는 것은 esp+0x14위치에 셀코드가 들어간다는 것을 의미한다. 근데 왜 이걸 나는 이해하지 못하고 있지? ㅠ 우울하넹.............
나중에 알게되면 추가로 작성..하지........... 예상은 저기서 esp+0x14로 이동을 했고 pop 이니까 저게 빠져서 그 위가 esp+0x14가 된건가?
다음과 같이 exploit 해보면 flag를 획득할 수 있다.
FLAG{Pwn4bl3_tW_1s_y0ur_st4rt}