struct auth { char name[32]; int auth; }; struct auth *auth; char *service; int main(int argc, char **argv) { char line[128]; while(1) { printf("[ auth = %p, service = %p ]\n", auth, service); if(fgets(line, sizeof(line), stdin) == NULL) break; if(strncmp(line, "auth ", 5) == 0) { auth = malloc(sizeof(auth)); memset(auth, 0, sizeof(auth)); if(strlen(line + 5) < 31) { strcpy(auth->name, line + 5); } } if(strncmp(line, "reset", 5) == 0) { free(auth); } if(strncmp(line, "service", 6) == 0) { service = strdup(line + 7); } if(strncmp(line, "login", 5) == 0) { if(auth->auth) { printf("you have logged in already!\n"); } else { printf("please enter your password\n"); } } } }
출처: http://liveoverflow.com/binary_hacking/protostar/heap2.html
1. 문제 해결
1-1. gdb ./heap2
disas main
힙이 할당된 이후에 포인터를 알아야 하므로 브레이크 포인트 malloc이 할당된 시점 다음 라인에 브레이크 포인트를 건다.
b *main+127
strdup 이후
b *main+297 (eax가 heap에 대한 포인터)
if문 이후
b *main+346 (test 있는 곳이 if)
r
AAAA
eax는 malloc 할당 이후에 주소값을 가지고 있다.
그러므로
x/40wx 0x804c818 - 0x8
size 영역에 0x11이 할당된 것을 알 수 있다.
1-3. conti
conti 이후 AAAA가 데이터영역에 들어가 있다.
1-4. reset
reset을 하여도 포인터는 사라지지 않는다.
하지만 데이터 영역은 지워진다.
conti 하여
service를 통해 heap을 채워나가자!
기존 auth가 있던 곳에 재할당됨을 알 수 있다.
구조체 auth는 아래와 같이 32 바이트이다.
한 라인 당(heap) 16바이트이므로 32 바이트를 초과하려면 3개를 채워야한다.
struct auth { char name[32]; int auth; };
1-5. 결론
성공~
참고 자료: https://www.inflearn.com/course/%ED%94%84%EB%A1%9C%ED%86%A0%EC%8A%A4%ED%83%80/
피드백 환영입니다!
'프로토스타' 카테고리의 다른 글
[프로토스타] (번외) UAF (0) | 2019.01.30 |
---|---|
[프로토스타] heap1 (0) | 2019.01.24 |
[프로토스타] heap0 (0) | 2019.01.23 |
[프로토스타] format4 (0) | 2019.01.23 |
[프로토스타] format3 (0) | 2019.01.23 |