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){
    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
  • You're probably running into a linker optimisation. – Polynomial Mar 20 '15 at 10:22
  • At first I run the program under linux. but that thread is talking about MSDN as microsoft. second in the situation I explained situation is it possible to perform return-to-lib-c attack or not? – user2808671 Mar 20 '15 at 13:48
  • The linker optimisation mentioned there isn't exclusive to Microsoft toolchains. Actually - can you post the disassembly that you've seen? It may be a direct syscall rather than an actual call to system(). – Polynomial Mar 20 '15 at 13:55
  • @Polynomial I updated the question with the codes. Please review – user2808671 Mar 20 '15 at 14:02
  • Ah, it's a PLT. – Polynomial Mar 20 '15 at 14:09

What you're looking at is a PLT, which is a way of doing late-bound library imports. The "calling convention" of PLTs isn't standard, but the toolchain usually uses register-based parameter passing for performance, which is why you're seeing edi as the address of the string. The call will go to a stub in the Global Offset Table (GOT) which then calls into the library function.

The answer is yes, you can exploit this with a ret2libc, but not a standard one. You'll need to use a ret-to-plt technique instead, which is described in this paper (PDF). The point is that you use ROP gadgets to massage the registers into containing the right values, which can then call into the PLT.

  • Thank You. Apparently it's more complicated than it seemed at beginning. – user2808671 Mar 20 '15 at 14:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.