Last active
August 29, 2015 14:15
-
-
Save ysangkok/31008718adced6608669 to your computer and use it in GitHub Desktop.
longjmp over different process invocations
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <setjmp.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdint.h> | |
#include <string.h> | |
static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', | |
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', | |
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', | |
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', | |
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', | |
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', | |
'w', 'x', 'y', 'z', '0', '1', '2', '3', | |
'4', '5', '6', '7', '8', '9', '+', '/'}; | |
static char *decoding_table = NULL; | |
static unsigned int mod_table[] = {0, 2, 1}; | |
char *base64_encode(const unsigned char * , size_t , size_t * ); | |
char *base64_encode(const unsigned char *data, size_t input_length, size_t *output_length) { | |
*output_length = 4 * ((input_length + 2) / 3); | |
char *encoded_data = malloc(*output_length); | |
if (encoded_data == NULL) return NULL; | |
for (unsigned int i = 0, j = 0; i < input_length;) { | |
uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0; | |
uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0; | |
uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0; | |
uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c; | |
encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F]; | |
encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F]; | |
encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F]; | |
encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F]; | |
} | |
for (unsigned int i = 0; i < mod_table[input_length % 3]; i++) | |
encoded_data[*output_length - 1 - i] = '='; | |
return encoded_data; | |
} | |
void build_decoding_table(void); | |
void build_decoding_table() { | |
decoding_table = malloc(256); | |
for (size_t i = 0; i < 64; i++) | |
decoding_table[(unsigned char) encoding_table[i]] = (char) i; | |
} | |
unsigned char *base64_decode(const char * , size_t , size_t * ); | |
unsigned char *base64_decode(const char *data, size_t input_length, size_t *output_length) { | |
if (decoding_table == NULL) build_decoding_table(); | |
if (input_length % 4 != 0) return NULL; | |
*output_length = input_length / 4 * 3; | |
if (data[input_length - 1] == '=') (*output_length)--; | |
if (data[input_length - 2] == '=') (*output_length)--; | |
unsigned char *decoded_data = malloc(*output_length); | |
if (decoded_data == NULL) return NULL; | |
for (unsigned int i = 0, j = 0; i < input_length;) { | |
uint32_t sextet_a = data[i] == '=' ? 0 & i++ : (unsigned) decoding_table[data[i++]]; | |
uint32_t sextet_b = data[i] == '=' ? 0 & i++ : (unsigned) decoding_table[data[i++]]; | |
uint32_t sextet_c = data[i] == '=' ? 0 & i++ : (unsigned) decoding_table[data[i++]]; | |
uint32_t sextet_d = data[i] == '=' ? 0 & i++ : (unsigned) decoding_table[data[i++]]; | |
uint32_t triple = (sextet_a << 3 * 6) | |
+ (sextet_b << 2 * 6) | |
+ (sextet_c << 1 * 6) | |
+ (sextet_d << 0 * 6); | |
if (j < *output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF; | |
if (j < *output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF; | |
if (j < *output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF; | |
} | |
return decoded_data; | |
} | |
void base64_cleanup(void); | |
void base64_cleanup() { | |
free(decoding_table); | |
} | |
int main(void) { | |
size_t output_length; | |
const char* q = getenv("QUERY_STRING"); | |
freopen("/dev/stdout", "w", stderr); | |
printf("Content-Type: text/html\n\n<div style='white-space:pre'>"); | |
fflush(stdout); | |
if (q && strlen(q)) { | |
jmp_buf dest; | |
build_decoding_table(); | |
unsigned char* buf = base64_decode((void*) q, strlen(q), &output_length); | |
puts(q); | |
fflush(stdout); | |
memcpy(dest, buf, output_length); | |
longjmp(dest, 1); | |
} else { | |
jmp_buf link1; | |
if (!setjmp(link1)) { | |
const char* b64 = base64_encode((unsigned char*) &link1, sizeof(jmp_buf), &output_length); | |
printf("<a href='a.out?"); | |
fwrite(b64, sizeof(char), output_length, stdout); | |
//printf("%.*s", output_length, b64); | |
printf("'>"); | |
fwrite(b64, sizeof(char), output_length, stdout); | |
//printf("%.*s", output_length, b64); | |
printf("</a>"); | |
free((void*) b64); | |
} else { | |
printf("you pressed the link\n"); | |
} | |
} | |
base64_cleanup(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment