# [zer0pts CTF 2020] shredder ###### tags: `zer0pts CTF` `forensics` ## Overview We're given a core dump. Let's extract the original ELF file by binwalk or something. ``` $ binwalk -e core ``` And you'll get the binary: `2000.elf`. ## Analysis Although analysing the ELF may seem hard as every symbol is gone, recovering symbols is pretty easy. For example, assume you want to know what function `sub_8F0` is. ![](https://i.imgur.com/5VGXr8T.png) Tracing deeper by IDA, we find the function address: ![](https://i.imgur.com/rCyurtX.png) You can get the symbol in gdb. (Open `core` in gdb) ``` $ gdb -q ./_core.extracted/2000.elf core pwndbg> x/4xg 0x7FFBF0AB9DA0 0x7ffbf0ab9da0 <__bsd_signal>: 0x06773ff883ff478d 0x8b481a75fffe8348 0x7ffbf0ab9db0 <__bsd_signal+16>: 0x00c764003ac0b305 0xffc0c74800000016 ``` So, you can understand `sub_8F0` is `signal`. In this way, you'll find the remove process. ```c int sqsum(int a, int b) { return a * a + b * b; } int shred(char *filename) { int fd, i; char *buffer; struct stat st; struct timeval tv; struct timezone tz; if (stat(filename, &st)) return 1; fd = open(filename, O_RDWR); if (fd < 0) return 1; gettimeofday(&tv, &tz); srand(sqsum(tv.tv_sec, tv.tv_usec)); buffer = malloc(st.st_size); lseek(fd, 0, SEEK_SET); read(fd, buffer, st.st_size); for(i = 0; i < st.st_size; i++) { buffer[i] ^= rand() & 0xff; } lseek(fd, 0, SEEK_SET); write(fd, buffer, st.st_size); free(buffer); close(fd); if (unlink(filename) != 0) return 1; write(1, "Press ENTER to quit...", 0x16); read(0, NULL, 1); return 0; } ``` We need to recover the seed of `srand`, which may remain on the stack. One way to find this is look around the `main` stack. Since main will return to `__libc_start_main`, we can search for the return address. We know the address of `__libc_start_main_ret`: ``` pwndbg> x/16i 0x7ffbf0a9cb5c <-- near __libc_start_main 0x7ffbf0a9cb5c <__libc_start_main+172>: mov QWORD PTR [rsp+0x68],rax 0x7ffbf0a9cb61 <__libc_start_main+177>: mov rax,QWORD PTR fs:0x2f8 0x7ffbf0a9cb6a <__libc_start_main+186>: mov QWORD PTR [rsp+0x70],rax 0x7ffbf0a9cb6f <__libc_start_main+191>: lea rax,[rsp+0x20] 0x7ffbf0a9cb74 <__libc_start_main+196>: mov QWORD PTR fs:0x300,rax 0x7ffbf0a9cb7d <__libc_start_main+205>: mov rax,QWORD PTR [rip+0x3c9324] # 0x7ffbf0e65ea8 0x7ffbf0a9cb84 <__libc_start_main+212>: mov rsi,QWORD PTR [rsp+0x8] 0x7ffbf0a9cb89 <__libc_start_main+217>: mov edi,DWORD PTR [rsp+0x14] 0x7ffbf0a9cb8d <__libc_start_main+221>: mov rdx,QWORD PTR [rax] 0x7ffbf0a9cb90 <__libc_start_main+224>: mov rax,QWORD PTR [rsp+0x18] 0x7ffbf0a9cb95 <__libc_start_main+229>: call rax 0x7ffbf0a9cb97 <__libc_start_main+231>: mov edi,eax 0x7ffbf0a9cb99 <__libc_start_main+233>: call 0x7ffbf0abe120 <__GI_exit> 0x7ffbf0a9cb9e <__libc_start_main+238>: mov rax,QWORD PTR [rip+0x3ced23] # 0x7ffbf0e6b8c8 <__libc_pthread_functions+392> 0x7ffbf0a9cba5 <__libc_start_main+245>: ror rax,0x11 0x7ffbf0a9cba9 <__libc_start_main+249>: xor rax,QWORD PTR fs:0x30 pwndbg> search -p 0x7ffbf0a9cb97 warning: Unable to access 16000 bytes of target memory at 0x7ffbf0a92707, halting search. warning: Unable to access 15737 bytes of target memory at 0x7ffbf0e8f287, halting search. warning: Unable to access 15737 bytes of target memory at 0x7ffbf0e8f287, halting search. [stack] 0x7ffd8fdadfa8 0x7ffbf0a9cb97 pwndbg> x/24xg 0x7ffd8fdadf00 0x7ffd8fdadf00: 0x0000000000000001 0x000003e8000081b4 0x7ffd8fdadf10: 0x00000000000003e8 0x0000000000000000 0x7ffd8fdadf20: 0x0000000000003ca7 0x0000000000001000 0x7ffd8fdadf30: 0x0000000000000020 0x000000005e23f5d2 0x7ffd8fdadf40: 0x0000000003400ca0 0x000000005e23f5d2 0x7ffd8fdadf50: 0x0000000003400ca0 0x000000005e23f5d2 0x7ffd8fdadf60: 0x0000000003400ca0 0x0000000000000000 0x7ffd8fdadf70: 0x0000000000000000 0x0000000000000000 0x7ffd8fdadf80: 0x00007ffd8fdadfa0 0x00005635b10a3cb4 <-- return adddress of shred 0x7ffd8fdadf90: 0x00007ffd8fdae088 0x0000000200000000 0x7ffd8fdadfa0: 0x00005635b10a3cd0 0x00007ffbf0a9cb97 <-- return address of main 0x7ffd8fdadfb0: 0x0000000000000002 0x00007ffd8fdae088 pwndbg> x/32xg 0x7ffd8fdadf00 - 0x100 0x7ffd8fdade00: 0x0000000046505845 0x00000122000003cb 0x7ffd8fdade10: 0x000000000000001e 0x00007ffbf0e66c40 0x7ffd8fdade20: 0x0000000000000001 0x00005635b211a260 0x7ffd8fdade30: 0x00005635b211a250 0x00007ffbf0b13335 0x7ffd8fdade40: 0xffffffffffffffb0 0x0000000000003ca7 0x7ffd8fdade50: 0xffffffffffffffb0 0x00005635b10a3960 0x7ffd8fdade60: 0x00007ffd8fdae080 0x9a7e4d02ae2ede00 0x7ffd8fdade70: 0x0000000000000000 0x0000000000000000 0x7ffd8fdade80: 0x00007ffd8fdadf80 0x00005635b10a3960 0x7ffd8fdade90: 0x00007ffd8fdae080 0x0000000000000000 0x7ffd8fdadea0: 0x0000000000000000 0x00005635b10a3c67 0x7ffd8fdadeb0: 0x0000000000000000 0x00007ffd8fdaef38 0x7ffd8fdadec0: 0x0000000000000000 0x0000000300003ca7 0x7ffd8fdaded0: 0x00005635b211a260 0x0000000000000000 <-- address of shredded file 0x7ffd8fdadee0: 0x000000005e23f5f6 0x00000000000f17d8 0x7ffd8fdadef0: 0x0000000000000803 0x0000000000de0ce6- pwndbg> x/16xg 0x00005635b211a260 0x5635b211a260: 0x1ea4e01452991394 0x5f88f11aa7768cb6 0x5635b211a270: 0x76cf90fcba38d09d 0xd755583ddf177936 0x5635b211a280: 0xb43e63e89bb291d4 0x1bc8bf4995a781d9 0x5635b211a290: 0xa67d82ef9241c150 0x6d82e1c96eaa566c 0x5635b211a2a0: 0xb52815b2f828f7a6 0x93dc80f226fa0fd7 0x5635b211a2b0: 0xe61cf6de28313ef7 0x42c1d707b89859ce 0x5635b211a2c0: 0xc351ea537844bd31 0x5e9fbed589a1cf44 0x5635b211a2d0: 0xb3fc3c26d4dda2db 0xb92db878af3d2e82 ``` ## Solution We have everything necessary to restore the file. Let's restore the PDF file. ```python from ptrlib import * import ctypes glibc = ctypes.cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc-2.27.so') with open("../distfiles/core", "rb") as f: buf = f.read() ofs_stat = buf.index(p64(0x803)) ofs_tv = ofs_stat - 0x10 ofs_enc = buf.index(p64(0x20db1)) + 8 st_size = u64(buf[ofs_stat + 0x30:ofs_stat + 0x38]) tv_sec = u64(buf[ofs_tv:ofs_tv+8]) tv_usec = u64(buf[ofs_tv+8:ofs_tv+16]) enc = buf[ofs_enc:ofs_enc + st_size] glibc.srand(tv_sec**2 + tv_usec**2) plain = b"" for c in enc: plain += bytes([c ^ (glibc.rand() & 0xff)]) with open("restored.pdf", "wb") as f: f.write(plain) ``` You'll find the flag in the PDF.