I've read that to make a successful return-to-libc attack, the attacker should store the address of the command (for example /bin/sh
) in the stack exactly after the return address of the system
function (for example). This way the system()
function reads that address as its parameter and executes that command. But now after disassembling a program which calls system()
I noticed that it doesn't use the stack to get the address of that string ("/bin/sh"
). Instead the address is stored in the EDI or RDI registers. As long as the attacker can't access the registers how is it possible to perform such attack?
Here is a simple example:
int main(int argc,char **argv){
system("id");
return 0;
}
And the disassembled one:
push %rbp
mov %rsp,%rbp
sub $0x10,%rsp
mov %edi,-0x4(%rbp)
mov %rsi,-0x10(%rbp)
mov $0x4005dc,%edi #Here the address of string is copied to EDI
callq 0x4003e0 <system@plt>
mov $0x0,%eax
leaveq
retq
system()
.