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 Checksec returns:

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 ^


You must log in to answer this question.

Browse other questions tagged .