I've got a pretty tricky flag that I have been beating my head against for a while now and would love an explanation for how something like this would be possible. I have a program that when run, seemingly immediately cancels itself. File returns:
file.exe: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=60e0255339eac5de5c216aed54d2b55cfa3d7dda, not stripped and
Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
As you can see, it has a canary enabled which is a problem considering the program accepts no input after running it. Usually I would either brute force the canary or grab it when it leaks then pass it to be input, but I don't see how it's possible to grab the leak and then put it in as an arg after the fact - but since the canary changes on execution you clearly have to do that. Everything looks like you'd expect when disassembling it in ghidra - except for the no input part. Here's the main func:
0x000000000040060e <+0>: push rbp 0x000000000040060f <+1>: mov rbp,rsp 0x0000000000400612 <+4>: sub rsp,0x10 0x0000000000400616 <+8>: mov DWORD PTR [rbp-0x4],edi 0x0000000000400619 <+11>: mov QWORD PTR [rbp-0x10],rsi 0x000000000040061d <+15>: mov rax,QWORD PTR [rbp-0x10] 0x0000000000400621 <+19>: add rax,0x8 0x0000000000400625 <+23>: mov rax,QWORD PTR [rax] 0x0000000000400628 <+26>: mov rdi,rax 0x000000000040062b <+29>: call 0x4005a7 <evil> 0x0000000000400630 <+34>: mov eax,0x0 0x0000000000400635 <+39>: leave 0x0000000000400636 <+40>: ret
and here's the evil func:
0x00000000004005a7 <+0>: push rbp 0x00000000004005a8 <+1>: mov rbp,rsp 0x00000000004005ab <+4>: sub rsp,0x70 0x00000000004005af <+8>: mov QWORD PTR [rbp-0x68],rdi 0x00000000004005b3 <+12>: mov rax,QWORD PTR fs:0x28 0x00000000004005bc <+21>: mov QWORD PTR [rbp-0x8],rax 0x00000000004005c0 <+25>: xor eax,eax 0x00000000004005c2 <+27>: mov DWORD PTR [rbp-0x54],0x0 0x00000000004005c9 <+34>: mov rdx,QWORD PTR [rbp-0x68] 0x00000000004005cd <+38>: lea rax,[rbp-0x50] 0x00000000004005d1 <+42>: mov rsi,rdx 0x00000000004005d4 <+45>: mov rdi,rax 0x00000000004005d7 <+48>: mov eax,0x0 0x00000000004005dc <+53>: call 0x4004b0 <sprintf@plt> 0x00000000004005e1 <+58>: mov eax,DWORD PTR [rbp-0x54] 0x00000000004005e4 <+61>: cmp eax,0xdeadbeef 0x00000000004005e9 <+66>: jne 0x4005f7 <evil+80> 0x00000000004005eb <+68>: lea rdi,[rip+0xd6] # 0x4006c8 0x00000000004005f2 <+75>: call 0x400490 <puts@plt> 0x00000000004005f7 <+80>: nop 0x00000000004005f8 <+81>: mov rax,QWORD PTR [rbp-0x8] 0x00000000004005fc <+85>: xor rax,QWORD PTR fs:0x28 0x0000000000400605 <+94>: je 0x40060c <evil+101> 0x0000000000400607 <+96>: call 0x4004a0 <__stack_chk_fail@plt> 0x000000000040060c <+101>: leave 0x000000000040060d <+102>: ret
there's clearly some pretty suspect stuff going on here, but I can't seem to make heads or tails of it.
edit: I've found this video which is exactly this problem but with a buffer of 72 and I can not for the life of me figure out how to get this to work. Could someone explain to me where he gets the numbers from in his fuzzing script?
edit2: Here's an asciinema recording of me replicating that video ^