3

I'm new to security and currently referring to Robert Seacord's Secure Coding in C and C++.

In chapter 2 of the same, the author talks about arc injection, wherein he passes the flow of control in the following program from the isPasswordOK() routine to the else() {puts ("Access granted!");}; branch in main() by overwriting the Password buffer in gets() call with a tainted string: 1234567890123456j>*!

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

bool isPasswordOK(void) {
    char Password[12];

    gets(Password);
    return 0 == strcmp(Password, "goodpass");
}

int main(void) {
    bool pwStatus;

    puts("Enter Password: ");
    pwStatus = isPasswordOK();
    if (pwStatus == false) {
        puts("Access denied");
        exit(-1);
    }
    else {
        puts("Access granted!");
    }
}

Here, j = 0x6A, > = 0x10 (This is the Data Link Escape symbol), * = 0x2A and ! = 0x21

This sequence of 4 characters then corresponds to a 4-byte address, which I'm assuming is 0x6A102A21. This address, I think, points to the else line in the main() function, and we redirect control by overwriting the return address on the stack by the address of this line.

I'm trying to reproduce the same on my machine (x86-64 architecture). I've turned stack protection and randomization off, so I don't think that should be a issue. In fact, the program crashes as expected when I try to corrupt the return address. My problem is: how do I provide as an input to gets the tainted string? If I disassemble main using gdb, I get the following output:

(gdb) disassemble main
Dump of assembler code for function main:
   0x0000000000400642 <+0>: push   %rbp
   0x0000000000400643 <+1>: mov    %rsp,%rbp
   0x0000000000400646 <+4>: sub    $0x10,%rsp
   0x000000000040064a <+8>: mov    $0x40071d,%edi
   0x000000000040064f <+13>:    callq  0x4004c0 <puts@plt>
   0x0000000000400654 <+18>:    callq  0x400616 <isPasswordOK>
   0x0000000000400659 <+23>:    mov    %al,-0x1(%rbp)
   0x000000000040065c <+26>:    movzbl -0x1(%rbp),%eax
   0x0000000000400660 <+30>:    xor    $0x1,%eax
   0x0000000000400663 <+33>:    test   %al,%al
   0x0000000000400665 <+35>:    je     0x40067b <main+57>
   0x0000000000400667 <+37>:    mov    $0x40072e,%edi
   0x000000000040066c <+42>:    callq  0x4004c0 <puts@plt>
   0x0000000000400671 <+47>:    mov    $0xffffffff,%edi
   0x0000000000400676 <+52>:    callq  0x400510 <exit@plt>
   0x000000000040067b <+57>:    mov    $0x40073c,%edi
   0x0000000000400680 <+62>:    callq  0x4004c0 <puts@plt>
   0x0000000000400685 <+67>:    leaveq 
   0x0000000000400686 <+68>:    retq   
End of assembler dump.

Since I want to jump to the second puts() call, I think I need to provide 0x0000000000400680 as a part of my tainted string because this is the address of the second puts() according to the gdb disassembly.

How can I do this? In the book, the address was of length 8, but here I have one of length 16. Also, there is no ASCII representation for 0x80, so what am I supposed to provide as an input to gets? Basically, what I'm asking for are the characters that I should provide at ?:

1234567890123456????

1 Answer 1

1

There are two things you should consider in this piece of code: The first one is the type of the variable pwStatus, the second one is the value of the strcmp return address. The goal is to overwrite the strcmp return address to make the pwStatus variable to be always true, because of pwStatus variable could only be true or false; So, if the ASCII code of one character of the string buffer passed to the strcmp function overwrites the pwStatus variable to a true value, the flaw of the script code is managed to grant you the access. If the password is only 8 char, why don't you use strncmp instead of strcmp on a 12 or more char buffer ?

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .