Ghost_Diary
Problem
Solution
Stage 1: Analysis
$ ldd ghostdiary linux-vdso.so.1 (0x00007ffc22b9f000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f860ee47000) /lib64/ld-linux-x86-64.so.2 (0x00007f860f43b000) $ strings /lib/x86_64-linux-gnu/libc.so.6 | grep GNU GNU C Library (Ubuntu GLIBC 2.27-3ubuntu1) stable release version 2.27. Compiled by GNU CC version 7.3.0. $ checksec ghostdiary Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled-=-=-=[[Ghost Diary]]=-=-=- 1. New page in diary 2. Talk with ghost 3. Listen to ghost 4. Burn the page 5. Go to sleep > 1 1. Write on one side? 2. Write on both sides? > 1 size: 1 page #0 1. New page in diary 2. Talk with ghost 3. Listen to ghost 4. Burn the page 5. Go to sleep > 2 Page: 1 Content: 1. New page in diary 2. Talk with ghost 3. Listen to ghost 4. Burn the page 5. Go to sleep > 4 Page: 1 1. New page in diary 2. Talk with ghost 3. Listen to ghost 4. Burn the page 5. Go to sleep > 5 bye human!void FUN_00100b0b(void) { void *pvVar1; long in_FS_OFFSET; uint local_1c; int local_18; uint local_14; long local_10; local_10 = *(long *)(in_FS_OFFSET + 0x28); local_14 = 0; while ((local_14 < 0x14 && (*(long *)(&DAT_00302060 + (ulong)local_14 * 0x10) != 0))) { local_14 = local_14 + 1; } if (local_14 == 0x14) { puts("Buy new book"); } else { puts("1. Write on one side?"); puts("2. Write on both sides?"); while( true ) { while( true ) { while( true ) { printf("> "); __isoc99_scanf(&DAT_0010119d,&local_18); if (local_18 != 1) break; printf("size: "); __isoc99_scanf(&DAT_0010119d,&local_1c); if (local_1c < 0xf1) goto LAB_00100c64; puts("too big to fit in a page"); } if (local_18 != 2) goto LAB_00100ce5; printf("size: "); __isoc99_scanf(&DAT_0010119d,&local_1c); if (0x10f < local_1c) break; puts("don\'t waste pages -_-"); } if (local_1c < 0x1e1) break; puts("can you not write that much?"); } LAB_00100c64: pvVar1 = malloc((ulong)local_1c); *(void **)(&DAT_00302060 + (ulong)local_14 * 0x10) = pvVar1; if (*(long *)(&DAT_00302060 + (ulong)local_14 * 0x10) == 0) { puts("oh noooooooo!! :("); } else { *(uint *)(&DAT_00302068 + (ulong)local_14 * 0x10) = local_1c; printf("page #%d\n",(ulong)local_14); } } LAB_00100ce5: if (local_10 == *(long *)(in_FS_OFFSET + 0x28)) { return; } /* WARNING: Subroutine does not return */ __stack_chk_fail(); }void FUN_00100cfb(void) { long in_FS_OFFSET; uint local_14; long local_10; local_10 = *(long *)(in_FS_OFFSET + 0x28); printf("Page: "); __isoc99_scanf(&DAT_0010119d,&local_14); printf("Content: "); if ((local_14 < 0x14) && (*(long *)(&DAT_00302060 + (ulong)local_14 * 0x10) != 0)) { FUN_00100a5a(*(undefined8 *)(&DAT_00302060 + (ulong)local_14 * 0x10), (ulong)*(uint *)(&DAT_00302068 + (ulong)local_14 * 0x10), (ulong)*(uint *)(&DAT_00302068 + (ulong)local_14 * 0x10)); } if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) { /* WARNING: Subroutine does not return */ __stack_chk_fail(); } return; }void FUN_00100a5a(long param_1,uint param_2) { ssize_t sVar1; long in_FS_OFFSET; char local_15; uint local_14; long local_10; local_10 = *(long *)(in_FS_OFFSET + 0x28); local_14 = 0; if (param_2 != 0) { while (local_14 != param_2) { sVar1 = read(0,&local_15,1); if (sVar1 != 1) { puts("read error"); /* WARNING: Subroutine does not return */ exit(-1); } if (local_15 == '\n') break; *(char *)((ulong)local_14 + param_1) = local_15; local_14 = local_14 + 1; } *(undefined *)(param_1 + (ulong)local_14) = 0; } if (local_10 == *(long *)(in_FS_OFFSET + 0x28)) { return; } /* WARNING: Subroutine does not return */ __stack_chk_fail(); }void FUN_00100dbe(void) { long in_FS_OFFSET; uint local_14; long local_10; local_10 = *(long *)(in_FS_OFFSET + 0x28); printf("Page: "); __isoc99_scanf(&DAT_0010119d,&local_14); printf("Content: "); if ((local_14 < 0x14) && (*(long *)(&DAT_00302060 + (ulong)local_14 * 0x10) != 0)) { puts(*(char **)(&DAT_00302060 + (ulong)local_14 * 0x10)); } if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) { /* WARNING: Subroutine does not return */ __stack_chk_fail(); } return; }void FUN_00100e69(void) { long in_FS_OFFSET; uint local_14; long local_10; local_10 = *(long *)(in_FS_OFFSET + 0x28); printf("Page: "); __isoc99_scanf(&DAT_0010119d,&local_14); if ((local_14 < 0x14) && (*(long *)(&DAT_00302060 + (ulong)local_14 * 0x10) != 0)) { free(*(void **)(&DAT_00302060 + (ulong)local_14 * 0x10)); *(undefined8 *)(&DAT_00302060 + (ulong)local_14 * 0x10) = 0; } if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) { /* WARNING: Subroutine does not return */ __stack_chk_fail(); } return; }void FUN_00100e69(void) { long in_FS_OFFSET; uint local_14; long local_10; local_10 = *(long *)(in_FS_OFFSET + 0x28); printf("Page: "); __isoc99_scanf(&DAT_0010119d,&local_14); if ((local_14 < 0x14) && (*(long *)(&DAT_00302060 + (ulong)local_14 * 0x10) != 0)) { free(*(void **)(&DAT_00302060 + (ulong)local_14 * 0x10)); *(undefined8 *)(&DAT_00302060 + (ulong)local_14 * 0x10) = 0; } if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) { /* WARNING: Subroutine does not return */ __stack_chk_fail(); } return; }
Stage 2: Leak Libc (using a poison null byte)
Stage 3: Overlap chunks and overwrite an address
Flag
Last updated